gistools/geometry/wm/convert/
flat.rs

1use s2json::{
2    BBox3D, Geometry, GeometryType, LineString3DGeometry, LineStringGeometry,
3    MultiLineString3DGeometry, MultiLineStringGeometry, MultiPoint3DGeometry, MultiPointGeometry,
4    MultiPolygon3DGeometry, MultiPolygonGeometry, Point, Point3D, Point3DGeometry, PointGeometry,
5    Polygon3DGeometry, PolygonGeometry, VectorGeometry, VectorLineStringGeometry,
6    VectorMultiLineStringGeometry, VectorMultiPointGeometry, VectorMultiPolygonGeometry,
7    VectorPointGeometry, VectorPolygonGeometry,
8};
9
10/// Convert a GeoJSON Geometry to an Vector Geometry
11pub fn convert_vector_to_geometry<M: Clone + Default>(
12    geometry: &VectorGeometry<M>,
13    build_bbox: bool,
14) -> Geometry<M> {
15    let bbox = if build_bbox { Some(BBox3D::default()) } else { None };
16    match geometry {
17        VectorGeometry::Point(geo) => to_point(geo, bbox),
18        VectorGeometry::MultiPoint(geo) => to_points(geo, bbox),
19        VectorGeometry::LineString(geo) => to_linestring(geo, bbox),
20        VectorGeometry::MultiLineString(geo) => to_linestrings(geo, bbox),
21        VectorGeometry::Polygon(geo) => to_polygon(geo, bbox),
22        VectorGeometry::MultiPolygon(geo) => to_polygons(geo, bbox),
23    }
24}
25
26/// Mutate a GeoJSON Vector Point to a GeoJSON Point or Point3D
27fn to_point<M: Clone + Default>(
28    point: &VectorPointGeometry<M>,
29    mut bbox: Option<BBox3D>,
30) -> Geometry<M> {
31    let coords = &point.coordinates;
32    if let Some(b) = bbox.as_mut() {
33        b.extend_from_point(coords);
34    }
35    if point.is_3d {
36        Geometry::Point3D(Point3DGeometry::<M> {
37            _type: GeometryType::Point3D,
38            coordinates: Point3D(coords.x, coords.y, coords.z.unwrap_or_default()),
39            m_values: coords.m.clone(),
40            bbox,
41        })
42    } else {
43        Geometry::Point(PointGeometry::<M> {
44            _type: GeometryType::Point,
45            coordinates: Point(coords.x, coords.y),
46            m_values: coords.m.clone(),
47            bbox: bbox.map(|b| b.into()),
48        })
49    }
50}
51
52/// Mutate a GeoJSON Vector MultiPoint to a GeoJSON MultiPoint/MultiPoint3D
53fn to_points<M: Clone + Default>(
54    points: &VectorMultiPointGeometry<M>,
55    mut bbox: Option<BBox3D>,
56) -> Geometry<M> {
57    let coords = &points.coordinates;
58    if let Some(b) = bbox.as_mut() {
59        coords.iter().for_each(|p| b.extend_from_point(p));
60    }
61    let m_values = coords.iter().map(|p| p.m.clone()).collect();
62    if points.is_3d {
63        Geometry::MultiPoint3D(MultiPoint3DGeometry::<M> {
64            _type: GeometryType::MultiPoint3D,
65            coordinates: coords
66                .iter()
67                .map(|p| Point3D(p.x, p.y, p.z.unwrap_or_default()))
68                .collect(),
69            m_values,
70            bbox,
71        })
72    } else {
73        Geometry::MultiPoint(MultiPointGeometry::<M> {
74            _type: GeometryType::MultiPoint,
75            coordinates: coords.iter().map(|p| Point(p.x, p.y)).collect(),
76            m_values,
77            bbox: bbox.map(|b| b.into()),
78        })
79    }
80}
81
82/// Mutate a GeoJSON Vector LineString to a GeoJSON LineString/LineString3D
83fn to_linestring<M: Clone + Default>(
84    linestring: &VectorLineStringGeometry<M>,
85    mut bbox: Option<BBox3D>,
86) -> Geometry<M> {
87    let coords = &linestring.coordinates;
88    if let Some(b) = bbox.as_mut() {
89        coords.iter().for_each(|p| b.extend_from_point(p));
90    }
91    let m_values = coords.iter().map(|p| p.m.clone()).collect();
92    if linestring.is_3d {
93        Geometry::LineString3D(LineString3DGeometry {
94            _type: GeometryType::LineString3D,
95            coordinates: coords
96                .iter()
97                .map(|p| Point3D(p.x, p.y, p.z.unwrap_or_default()))
98                .collect(),
99            m_values,
100            bbox,
101        })
102    } else {
103        Geometry::LineString(LineStringGeometry {
104            _type: GeometryType::LineString,
105            coordinates: coords.iter().map(|p| Point(p.x, p.y)).collect(),
106            m_values,
107            bbox: bbox.map(|b| b.into()),
108        })
109    }
110}
111
112/// Mutate a GeoJSON Vector MultiLineString to a GeoJSON MultiLineString/MultiLineString3D
113fn to_linestrings<M: Clone + Default>(
114    linestrings: &VectorMultiLineStringGeometry<M>,
115    mut bbox: Option<BBox3D>,
116) -> Geometry<M> {
117    let coords = &linestrings.coordinates;
118    if let Some(b) = bbox.as_mut() {
119        coords.iter().for_each(|l| l.iter().for_each(|p| b.extend_from_point(p)));
120    }
121    let m_values = coords.iter().map(|l| l.iter().map(|p| p.m.clone()).collect()).collect();
122    if linestrings.is_3d {
123        Geometry::MultiLineString3D(MultiLineString3DGeometry {
124            _type: GeometryType::MultiLineString3D,
125            coordinates: coords
126                .iter()
127                .map(|l| l.iter().map(|p| Point3D(p.x, p.y, p.z.unwrap_or_default())).collect())
128                .collect(),
129            m_values,
130            bbox,
131        })
132    } else {
133        Geometry::MultiLineString(MultiLineStringGeometry {
134            _type: GeometryType::MultiLineString,
135            coordinates: coords
136                .iter()
137                .map(|l| l.iter().map(|p| Point(p.x, p.y)).collect())
138                .collect(),
139            m_values,
140            bbox: bbox.map(|b| b.into()),
141        })
142    }
143}
144
145/// Mutate a GeoJSON Vector Polygon to a GeoJSON Polygon/Polygon3D
146fn to_polygon<M: Clone + Default>(
147    polygon: &VectorPolygonGeometry<M>,
148    mut bbox: Option<BBox3D>,
149) -> Geometry<M> {
150    let coords = &polygon.coordinates;
151    if let Some(b) = bbox.as_mut() {
152        coords.iter().for_each(|r| r.iter().for_each(|p| b.extend_from_point(p)));
153    }
154    let m_values = coords.iter().map(|r| r.iter().map(|p| p.m.clone()).collect()).collect();
155    if polygon.is_3d {
156        Geometry::Polygon3D(Polygon3DGeometry {
157            _type: GeometryType::Polygon3D,
158            coordinates: coords
159                .iter()
160                .map(|r| r.iter().map(|p| Point3D(p.x, p.y, p.z.unwrap_or_default())).collect())
161                .collect(),
162            m_values,
163            bbox,
164        })
165    } else {
166        Geometry::Polygon(PolygonGeometry {
167            _type: GeometryType::Polygon,
168            coordinates: coords
169                .iter()
170                .map(|r| r.iter().map(|p| Point(p.x, p.y)).collect())
171                .collect(),
172            m_values,
173            bbox: bbox.map(|b| b.into()),
174        })
175    }
176}
177
178/// Mutate a GeoJSON Vector MultiPolygon to a GeoJSON MultiPolygon/MultiPolygon3D
179fn to_polygons<M: Clone + Default>(
180    polygons: &VectorMultiPolygonGeometry<M>,
181    mut bbox: Option<BBox3D>,
182) -> Geometry<M> {
183    let coords = &polygons.coordinates;
184    if let Some(b) = bbox.as_mut() {
185        coords
186            .iter()
187            .for_each(|p| p.iter().for_each(|r| r.iter().for_each(|p| b.extend_from_point(p))));
188    }
189    let m_values = coords
190        .iter()
191        .map(|p| p.iter().map(|r| r.iter().map(|p| p.m.clone()).collect()).collect())
192        .collect();
193    if polygons.is_3d {
194        Geometry::MultiPolygon3D(MultiPolygon3DGeometry {
195            _type: GeometryType::MultiPolygon3D,
196            coordinates: coords
197                .iter()
198                .map(|p| {
199                    p.iter()
200                        .map(|r| {
201                            r.iter().map(|p| Point3D(p.x, p.y, p.z.unwrap_or_default())).collect()
202                        })
203                        .collect()
204                })
205                .collect(),
206            m_values,
207            bbox,
208        })
209    } else {
210        Geometry::MultiPolygon(MultiPolygonGeometry {
211            _type: GeometryType::MultiPolygon,
212            coordinates: coords
213                .iter()
214                .map(|p| p.iter().map(|r| r.iter().map(|p| Point(p.x, p.y)).collect()).collect())
215                .collect(),
216            m_values,
217            bbox: bbox.map(|b| b.into()),
218        })
219    }
220}