1use geo_types::{self, CoordFloat};
2
3use crate::geometry;
4
5use crate::{Error, Result};
6use crate::{Feature, FeatureCollection, GeoJson, LineStringType, PointType, PolygonType};
7use std::convert::{TryFrom, TryInto};
8
9#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
10impl<T> TryFrom<&geometry::Value> for geo_types::Point<T>
11where
12 T: CoordFloat,
13{
14 type Error = Error;
15
16 fn try_from(value: &geometry::Value) -> Result<Self> {
17 match value {
18 geometry::Value::Point(point_type) => Ok(create_geo_point(point_type)),
19 other => Err(mismatch_geom_err("Point", other)),
20 }
21 }
22}
23try_from_owned_value!(geo_types::Point<T>);
24
25#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
26impl<T> TryFrom<&geometry::Value> for geo_types::MultiPoint<T>
27where
28 T: CoordFloat,
29{
30 type Error = Error;
31
32 fn try_from(value: &geometry::Value) -> Result<Self> {
33 match value {
34 geometry::Value::MultiPoint(multi_point_type) => Ok(geo_types::MultiPoint(
35 multi_point_type
36 .iter()
37 .map(|point_type| create_geo_point(point_type))
38 .collect(),
39 )),
40 other => Err(mismatch_geom_err("MultiPoint", other)),
41 }
42 }
43}
44try_from_owned_value!(geo_types::MultiPoint<T>);
45
46#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
47impl<T> TryFrom<&geometry::Value> for geo_types::LineString<T>
48where
49 T: CoordFloat,
50{
51 type Error = Error;
52
53 fn try_from(value: &geometry::Value) -> Result<Self> {
54 match value {
55 geometry::Value::LineString(multi_point_type) => {
56 Ok(create_geo_line_string(multi_point_type))
57 }
58 other => Err(mismatch_geom_err("LineString", other)),
59 }
60 }
61}
62try_from_owned_value!(geo_types::LineString<T>);
63
64#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
65impl<T> TryFrom<&geometry::Value> for geo_types::MultiLineString<T>
66where
67 T: CoordFloat,
68{
69 type Error = Error;
70
71 fn try_from(value: &geometry::Value) -> Result<Self> {
72 match value {
73 geometry::Value::MultiLineString(multi_line_string_type) => {
74 Ok(create_geo_multi_line_string(multi_line_string_type))
75 }
76 other => Err(mismatch_geom_err("MultiLineString", other)),
77 }
78 }
79}
80try_from_owned_value!(geo_types::MultiLineString<T>);
81
82#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
83impl<T> TryFrom<&geometry::Value> for geo_types::Polygon<T>
84where
85 T: CoordFloat,
86{
87 type Error = Error;
88
89 fn try_from(value: &geometry::Value) -> Result<Self> {
90 match value {
91 geometry::Value::Polygon(polygon_type) => Ok(create_geo_polygon(polygon_type)),
92 other => Err(mismatch_geom_err("Polygon", other)),
93 }
94 }
95}
96try_from_owned_value!(geo_types::Polygon<T>);
97
98#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
99impl<T> TryFrom<&geometry::Value> for geo_types::MultiPolygon<T>
100where
101 T: CoordFloat,
102{
103 type Error = Error;
104
105 fn try_from(value: &geometry::Value) -> Result<geo_types::MultiPolygon<T>> {
106 match value {
107 geometry::Value::MultiPolygon(multi_polygon_type) => {
108 Ok(create_geo_multi_polygon(multi_polygon_type))
109 }
110 other => Err(mismatch_geom_err("MultiPolygon", other)),
111 }
112 }
113}
114try_from_owned_value!(geo_types::MultiPolygon<T>);
115
116#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
117impl<T> TryFrom<&geometry::Value> for geo_types::GeometryCollection<T>
118where
119 T: CoordFloat,
120{
121 type Error = Error;
122
123 fn try_from(value: &geometry::Value) -> Result<Self> {
124 match value {
125 geometry::Value::GeometryCollection(geometries) => {
126 let geojson_geometries = geometries
127 .iter()
128 .map(|geometry| (&geometry.value).try_into().unwrap())
129 .collect();
130
131 Ok(geo_types::GeometryCollection(geojson_geometries))
132 }
133 other => Err(mismatch_geom_err("GeometryCollection", other)),
134 }
135 }
136}
137try_from_owned_value!(geo_types::GeometryCollection<T>);
138
139#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
140impl<T> TryFrom<&geometry::Value> for geo_types::Geometry<T>
141where
142 T: CoordFloat,
143{
144 type Error = Error;
145
146 fn try_from(value: &geometry::Value) -> Result<Self> {
147 match value {
148 geometry::Value::Point(ref point_type) => {
149 Ok(geo_types::Geometry::Point(create_geo_point(point_type)))
150 }
151 geometry::Value::MultiPoint(ref multi_point_type) => {
152 Ok(geo_types::Geometry::MultiPoint(geo_types::MultiPoint(
153 multi_point_type
154 .iter()
155 .map(|point_type| create_geo_point(point_type))
156 .collect(),
157 )))
158 }
159 geometry::Value::LineString(ref line_string_type) => Ok(
160 geo_types::Geometry::LineString(create_geo_line_string(line_string_type)),
161 ),
162 geometry::Value::MultiLineString(ref multi_line_string_type) => {
163 Ok(geo_types::Geometry::MultiLineString(
164 create_geo_multi_line_string(multi_line_string_type),
165 ))
166 }
167 geometry::Value::Polygon(ref polygon_type) => Ok(geo_types::Geometry::Polygon(
168 create_geo_polygon(polygon_type),
169 )),
170 geometry::Value::MultiPolygon(ref multi_polygon_type) => Ok(
171 geo_types::Geometry::MultiPolygon(create_geo_multi_polygon(multi_polygon_type)),
172 ),
173 geometry::Value::GeometryCollection(ref gc_type) => {
174 let gc = geo_types::Geometry::GeometryCollection(geo_types::GeometryCollection(
175 gc_type
176 .iter()
177 .cloned()
178 .map(|geom| geom.try_into())
179 .collect::<Result<Vec<geo_types::Geometry<T>>>>()?,
180 ));
181 Ok(gc)
182 }
183 }
184 }
185}
186try_from_owned_value!(geo_types::Geometry<T>);
187
188macro_rules! impl_try_from_geom_value {
189 ($($kind:ident),*) => {
190 $(
191 #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
192 impl<T> TryFrom<&$crate::Geometry> for geo_types::$kind<T>
193 where
194 T: CoordFloat,
195 {
196 type Error = Error;
197
198 fn try_from(geometry: &crate::Geometry) -> Result<Self> {
199 Self::try_from(&geometry.value)
200 }
201 }
202
203 #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
204 impl<T> TryFrom<$crate::Geometry> for geo_types::$kind<T>
205 where
206 T: CoordFloat,
207 {
208 type Error = Error;
209
210 fn try_from(geometry: crate::Geometry) -> Result<Self> {
211 Self::try_from(geometry.value)
212 }
213 }
214
215 #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
216 impl<T> TryFrom<$crate::Feature> for geo_types::$kind<T>
217 where
218 T: CoordFloat,
219 {
220 type Error = Error;
221
222 fn try_from(val: Feature) -> Result<Self> {
223 match val.geometry {
224 None => Err(Error::FeatureHasNoGeometry(val)),
225 Some(geom) => geom.try_into(),
226 }
227 }
228 }
229 )*
230 }
231}
232
233impl_try_from_geom_value![
234 Point,
235 LineString,
236 Polygon,
237 MultiPoint,
238 MultiLineString,
239 MultiPolygon,
240 Geometry,
241 GeometryCollection
242];
243
244impl<T: CoordFloat> TryFrom<&GeoJson> for geo_types::GeometryCollection<T> {
245 type Error = Error;
246
247 fn try_from(gj: &GeoJson) -> Result<geo_types::GeometryCollection<T>>
249 where
250 T: CoordFloat,
251 {
252 match gj {
253 GeoJson::FeatureCollection(collection) => Ok(geo_types::GeometryCollection(
254 collection
255 .features
256 .iter()
257 .filter_map(|feature| feature.geometry.as_ref())
259 .map(|geometry| geometry.clone().try_into())
260 .collect::<Result<_>>()?,
261 )),
262 GeoJson::Feature(feature) => {
263 if let Some(geometry) = &feature.geometry {
264 Ok(geo_types::GeometryCollection(vec![geometry
265 .clone()
266 .try_into()?]))
267 } else {
268 Ok(geo_types::GeometryCollection(vec![]))
269 }
270 }
271 GeoJson::Geometry(geometry) => Ok(geo_types::GeometryCollection(vec![geometry
272 .clone()
273 .try_into()?])),
274 }
275 }
276}
277
278#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
279impl<T> TryFrom<FeatureCollection> for geo_types::Geometry<T>
280where
281 T: CoordFloat,
282{
283 type Error = Error;
284
285 fn try_from(val: FeatureCollection) -> Result<geo_types::Geometry<T>> {
286 Ok(geo_types::Geometry::GeometryCollection(
287 geo_types::GeometryCollection::try_from(&GeoJson::FeatureCollection(val))?,
288 ))
289 }
290}
291
292#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
293impl<T> TryFrom<GeoJson> for geo_types::Geometry<T>
294where
295 T: CoordFloat,
296{
297 type Error = Error;
298
299 fn try_from(val: GeoJson) -> Result<geo_types::Geometry<T>> {
300 match val {
301 GeoJson::Geometry(geom) => geom.try_into(),
302 GeoJson::Feature(feat) => feat.try_into(),
303 GeoJson::FeatureCollection(fc) => fc.try_into(),
304 }
305 }
306}
307
308fn create_geo_coordinate<T>(point_type: &PointType) -> geo_types::Coord<T>
309where
310 T: CoordFloat,
311{
312 geo_types::Coord {
313 x: T::from(point_type[0]).unwrap(),
314 y: T::from(point_type[1]).unwrap(),
315 }
316}
317
318fn create_geo_point<T>(point_type: &PointType) -> geo_types::Point<T>
319where
320 T: CoordFloat,
321{
322 geo_types::Point::new(
323 T::from(point_type[0]).unwrap(),
324 T::from(point_type[1]).unwrap(),
325 )
326}
327
328fn create_geo_line_string<T>(line_type: &LineStringType) -> geo_types::LineString<T>
329where
330 T: CoordFloat,
331{
332 geo_types::LineString(
333 line_type
334 .iter()
335 .map(|point_type| create_geo_coordinate(point_type))
336 .collect(),
337 )
338}
339
340fn create_geo_multi_line_string<T>(
341 multi_line_type: &[LineStringType],
342) -> geo_types::MultiLineString<T>
343where
344 T: CoordFloat,
345{
346 geo_types::MultiLineString(
347 multi_line_type
348 .iter()
349 .map(|point_type| create_geo_line_string(point_type))
350 .collect(),
351 )
352}
353
354fn create_geo_polygon<T>(polygon_type: &PolygonType) -> geo_types::Polygon<T>
355where
356 T: CoordFloat,
357{
358 let exterior = polygon_type
359 .first()
360 .map(|e| create_geo_line_string(e))
361 .unwrap_or_else(|| create_geo_line_string(&vec![]));
362
363 let interiors = if polygon_type.len() < 2 {
364 vec![]
365 } else {
366 polygon_type[1..]
367 .iter()
368 .map(|line_string_type| create_geo_line_string(line_string_type))
369 .collect()
370 };
371
372 geo_types::Polygon::new(exterior, interiors)
373}
374
375fn create_geo_multi_polygon<T>(multi_polygon_type: &[PolygonType]) -> geo_types::MultiPolygon<T>
376where
377 T: CoordFloat,
378{
379 geo_types::MultiPolygon(
380 multi_polygon_type
381 .iter()
382 .map(|polygon_type| create_geo_polygon(polygon_type))
383 .collect(),
384 )
385}
386
387fn mismatch_geom_err(expected_type: &'static str, found: &geometry::Value) -> Error {
388 Error::InvalidGeometryConversion {
389 expected_type,
390 found_type: found.type_name(),
391 }
392}
393
394#[cfg(test)]
395mod tests {
396 use crate::{Geometry, Value};
397 use serde_json::json;
398
399 use std::convert::TryInto;
400
401 #[test]
402 fn geojson_point_conversion_test() {
403 let coords = vec![100.0, 0.2];
404 let geojson_point = Value::Point(coords.clone());
405 let geo_point: geo_types::Point<f64> = geojson_point.try_into().unwrap();
406
407 assert_almost_eq!(geo_point.x(), coords[0], 1e-6);
408 assert_almost_eq!(geo_point.y(), coords[1], 1e-6);
409 }
410
411 #[test]
412 fn geojson_multi_point_conversion_test() {
413 let coord1 = vec![100.0, 0.2];
414 let coord2 = vec![101.0, 1.0];
415 let geojson_multi_point = Value::MultiPoint(vec![coord1.clone(), coord2.clone()]);
416 let geo_multi_point: geo_types::MultiPoint<f64> = geojson_multi_point.try_into().unwrap();
417
418 assert_almost_eq!(geo_multi_point.0[0].x(), coord1[0], 1e-6);
419 assert_almost_eq!(geo_multi_point.0[0].y(), coord1[1], 1e-6);
420 assert_almost_eq!(geo_multi_point.0[1].x(), coord2[0], 1e-6);
421 assert_almost_eq!(geo_multi_point.0[1].y(), coord2[1], 1e-6);
422 }
423
424 #[test]
425 fn geojson_line_string_conversion_test() {
426 let coord1 = vec![100.0, 0.2];
427 let coord2 = vec![101.0, 1.0];
428 let geojson_line_string = Value::LineString(vec![coord1.clone(), coord2.clone()]);
429 let geo_line_string: geo_types::LineString<f64> = geojson_line_string.try_into().unwrap();
430
431 assert_almost_eq!(geo_line_string.0[0].x, coord1[0], 1e-6);
432 assert_almost_eq!(geo_line_string.0[0].y, coord1[1], 1e-6);
433 assert_almost_eq!(geo_line_string.0[1].x, coord2[0], 1e-6);
434 assert_almost_eq!(geo_line_string.0[1].y, coord2[1], 1e-6);
435 }
436
437 #[test]
438 fn geojson_multi_line_string_conversion_test() {
439 let coord1 = vec![100.0, 0.2];
440 let coord2 = vec![101.0, 1.0];
441 let coord3 = vec![102.0, 0.8];
442 let geojson_multi_line_string = Value::MultiLineString(vec![
443 vec![coord1.clone(), coord2.clone()],
444 vec![coord2.clone(), coord3.clone()],
445 ]);
446 let geo_multi_line_string: geo_types::MultiLineString<f64> =
447 geojson_multi_line_string.try_into().unwrap();
448
449 let geo_line_string1 = &geo_multi_line_string.0[0];
450 assert_almost_eq!(geo_line_string1.0[0].x, coord1[0], 1e-6);
451 assert_almost_eq!(geo_line_string1.0[0].y, coord1[1], 1e-6);
452 assert_almost_eq!(geo_line_string1.0[1].x, coord2[0], 1e-6);
453 assert_almost_eq!(geo_line_string1.0[1].y, coord2[1], 1e-6);
454
455 let geo_line_string2 = &geo_multi_line_string.0[1];
456 assert_almost_eq!(geo_line_string2.0[0].x, coord2[0], 1e-6);
457 assert_almost_eq!(geo_line_string2.0[0].y, coord2[1], 1e-6);
458 assert_almost_eq!(geo_line_string2.0[1].x, coord3[0], 1e-6);
459 assert_almost_eq!(geo_line_string2.0[1].y, coord3[1], 1e-6);
460 }
461
462 #[test]
463 fn geojson_polygon_conversion_test() {
464 let coord1 = vec![100.0, 0.0];
465 let coord2 = vec![101.0, 1.0];
466 let coord3 = vec![101.0, 1.0];
467 let coord4 = vec![104.0, 0.2];
468 let coord5 = vec![100.9, 0.2];
469 let coord6 = vec![100.9, 0.7];
470
471 let geojson_multi_line_string_type1 = vec![
472 vec![
473 coord1.clone(),
474 coord2.clone(),
475 coord3.clone(),
476 coord1.clone(),
477 ],
478 vec![
479 coord4.clone(),
480 coord5.clone(),
481 coord6.clone(),
482 coord4.clone(),
483 ],
484 ];
485 let geojson_polygon = Value::Polygon(geojson_multi_line_string_type1);
486 let geo_polygon: geo_types::Polygon<f64> = geojson_polygon.try_into().unwrap();
487
488 let geo_line_string1 = geo_polygon.exterior();
489 assert_almost_eq!(geo_line_string1.0[0].x, coord1[0], 1e-6);
490 assert_almost_eq!(geo_line_string1.0[0].y, coord1[1], 1e-6);
491 assert_almost_eq!(geo_line_string1.0[1].x, coord2[0], 1e-6);
492 assert_almost_eq!(geo_line_string1.0[1].y, coord2[1], 1e-6);
493 assert_almost_eq!(geo_line_string1.0[2].x, coord3[0], 1e-6);
494 assert_almost_eq!(geo_line_string1.0[2].y, coord3[1], 1e-6);
495 assert_almost_eq!(geo_line_string1.0[3].x, coord1[0], 1e-6);
496 assert_almost_eq!(geo_line_string1.0[3].y, coord1[1], 1e-6);
497
498 let geo_line_string2 = &geo_polygon.interiors()[0];
499 assert_almost_eq!(geo_line_string2.0[0].x, coord4[0], 1e-6);
500 assert_almost_eq!(geo_line_string2.0[0].y, coord4[1], 1e-6);
501 assert_almost_eq!(geo_line_string2.0[1].x, coord5[0], 1e-6);
502 assert_almost_eq!(geo_line_string2.0[1].y, coord5[1], 1e-6);
503 assert_almost_eq!(geo_line_string2.0[2].x, coord6[0], 1e-6);
504 assert_almost_eq!(geo_line_string2.0[2].y, coord6[1], 1e-6);
505 assert_almost_eq!(geo_line_string2.0[3].x, coord4[0], 1e-6);
506 assert_almost_eq!(geo_line_string2.0[3].y, coord4[1], 1e-6);
507 }
508
509 #[test]
510 fn geojson_empty_polygon_conversion_test() {
511 let geojson_polygon = Value::Polygon(vec![]);
512 let geo_polygon: geo_types::Polygon<f64> = geojson_polygon.try_into().unwrap();
513
514 assert!(geo_polygon.exterior().0.is_empty());
515 }
516
517 #[test]
518 fn geojson_polygon_without_interiors_conversion_test() {
519 let coord1 = vec![100.0, 0.0];
520 let coord2 = vec![101.0, 1.0];
521 let coord3 = vec![101.0, 1.0];
522
523 let geojson_multi_line_string_type1 = vec![vec![
524 coord1.clone(),
525 coord2.clone(),
526 coord3.clone(),
527 coord1.clone(),
528 ]];
529 let geojson_polygon = Value::Polygon(geojson_multi_line_string_type1);
530 let geo_polygon: geo_types::Polygon<f64> = geojson_polygon.try_into().unwrap();
531
532 let geo_line_string1 = geo_polygon.exterior();
533 assert_almost_eq!(geo_line_string1.0[0].x, coord1[0], 1e-6);
534 assert_almost_eq!(geo_line_string1.0[0].y, coord1[1], 1e-6);
535 assert_almost_eq!(geo_line_string1.0[1].x, coord2[0], 1e-6);
536 assert_almost_eq!(geo_line_string1.0[1].y, coord2[1], 1e-6);
537 assert_almost_eq!(geo_line_string1.0[2].x, coord3[0], 1e-6);
538 assert_almost_eq!(geo_line_string1.0[2].y, coord3[1], 1e-6);
539 assert_almost_eq!(geo_line_string1.0[3].x, coord1[0], 1e-6);
540 assert_almost_eq!(geo_line_string1.0[3].y, coord1[1], 1e-6);
541
542 assert_eq!(0, geo_polygon.interiors().len());
543 }
544
545 #[test]
546 fn geojson_multi_polygon_conversion_test() {
547 let coord1 = vec![100.0, 0.0];
548 let coord2 = vec![101.0, 1.0];
549 let coord3 = vec![101.0, 1.0];
550 let coord4 = vec![104.0, 0.2];
551 let coord5 = vec![100.9, 0.2];
552 let coord6 = vec![100.9, 0.7];
553
554 let geojson_line_string_type1 = vec![
555 coord1.clone(),
556 coord2.clone(),
557 coord3.clone(),
558 coord1.clone(),
559 ];
560
561 let geojson_line_string_type2 = vec![
562 coord4.clone(),
563 coord5.clone(),
564 coord6.clone(),
565 coord4.clone(),
566 ];
567 let geojson_multi_polygon = Value::MultiPolygon(vec![
568 vec![geojson_line_string_type1],
569 vec![geojson_line_string_type2],
570 ]);
571 let geo_multi_polygon: geo_types::MultiPolygon<f64> =
572 geojson_multi_polygon.try_into().unwrap();
573
574 let geo_line_string1 = geo_multi_polygon.0[0].exterior();
575 assert_almost_eq!(geo_line_string1.0[0].x, coord1[0], 1e-6);
576 assert_almost_eq!(geo_line_string1.0[0].y, coord1[1], 1e-6);
577 assert_almost_eq!(geo_line_string1.0[1].x, coord2[0], 1e-6);
578 assert_almost_eq!(geo_line_string1.0[1].y, coord2[1], 1e-6);
579 assert_almost_eq!(geo_line_string1.0[2].x, coord3[0], 1e-6);
580 assert_almost_eq!(geo_line_string1.0[2].y, coord3[1], 1e-6);
581 assert_almost_eq!(geo_line_string1.0[3].x, coord1[0], 1e-6);
582 assert_almost_eq!(geo_line_string1.0[3].y, coord1[1], 1e-6);
583
584 let geo_line_string2 = geo_multi_polygon.0[1].exterior();
585 assert_almost_eq!(geo_line_string2.0[0].x, coord4[0], 1e-6);
586 assert_almost_eq!(geo_line_string2.0[0].y, coord4[1], 1e-6);
587 assert_almost_eq!(geo_line_string2.0[1].x, coord5[0], 1e-6);
588 assert_almost_eq!(geo_line_string2.0[1].y, coord5[1], 1e-6);
589 assert_almost_eq!(geo_line_string2.0[2].x, coord6[0], 1e-6);
590 assert_almost_eq!(geo_line_string2.0[2].y, coord6[1], 1e-6);
591 assert_almost_eq!(geo_line_string2.0[3].x, coord4[0], 1e-6);
592 assert_almost_eq!(geo_line_string2.0[3].y, coord4[1], 1e-6);
593 }
594
595 #[test]
596 fn geojson_geometry_collection_conversion_test() {
597 let coord1 = vec![100.0, 0.0];
598 let coord2 = vec![100.0, 1.0];
599 let coord3 = vec![101.0, 1.0];
600 let coord4 = vec![102.0, 0.0];
601 let coord5 = vec![101.0, 0.0];
602
603 let geojson_multi_point = Value::MultiPoint(vec![coord1.clone(), coord2.clone()]);
604 let geojson_multi_line_string = Value::MultiLineString(vec![
605 vec![coord1.clone(), coord2.clone()],
606 vec![coord2.clone(), coord3.clone()],
607 ]);
608 let geojson_multi_polygon = Value::MultiPolygon(vec![
609 vec![vec![
610 coord3.clone(),
611 coord4.clone(),
612 coord5.clone(),
613 coord3.clone(),
614 ]],
615 vec![vec![
616 coord1.clone(),
617 coord5.clone(),
618 coord3.clone(),
619 coord1.clone(),
620 ]],
621 ]);
622
623 let geojson_geometry_collection = Value::GeometryCollection(vec![
624 Geometry::new(geojson_multi_point),
625 Geometry::new(geojson_multi_line_string),
626 Geometry::new(geojson_multi_polygon),
627 ]);
628
629 let geo_geometry_collection: geo_types::GeometryCollection<f64> =
630 geojson_geometry_collection.try_into().unwrap();
631
632 assert_eq!(3, geo_geometry_collection.0.len());
633 }
634
635 #[test]
636 fn geojson_geometry_conversion() {
637 let coords = vec![100.0, 0.2];
638 let geojson_geometry = Geometry::from(Value::Point(coords.clone()));
639 let geo_geometry: geo_types::Geometry<f64> = geojson_geometry
640 .try_into()
641 .expect("Should be able to convert to geo_types::Geometry");
642 let geo_point: geo_types::Point<_> =
643 geo_geometry.try_into().expect("this should be a point");
644 assert_almost_eq!(geo_point.x(), coords[0], 1e-6);
645 assert_almost_eq!(geo_point.y(), coords[1], 1e-6);
646 }
647
648 #[test]
649 fn geojson_mismatch_geometry_conversion_test() {
650 let coord1 = vec![100.0, 0.2];
651 let coord2 = vec![101.0, 1.0];
652 let geojson_line_string = Value::LineString(vec![coord1.clone(), coord2.clone()]);
653 use std::convert::TryFrom;
654 let error = geo_types::Point::<f64>::try_from(geojson_line_string).unwrap_err();
655 assert_eq!(
656 "Expected type: `Point`, but found `LineString`",
657 format!("{}", error)
658 )
659 }
660
661 #[test]
662 fn feature_collection_with_geom_collection() {
663 let geojson_str = json!({
664 "type": "FeatureCollection",
665 "features": [
666 {
667 "type": "Feature",
668 "geometry": {
669 "type": "GeometryCollection",
670 "geometries": [
671 {
672 "type": "Polygon",
673 "coordinates": [
674 [
675 [1.0, 1.0],
676 [2.0, 2.0],
677 [3.0, 1.0],
678 [1.0, 1.0]
679 ]
680 ]
681 }
682 ]
683 },
684 "properties": {}
685 }
686 ]
687 })
688 .to_string();
689 let geojson: crate::GeoJson = geojson_str.parse().unwrap();
690 let mut geojson_feature_collection: crate::FeatureCollection = geojson.try_into().unwrap();
691 let feature: crate::Feature = geojson_feature_collection.features.remove(0);
692
693 use std::convert::TryFrom;
694 let geo_geom = geo_types::Geometry::try_from(feature).unwrap();
695
696 let expected =
697 geo_types::Geometry::GeometryCollection(geo_types::GeometryCollection(vec![
698 geo_types::Geometry::Polygon(geo_types::Polygon::new(
699 geo_types::LineString::new(vec![
700 geo_types::coord!(x: 1.0, y: 1.0),
701 geo_types::coord!(x: 2.0, y: 2.0),
702 geo_types::coord!(x: 3.0, y: 1.0),
703 geo_types::coord!(x: 1.0, y: 1.0),
704 ]),
705 vec![],
706 )),
707 ]));
708 assert_eq!(geo_geom, expected);
709 }
710
711 #[test]
712 fn borrowed_value_conversions_test() -> crate::Result<()> {
713 let coord1 = vec![100.0, 0.2];
714 let coord2 = vec![101.0, 1.0];
715 let coord3 = vec![102.0, 0.8];
716 let coord4 = vec![104.0, 0.2];
717
718 let geojson_point = Value::Point(coord1.clone());
719 let _: geo_types::Point<f64> = (&geojson_point).try_into()?;
720
721 let geojson_multi_point = Value::MultiPoint(vec![coord1.clone(), coord2.clone()]);
722 let _: geo_types::MultiPoint<f64> = (&geojson_multi_point).try_into()?;
723
724 let geojson_line_string = Value::LineString(vec![coord1.clone(), coord2.clone()]);
725 let _: geo_types::LineString<f64> = (&geojson_line_string).try_into()?;
726
727 let geojson_multi_line_string = Value::MultiLineString(vec![
728 vec![coord1.clone(), coord2.clone()],
729 vec![coord2.clone(), coord3.clone()],
730 ]);
731 let _: geo_types::MultiLineString<f64> = (&geojson_multi_line_string).try_into()?;
732
733 let geojson_multi_line_string_type1 = vec![
734 vec![
735 coord1.clone(),
736 coord2.clone(),
737 coord3.clone(),
738 coord1.clone(),
739 ],
740 vec![
741 coord4.clone(),
742 coord1.clone(),
743 coord2.clone(),
744 coord4.clone(),
745 ],
746 ];
747 let geojson_polygon = Value::Polygon(geojson_multi_line_string_type1);
748 let _: geo_types::Polygon<f64> = (&geojson_polygon).try_into()?;
749
750 let geojson_line_string_type1 = vec![
751 coord1.clone(),
752 coord2.clone(),
753 coord3.clone(),
754 coord1.clone(),
755 ];
756
757 let geojson_line_string_type2 = vec![
758 coord4.clone(),
759 coord3.clone(),
760 coord2.clone(),
761 coord4.clone(),
762 ];
763 let geojson_multi_polygon = Value::MultiPolygon(vec![
764 vec![geojson_line_string_type1],
765 vec![geojson_line_string_type2],
766 ]);
767 let _: geo_types::MultiPolygon<f64> = (&geojson_multi_polygon).try_into()?;
768
769 let geojson_geometry_collection = Value::GeometryCollection(vec![
770 Geometry::new(geojson_multi_point),
771 Geometry::new(geojson_multi_line_string),
772 Geometry::new(geojson_multi_polygon),
773 ]);
774
775 let _: geo_types::GeometryCollection<f64> = (&geojson_geometry_collection).try_into()?;
776
777 Ok(())
778 }
779}