geos/
to_geo.rs

1use crate::error::Error;
2use crate::{ConstGeometry, Geom, Geometry as GGeometry};
3use geo_types::Geometry;
4use wkt;
5use wkt::TryFromWkt;
6
7use std::convert::TryFrom;
8
9macro_rules! impl_try_into {
10    ($ty_name:ident $(,$lt:lifetime)?) => (
11impl<'b$(,$lt)?> TryFrom<&'b $ty_name$(<$lt>)?> for Geometry<f64> {
12    type Error = Error;
13
14    fn try_from(other: &'b $ty_name$(<$lt>)?) -> Result<Geometry<f64>, Self::Error> {
15        // This is a first draft, it's very inefficient, we use wkt as a pivot format to
16        // translate the geometry.
17        // We should at least use wkb, or even better implement a direct translation
18        let wkt_str = other.to_wkt()?;
19        geo_types::Geometry::try_from_wkt_str(&wkt_str)
20            .map_err(|e| Error::ConversionError(format!("impossible to read wkt: {}", e)))
21    }
22}
23impl$(<$lt>)? TryFrom<$ty_name$(<$lt>)?> for Geometry<f64> {
24    type Error = Error;
25
26    fn try_from(other: $ty_name$(<$lt>)?) -> Result<Geometry<f64>, Self::Error> {
27        Geometry::try_from(&other)
28    }
29}
30    );
31}
32
33impl_try_into!(GGeometry);
34impl_try_into!(ConstGeometry, 'c);
35
36#[cfg(test)]
37mod test {
38    use crate::Geometry as GGeometry;
39    use geo_types::{Coordinate, Geometry, LineString, MultiPoint, MultiPolygon, Point, Polygon};
40    use std::convert::TryInto;
41
42    fn coords(tuples: Vec<(f64, f64)>) -> Vec<Coordinate<f64>> {
43        tuples.into_iter().map(Coordinate::from).collect()
44    }
45
46    #[test]
47    fn geom_to_geo_polygon() {
48        let poly = "MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))";
49        let poly = GGeometry::new_from_wkt(poly).unwrap();
50
51        let geo_polygon: Geometry<f64> = (&poly).try_into().unwrap();
52
53        let exterior = LineString(coords(vec![
54            (0., 0.),
55            (0., 1.),
56            (1., 1.),
57            (1., 0.),
58            (0., 0.),
59        ]));
60        let expected_poly = MultiPolygon(vec![Polygon::new(exterior, vec![])]);
61        let expected: Geometry<_> = expected_poly.into();
62        assert_eq!(expected, geo_polygon);
63        // This check is to enforce that `TryFrom` is implemented for both reference and value.
64        assert_eq!(expected, poly.try_into().unwrap());
65    }
66
67    #[test]
68    fn geom_to_geo_multipoint() {
69        let mp = "MULTIPOINT (0 0, 1 1)";
70        let mp = GGeometry::new_from_wkt(mp).unwrap();
71
72        let geo_multipoint: Geometry<f64> = (&mp).try_into().unwrap();
73
74        let expected_multipoint = MultiPoint(vec![
75            Point(Coordinate::from((0., 0.))),
76            Point(Coordinate::from((1., 1.))),
77        ]);
78        let expected: Geometry<_> = expected_multipoint.into();
79        assert_eq!(expected, geo_multipoint);
80        // This check is to enforce that `TryFrom` is implemented for both reference and value.
81        assert_eq!(expected, mp.try_into().unwrap());
82    }
83}