@@ -9,6 +9,7 @@ use quick_xml::events::Event;
9
9
use yaml_rust:: YamlLoader ;
10
10
use yaml_rust:: yaml:: Yaml ;
11
11
use regex:: Regex ;
12
+ use lazy_static:: lazy_static;
12
13
13
14
struct Table < ' a > {
14
15
path : String ,
@@ -56,7 +57,8 @@ struct Column<'a> {
56
57
find : Option < & ' a str > ,
57
58
replace : Option < & ' a str > ,
58
59
consol : Option < & ' a str > ,
59
- subtable : Option < Table < ' a > >
60
+ subtable : Option < Table < ' a > > ,
61
+ bbox : Option < BBox >
60
62
}
61
63
impl std:: fmt:: Debug for Column < ' _ > {
62
64
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
@@ -80,7 +82,24 @@ impl Geometry {
80
82
}
81
83
}
82
84
83
- fn gml_to_ewkb ( cell : & RefCell < String > , coll : & [ Geometry ] ) {
85
+ struct BBox {
86
+ minx : f64 ,
87
+ miny : f64 ,
88
+ maxx : f64 ,
89
+ maxy : f64
90
+ }
91
+ impl BBox {
92
+ fn from ( str : & str ) -> Option < BBox > {
93
+ lazy_static ! {
94
+ static ref RE : Regex = Regex :: new( r"^([0-9.]+),([0-9.]+) ([0-9.]+),([0-9.]+)$" ) . unwrap( ) ;
95
+ }
96
+ RE . captures ( str) . map ( |caps|
97
+ BBox { minx : caps[ 1 ] . parse ( ) . unwrap ( ) , miny : caps[ 2 ] . parse ( ) . unwrap ( ) , maxx : caps[ 3 ] . parse ( ) . unwrap ( ) , maxy : caps[ 4 ] . parse ( ) . unwrap ( ) }
98
+ )
99
+ }
100
+ }
101
+
102
+ fn gml_to_ewkb ( cell : & RefCell < String > , coll : & [ Geometry ] , bbox : Option < & BBox > ) -> bool {
84
103
let mut ewkb: Vec < u8 > = vec ! [ ] ;
85
104
86
105
if coll. len ( ) > 1 {
@@ -100,11 +119,39 @@ fn gml_to_ewkb(cell: &RefCell<String>, coll: &[Geometry]) {
100
119
} ;
101
120
ewkb. extend_from_slice ( & [ 1 , geom. gtype , 0 , 0 , code] ) ;
102
121
ewkb. extend_from_slice ( & geom. srid . to_le_bytes ( ) ) ;
103
- if geom. gtype == 3 { ewkb. extend_from_slice ( & ( geom. rings . len ( ) as u32 ) . to_le_bytes ( ) ) ; } // Only polygons have multiple rings
104
- for ring in geom. rings . iter ( ) {
105
- if geom. gtype != 1 { ewkb. extend_from_slice ( & ( ( ring. len ( ) as u32 ) /geom. dims as u32 ) . to_le_bytes ( ) ) ; } // Points don't have multiple vertices
106
- for pos in ring. iter ( ) {
107
- ewkb. extend_from_slice ( & pos. to_le_bytes ( ) ) ;
122
+ if geom. gtype == 3 { ewkb. extend_from_slice ( & ( geom. rings . len ( ) as u32 ) . to_le_bytes ( ) ) ; } // Only polygons can have multiple rings
123
+ if let Some ( bbox) = bbox {
124
+ let mut overlap = false ;
125
+ let mut overlapx = false ;
126
+ for ring in geom. rings . iter ( ) {
127
+ if geom. gtype != 1 { ewkb. extend_from_slice ( & ( ( ring. len ( ) as u32 ) /geom. dims as u32 ) . to_le_bytes ( ) ) ; } // Points don't have multiple vertices
128
+ for ( i, pos) in ring. iter ( ) . enumerate ( ) {
129
+ if overlap == true { }
130
+ else if geom. dims == 2 {
131
+ if i%2 == 0 {
132
+ overlapx = false ;
133
+ if * pos >= bbox. minx && * pos <= bbox. maxx { overlapx = true ; }
134
+ }
135
+ else if overlapx && * pos < bbox. miny && * pos > bbox. maxy { overlap = true ; }
136
+ }
137
+ else { // geom.dims == 3
138
+ if i%3 == 0 {
139
+ overlapx = false ;
140
+ if * pos >= bbox. minx && * pos <= bbox. maxx { overlapx = true ; }
141
+ }
142
+ else if overlapx && i%3 == 1 && ( * pos >= bbox. miny && * pos <= bbox. maxy ) { overlap = true ; }
143
+ }
144
+ ewkb. extend_from_slice ( & pos. to_le_bytes ( ) ) ;
145
+ }
146
+ }
147
+ if overlap == false { return false ; }
148
+ }
149
+ else {
150
+ for ring in geom. rings . iter ( ) {
151
+ if geom. gtype != 1 { ewkb. extend_from_slice ( & ( ( ring. len ( ) as u32 ) /geom. dims as u32 ) . to_le_bytes ( ) ) ; } // Points don't have multiple vertices
152
+ for pos in ring. iter ( ) {
153
+ ewkb. extend_from_slice ( & pos. to_le_bytes ( ) ) ;
154
+ }
108
155
}
109
156
}
110
157
}
@@ -113,6 +160,7 @@ fn gml_to_ewkb(cell: &RefCell<String>, coll: &[Geometry]) {
113
160
for byte in ewkb. iter ( ) {
114
161
value. push_str ( & format ! ( "{:02X}" , byte) ) ;
115
162
}
163
+ true
116
164
}
117
165
118
166
fn add_table < ' a > ( rowpath : & str , outfile : Option < & str > , filemode : & str , skip : Option < & ' a str > , colspec : & ' a [ Yaml ] ) -> Table < ' a > {
@@ -137,6 +185,7 @@ fn add_table<'a>(rowpath: &str, outfile: Option<&str>, filemode: &str, skip: Opt
137
185
let find = col[ "find" ] . as_str ( ) ;
138
186
let replace = col[ "repl" ] . as_str ( ) ;
139
187
let consol = col[ "cons" ] . as_str ( ) ;
188
+ let bbox = col[ "bbox" ] . as_str ( ) . and_then ( |str| BBox :: from ( str) ) ;
140
189
141
190
if convert. is_some ( ) && !vec ! ( "xml-to-text" , "gml-to-ewkb" ) . contains ( & convert. unwrap ( ) ) {
142
191
panic ! ( "Option 'convert' contains invalid value {}" , convert. unwrap( ) ) ;
@@ -152,8 +201,11 @@ fn add_table<'a>(rowpath: &str, outfile: Option<&str>, filemode: &str, skip: Opt
152
201
eprintln ! ( "Notice: when using filtering (incl/excl) and consolidation on a single column, the filter is checked at each phase of consolidation separately" ) ;
153
202
}
154
203
}
204
+ if bbox. is_some ( ) && ( convert. is_none ( ) || convert. unwrap ( ) != "gml-to-ewkb" ) {
205
+ eprintln ! ( "Warning: the bbox option has no function without conversion type 'gml-to-ekwb'" ) ;
206
+ }
155
207
156
- let column = Column { name : name. to_string ( ) , path, value : RefCell :: new ( String :: new ( ) ) , attr, hide, include, exclude, convert, find, replace, consol, subtable } ;
208
+ let column = Column { name : name. to_string ( ) , path, value : RefCell :: new ( String :: new ( ) ) , attr, hide, include, exclude, convert, find, replace, consol, subtable, bbox } ;
157
209
table. columns . push ( column) ;
158
210
}
159
211
table
@@ -447,7 +499,10 @@ fn main() -> std::io::Result<()> {
447
499
for i in 0 ..table. columns . len ( ) {
448
500
if path == table. columns [ i] . path {
449
501
gmltoewkb = false ;
450
- gml_to_ewkb ( & table. columns [ i] . value , & gmlcoll) ;
502
+ if !gml_to_ewkb ( & table. columns [ i] . value , & gmlcoll, table. columns [ i] . bbox . as_ref ( ) ) {
503
+ filtered = true ;
504
+ table. clear_columns ( ) ;
505
+ }
451
506
gmlcoll. clear ( ) ;
452
507
break ;
453
508
}
0 commit comments