1use crate::error::{Error, GResult};
2use crate::{ConstGeometry, CoordSeq, Geom, Geometry as GGeometry, GeometryTypes};
3use geojson::{Geometry, Value};
4
5use std::convert::{TryFrom, TryInto};
6
7fn coords_seq_to_vec_position(cs: &CoordSeq) -> GResult<Vec<Vec<f64>>> {
8 let n_coords = cs.size()?;
9 let mut coords = Vec::with_capacity(n_coords);
10 for i in 0..n_coords {
11 coords.push(vec![cs.get_x(i)?, cs.get_y(i)?]);
12 }
13 Ok(coords)
14}
15
16macro_rules! impl_try_from_geojson {
17 ($ty_name:ident $(,$lt:lifetime)?) => (
18impl$(<$lt>)? TryFrom<$ty_name$(<$lt>)?> for Geometry {
19 type Error = Error;
20
21 fn try_from(other: $ty_name$(<$lt>)?) -> Result<Geometry, Self::Error> {
22 let _type = other.geometry_type();
23 match _type {
24 GeometryTypes::Point => {
25 let coord_seq = other.get_coord_seq()?;
26 Ok(Geometry::new(
27 Value::Point(
28 vec![
29 coord_seq.get_x(0)?,
30 coord_seq.get_y(0)?,
31 ]
32 )
33 ))
34 }
35 GeometryTypes::MultiPoint => {
36 let n_pts = other.get_num_geometries()?;
37 let mut coords = Vec::with_capacity(n_pts);
38 for i in 0..n_pts {
39 let coord_seq = other.get_geometry_n(i)?.get_coord_seq()?;
40 coords.push(vec![
41 coord_seq.get_x(0)?,
42 coord_seq.get_y(0)?,
43 ]);
44 }
45 Ok(Geometry::new(Value::MultiPoint(coords)))
46 }
47 GeometryTypes::LineString | GeometryTypes::LinearRing => {
48 let cs = other.get_coord_seq()?;
49 let coords = coords_seq_to_vec_position(&cs)?;
50 Ok(Geometry::new(Value::LineString(coords)))
51 }
52 GeometryTypes::MultiLineString => {
53 let n_lines = other.get_num_geometries()?;
54 let mut result_lines = Vec::with_capacity(n_lines);
55 for i in 0..n_lines {
56 let cs = other.get_geometry_n(i)?.get_coord_seq()?;
57 result_lines.push(coords_seq_to_vec_position(&(cs))?);
58 }
59 Ok(Geometry::new(Value::MultiLineString(result_lines)))
60 }
61 GeometryTypes::Polygon => {
62 let nb_interiors = other.get_num_interior_rings()?;
63
64 let mut rings = Vec::with_capacity(nb_interiors + 1usize);
65 rings.push(coords_seq_to_vec_position(&(
67 other.get_exterior_ring()?.get_coord_seq()?))?);
68 for ix_interior in 0..nb_interiors {
70 rings.push(coords_seq_to_vec_position(
71 &(other.get_interior_ring_n(ix_interior as u32)?.get_coord_seq()?))?);
72 }
73 Ok(Geometry::new(Value::Polygon(rings)))
74 }
75 GeometryTypes::MultiPolygon => {
76 let n_polygs = other.get_num_geometries()?;
77 let mut result_polygs = Vec::with_capacity(n_polygs);
78 for i in 0..n_polygs {
79 let polyg = other.get_geometry_n(i)?;
80 let nb_interiors = polyg.get_num_interior_rings()?;
81
82 let mut rings = Vec::with_capacity(nb_interiors + 1usize);
83 rings.push(coords_seq_to_vec_position(&(
85 polyg.get_exterior_ring()?.get_coord_seq()?))?);
86 for ix_interior in 0..nb_interiors {
88 rings.push(coords_seq_to_vec_position(
89 &(polyg.get_interior_ring_n(ix_interior as u32)?.get_coord_seq()?))?);
90 }
91 result_polygs.push(rings);
92 }
93 Ok(Geometry::new(Value::MultiPolygon(result_polygs)))
94 }
95 GeometryTypes::GeometryCollection => {
96 let n_geoms = other.get_num_geometries()?;
97 let mut result_geoms = Vec::with_capacity(n_geoms);
98 for i in 0..n_geoms {
99 let g = other.get_geometry_n(i)?;
100 let geojsongeom: Geometry = g.try_into()?;
101 result_geoms.push(geojsongeom);
102 }
103 Ok(Geometry::new(Value::GeometryCollection(result_geoms)))
104 }
105 _ => unreachable!(),
106 }
107 }
108}
109 );
110}
111
112impl_try_from_geojson!(GGeometry);
113impl_try_from_geojson!(ConstGeometry, 'c);
114
115#[cfg(test)]
116mod test {
117 use crate::Geometry as GGeometry;
118 use geojson::{Geometry, Value};
119
120 use std::convert::TryInto;
121
122 #[test]
123 fn geom_to_geojson_point() {
124 let pt = "POINT(1 1)";
125 let pt = GGeometry::new_from_wkt(pt).unwrap();
126
127 let geojson_pt: Geometry = pt.try_into().unwrap();
128
129 let expected_pt = Geometry::new(Value::Point(vec![1., 1.]));
130 assert_eq!(geojson_pt, expected_pt);
131 }
132
133 #[test]
134 fn geom_to_geojson_multipoint() {
135 let pts = "MULTIPOINT((1 1), (2 2))";
136 let pts = GGeometry::new_from_wkt(pts).unwrap();
137
138 let geojson_pts: Geometry = pts.try_into().unwrap();
139
140 let expected_pts = Geometry::new(Value::MultiPoint(vec![vec![1., 1.], vec![2., 2.]]));
141 assert_eq!(geojson_pts, expected_pts);
142 }
143
144 #[test]
145 fn geom_to_geojson_line() {
146 let line = "LINESTRING(1 1, 2 2)";
147 let line = GGeometry::new_from_wkt(line).unwrap();
148
149 let geojson_line: Geometry = line.try_into().unwrap();
150
151 let expected_line = Geometry::new(Value::LineString(vec![vec![1., 1.], vec![2., 2.]]));
152 assert_eq!(geojson_line, expected_line);
153 }
154
155 #[test]
156 fn geom_to_geojson_linearring() {
157 let line = "LINEARRING(1 1, 2 1, 2 2, 1 1)";
158 let line = GGeometry::new_from_wkt(line).unwrap();
159
160 let geojson_line: Geometry = line.try_into().unwrap();
161
162 let expected_line = Geometry::new(Value::LineString(vec![
163 vec![1., 1.],
164 vec![2., 1.],
165 vec![2., 2.],
166 vec![1., 1.],
167 ]));
168 assert_eq!(geojson_line, expected_line);
169 }
170
171 #[test]
172 fn geom_to_geojson_multiline() {
173 let line = "MULTILINESTRING((1 1, 2 2), (3 3, 4 4))";
174 let line = GGeometry::new_from_wkt(line).unwrap();
175
176 let geojson_line: Geometry = line.try_into().unwrap();
177
178 let expected_line = Geometry::new(Value::MultiLineString(vec![
179 vec![vec![1., 1.], vec![2., 2.]],
180 vec![vec![3., 3.], vec![4., 4.]],
181 ]));
182 assert_eq!(geojson_line, expected_line);
183 }
184
185 #[test]
186 fn geom_to_geojson_polygon() {
187 let poly = "POLYGON((0 0, 0 3, 3 3, 3 0, 0 0) ,(0.2 0.2, 0.2 2, 2 2, 2 0.2, 0.2 0.2))";
188 let poly = GGeometry::new_from_wkt(poly).unwrap();
189
190 let geojson_polygon: Geometry = poly.try_into().unwrap();
191
192 let expected_polygon = Geometry::new(Value::Polygon(vec![
193 vec![
194 vec![0., 0.],
195 vec![0., 3.],
196 vec![3., 3.],
197 vec![3., 0.],
198 vec![0., 0.],
199 ],
200 vec![
201 vec![0.2, 0.2],
202 vec![0.2, 2.],
203 vec![2., 2.],
204 vec![2., 0.2],
205 vec![0.2, 0.2],
206 ],
207 ]));
208 assert_eq!(geojson_polygon, expected_polygon);
209 }
210
211 #[test]
212 fn geom_to_geojson_multipolygon() {
213 let poly = "MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))";
214 let poly = GGeometry::new_from_wkt(poly).unwrap();
215
216 let geojson_polygon: Geometry = poly.try_into().unwrap();
217
218 let expected_polygon = Geometry::new(Value::MultiPolygon(vec![vec![vec![
219 vec![0., 0.],
220 vec![0., 1.],
221 vec![1., 1.],
222 vec![1., 0.],
223 vec![0., 0.],
224 ]]]));
225 assert_eq!(geojson_polygon, expected_polygon);
226 }
227
228 #[test]
229 fn geom_to_geojson_geometry_collection() {
230 let gc = "GEOMETRYCOLLECTION(POINT(1 1), LINESTRING(1 1, 2 2))";
231 let gc = GGeometry::new_from_wkt(gc).unwrap();
232
233 let geojson_gc: Geometry = gc.try_into().unwrap();
234
235 let expected_gc = Geometry::new(Value::GeometryCollection(vec![
236 Geometry::new(Value::Point(vec![1., 1.])),
237 Geometry::new(Value::LineString(vec![vec![1., 1.], vec![2., 2.]])),
238 ]));
239 assert_eq!(geojson_gc, expected_gc);
240 }
241}