@@ -29,11 +29,29 @@ pub struct Polygon {
29
29
pub rings : Vec < LineString > ,
30
30
}
31
31
32
+ #[ derive( PartialEq , Clone , Debug ) ]
33
+ pub struct MultiPoint {
34
+ pub points : Vec < Point > ,
35
+ pub ids : Option < Vec < u64 > > ,
36
+ }
37
+
38
+ #[ derive( PartialEq , Clone , Debug ) ]
39
+ pub struct MultiLineString {
40
+ pub lines : Vec < LineString > ,
41
+ pub ids : Option < Vec < u64 > > ,
42
+ }
43
+
44
+ #[ derive( PartialEq , Clone , Debug ) ]
45
+ pub struct MultiPolygon {
46
+ pub polygons : Vec < Polygon > ,
47
+ pub ids : Option < Vec < u64 > > ,
48
+ }
49
+
32
50
#[ derive( Default , Debug ) ]
33
51
pub struct TwkbInfo {
34
52
geom_type : u8 ,
35
53
precision : i8 ,
36
- has_id_list : bool ,
54
+ has_idlist : bool ,
37
55
is_empty_geom : bool ,
38
56
size : Option < u64 > ,
39
57
has_z : bool ,
@@ -57,7 +75,7 @@ pub trait TwkbGeom: fmt::Debug + Sized {
57
75
let metadata_header = try!( raw. read_u8 ( ) ) ;
58
76
let has_bbox = ( metadata_header & 0b0001 ) != 0 ;
59
77
let has_size_attribute = ( metadata_header & 0b0010 ) != 0 ;
60
- twkb_info. has_id_list = ( metadata_header & 0b0100 ) != 0 ;
78
+ twkb_info. has_idlist = ( metadata_header & 0b0100 ) != 0 ;
61
79
let has_ext_prec_info = ( metadata_header & 0b1000 ) != 0 ;
62
80
twkb_info. is_empty_geom = ( metadata_header & 0b10000 ) != 0 ;
63
81
if has_ext_prec_info {
@@ -89,7 +107,7 @@ pub trait TwkbGeom: fmt::Debug + Sized {
89
107
90
108
fn read_twkb_body < R : Read > ( raw : & mut R , twkb_info : & TwkbInfo ) -> Result < Self , Error > ;
91
109
92
- fn read_point < R : Read > ( raw : & mut R , twkb_info : & TwkbInfo , x : f64 , y : f64 , z : Option < f64 > , m : Option < f64 > )
110
+ fn read_relative_point < R : Read > ( raw : & mut R , twkb_info : & TwkbInfo , x : f64 , y : f64 , z : Option < f64 > , m : Option < f64 > )
93
111
-> Result < ( f64 , f64 , Option < f64 > , Option < f64 > ) , Error >
94
112
{
95
113
let x2 = x + try!( read_varint64_as_f64 ( raw, twkb_info. precision ) ) ;
@@ -108,6 +126,17 @@ pub trait TwkbGeom: fmt::Debug + Sized {
108
126
} ;
109
127
Ok ( ( x2, y2, z2, m2) )
110
128
}
129
+
130
+ fn read_idlist < R : Read > ( raw : & mut R , size : usize ) -> Result < Vec < u64 > , Error >
131
+ {
132
+ let mut idlist = Vec :: new ( ) ;
133
+ idlist. reserve ( size) ;
134
+ for _ in 0 ..size {
135
+ let id = try!( read_raw_varint64 ( raw) ) ;
136
+ idlist. push ( id) ;
137
+ }
138
+ Ok ( idlist)
139
+ }
111
140
}
112
141
113
142
// --- helper functions for reading ---
@@ -208,7 +237,7 @@ impl TwkbGeom for LineString {
208
237
let mut z = if twkb_info. has_z { Some ( 0.0 ) } else { None } ;
209
238
let mut m = if twkb_info. has_m { Some ( 0.0 ) } else { None } ;
210
239
for _ in 0 ..npoints {
211
- let ( x2, y2, z2, m2) = try!( Self :: read_point ( raw, twkb_info, x, y, z, m) ) ;
240
+ let ( x2, y2, z2, m2) = try!( Self :: read_relative_point ( raw, twkb_info, x, y, z, m) ) ;
212
241
points. push ( Point :: new_from_opt_vals ( x2, y2, z2, m2) ) ;
213
242
x = x2; y = y2; z = z2; m = m2;
214
243
}
@@ -238,7 +267,7 @@ impl TwkbGeom for Polygon {
238
267
points. reserve ( npoints as usize ) ;
239
268
let ( x0, y0, z0, m0) = ( x, y, z, m) ;
240
269
for _ in 0 ..npoints {
241
- let ( x2, y2, z2, m2) = try!( Self :: read_point ( raw, twkb_info, x, y, z, m) ) ;
270
+ let ( x2, y2, z2, m2) = try!( Self :: read_relative_point ( raw, twkb_info, x, y, z, m) ) ;
242
271
points. push ( Point :: new_from_opt_vals ( x2, y2, z2, m2) ) ;
243
272
x = x2; y = y2; z = z2; m = m2;
244
273
}
@@ -253,6 +282,126 @@ impl TwkbGeom for Polygon {
253
282
}
254
283
255
284
285
+ impl TwkbGeom for MultiPoint {
286
+ fn read_twkb_body < R : Read > ( raw : & mut R , twkb_info : & TwkbInfo ) -> Result < Self , Error > {
287
+ // npoints uvarint
288
+ // [idlist] varint[]
289
+ // pointarray varint[]
290
+ let mut points: Vec < Point > = Vec :: new ( ) ;
291
+ let mut ids: Option < Vec < u64 > > = None ;
292
+ if !twkb_info. is_empty_geom {
293
+ let npoints = try!( read_raw_varint64 ( raw) ) ;
294
+ points. reserve ( npoints as usize ) ;
295
+
296
+ if twkb_info. has_idlist {
297
+ let idlist = try!( Self :: read_idlist ( raw, npoints as usize ) ) ;
298
+ ids = Some ( idlist) ;
299
+ }
300
+
301
+ let mut x = 0.0 ;
302
+ let mut y = 0.0 ;
303
+ let mut z = if twkb_info. has_z { Some ( 0.0 ) } else { None } ;
304
+ let mut m = if twkb_info. has_m { Some ( 0.0 ) } else { None } ;
305
+ for _ in 0 ..npoints {
306
+ let ( x2, y2, z2, m2) = try!( Self :: read_relative_point ( raw, twkb_info, x, y, z, m) ) ;
307
+ points. push ( Point :: new_from_opt_vals ( x2, y2, z2, m2) ) ;
308
+ x = x2; y = y2; z = z2; m = m2;
309
+ }
310
+ }
311
+ Ok ( MultiPoint { points : points, ids : ids} )
312
+ }
313
+ }
314
+
315
+ impl TwkbGeom for MultiLineString {
316
+ fn read_twkb_body < R : Read > ( raw : & mut R , twkb_info : & TwkbInfo ) -> Result < Self , Error > {
317
+ // nlinestrings uvarint
318
+ // [idlist] varint[]
319
+ // npoints[0] uvarint
320
+ // pointarray[0] varint[]
321
+ // ...
322
+ // npoints[n] uvarint
323
+ // pointarray[n] varint[]
324
+ let mut lines: Vec < LineString > = Vec :: new ( ) ;
325
+ let mut ids: Option < Vec < u64 > > = None ;
326
+ let nlines = try!( read_raw_varint64 ( raw) ) ;
327
+ lines. reserve ( nlines as usize ) ;
328
+
329
+ if twkb_info. has_idlist {
330
+ let idlist = try!( Self :: read_idlist ( raw, nlines as usize ) ) ;
331
+ ids = Some ( idlist) ;
332
+ }
333
+
334
+ let mut x = 0.0 ;
335
+ let mut y = 0.0 ;
336
+ let mut z = if twkb_info. has_z { Some ( 0.0 ) } else { None } ;
337
+ let mut m = if twkb_info. has_m { Some ( 0.0 ) } else { None } ;
338
+ for _ in 0 ..nlines {
339
+ let mut points: Vec < Point > = Vec :: new ( ) ;
340
+ let npoints = try!( read_raw_varint64 ( raw) ) ;
341
+ points. reserve ( npoints as usize ) ;
342
+ for _ in 0 ..npoints {
343
+ let ( x2, y2, z2, m2) = try!( Self :: read_relative_point ( raw, twkb_info, x, y, z, m) ) ;
344
+ points. push ( Point :: new_from_opt_vals ( x2, y2, z2, m2) ) ;
345
+ x = x2; y = y2; z = z2; m = m2;
346
+ }
347
+ lines. push ( LineString { points : points} ) ;
348
+ }
349
+ Ok ( MultiLineString { lines : lines, ids : ids} )
350
+ }
351
+ }
352
+
353
+ impl TwkbGeom for MultiPolygon {
354
+ fn read_twkb_body < R : Read > ( raw : & mut R , twkb_info : & TwkbInfo ) -> Result < Self , Error > {
355
+ // npolygons uvarint
356
+ // [idlist] varint[]
357
+ // nrings[0] uvarint
358
+ // npoints[0][0] uvarint
359
+ // pointarray[0][0] varint[]
360
+ // ...
361
+ // nrings[n] uvarint
362
+ // npoints[n][m] uvarint
363
+ // pointarray[n][m] varint[]
364
+ let mut polygons: Vec < Polygon > = Vec :: new ( ) ;
365
+ let mut ids: Option < Vec < u64 > > = None ;
366
+ let npolygons = try!( read_raw_varint64 ( raw) ) ;
367
+ polygons. reserve ( npolygons as usize ) ;
368
+
369
+ if twkb_info. has_idlist {
370
+ let idlist = try!( Self :: read_idlist ( raw, npolygons as usize ) ) ;
371
+ ids = Some ( idlist) ;
372
+ }
373
+
374
+ let mut x = 0.0 ;
375
+ let mut y = 0.0 ;
376
+ let mut z = if twkb_info. has_z { Some ( 0.0 ) } else { None } ;
377
+ let mut m = if twkb_info. has_m { Some ( 0.0 ) } else { None } ;
378
+ for _ in 0 ..npolygons {
379
+ let mut rings: Vec < LineString > = Vec :: new ( ) ;
380
+ let nrings = try!( read_raw_varint64 ( raw) ) ;
381
+ rings. reserve ( nrings as usize ) ;
382
+ for _ in 0 ..nrings {
383
+ let mut points: Vec < Point > = Vec :: new ( ) ;
384
+ let npoints = try!( read_raw_varint64 ( raw) ) ;
385
+ points. reserve ( npoints as usize ) ;
386
+ let ( x0, y0, z0, m0) = ( x, y, z, m) ;
387
+ for _ in 0 ..npoints {
388
+ let ( x2, y2, z2, m2) = try!( Self :: read_relative_point ( raw, twkb_info, x, y, z, m) ) ;
389
+ points. push ( Point :: new_from_opt_vals ( x2, y2, z2, m2) ) ;
390
+ x = x2; y = y2; z = z2; m = m2;
391
+ }
392
+ // close ring, if necessary
393
+ if x != x0 && y != y0 && z != z0 && m != m0 {
394
+ points. push ( Point :: new_from_opt_vals ( x0, y0, z0, m0) ) ;
395
+ }
396
+ rings. push ( LineString { points : points} ) ;
397
+ }
398
+ polygons. push ( Polygon { rings : rings} ) ;
399
+ }
400
+ Ok ( MultiPolygon { polygons : polygons, ids : ids} )
401
+ }
402
+ }
403
+
404
+
256
405
impl < ' a > AsEwkbLineString < ' a > for LineString {
257
406
type PointType = Point ;
258
407
type Iter = Iter < ' a , Point > ;
@@ -332,6 +481,27 @@ fn test_read_polygon() {
332
481
assert_eq ! ( format!( "{:?}" , poly) , "Polygon { rings: [LineString { points: [Point { x: 0, y: 0 }, Point { x: 2, y: 0 }, Point { x: 2, y: 2 }, Point { x: 0, y: 2 }, Point { x: 0, y: 0 }] }, LineString { points: [Point { x: 10, y: 10 }, Point { x: -2, y: 10 }, Point { x: -2, y: -2 }, Point { x: 10, y: -2 }, Point { x: 10, y: 10 }] }] }" ) ;
333
482
}
334
483
484
+ #[ test]
485
+ fn test_read_multipoint ( ) {
486
+ let twkb = hex_to_vec ( "04000214271326" ) ; // SELECT encode(ST_AsTWKB('MULTIPOINT ((10 -20), (0 -0.5))'::geometry), 'hex')
487
+ let points = MultiPoint :: read_twkb ( & mut twkb. as_slice ( ) ) . unwrap ( ) ;
488
+ assert_eq ! ( format!( "{:?}" , points) , "MultiPoint { points: [Point { x: 10, y: -20 }, Point { x: 0, y: -1 }], ids: None }" ) ;
489
+ }
490
+
491
+ #[ test]
492
+ fn test_read_multiline ( ) {
493
+ let twkb = hex_to_vec ( "05000202142713260200020400" ) ; // SELECT encode(ST_AsTWKB('MULTILINESTRING ((10 -20, 0 -0.5), (0 0, 2 0))'::geometry), 'hex')
494
+ let lines = MultiLineString :: read_twkb ( & mut twkb. as_slice ( ) ) . unwrap ( ) ;
495
+ assert_eq ! ( format!( "{:?}" , lines) , "MultiLineString { lines: [LineString { points: [Point { x: 10, y: -20 }, Point { x: 0, y: -1 }] }, LineString { points: [Point { x: 0, y: 0 }, Point { x: 2, y: 0 }] }], ids: None }" ) ;
496
+ }
497
+
498
+ #[ test]
499
+ fn test_read_multipolygon ( ) {
500
+ let twkb = hex_to_vec ( "060002010500000400000403000003010514141700001718000018" ) ; // SELECT encode(ST_AsTWKB('MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((10 10, -2 10, -2 -2, 10 -2, 10 10)))'::geometry), 'hex')
501
+ let polys = MultiPolygon :: read_twkb ( & mut twkb. as_slice ( ) ) . unwrap ( ) ;
502
+ assert_eq ! ( format!( "{:?}" , polys) , "MultiPolygon { polygons: [Polygon { rings: [LineString { points: [Point { x: 0, y: 0 }, Point { x: 2, y: 0 }, Point { x: 2, y: 2 }, Point { x: 0, y: 2 }, Point { x: 0, y: 0 }] }] }, Polygon { rings: [LineString { points: [Point { x: 10, y: 10 }, Point { x: -2, y: 10 }, Point { x: -2, y: -2 }, Point { x: 10, y: -2 }, Point { x: 10, y: 10 }] }] }], ids: None }" ) ;
503
+ }
504
+
335
505
#[ test]
336
506
fn test_write_point ( ) {
337
507
let twkb = hex_to_vec ( "01001427" ) ; // SELECT encode(ST_AsTWKB('POINT(10 -20)'::geometry), 'hex')
0 commit comments