gistools/geometry/wm/convert/
mod.rs

1mod flat;
2mod s2;
3mod vector;
4
5use crate::geometry::ConvertVectorFeatureS2;
6use alloc::{vec, vec::Vec};
7pub use flat::*;
8pub use s2::*;
9use s2json::{
10    BBox3D, Feature, MValue, Properties, VectorFeature, VectorFeatureType, VectorGeometry,
11};
12pub use vector::*;
13
14/// Underlying conversion mechanic to move GeoJSON Feature to GeoJSON Vector Feature
15pub trait ConvertFeature<
16    M: Clone = (),
17    P: Clone + Default = Properties,
18    D: Clone + Default = MValue,
19>
20{
21    /// Convert a GeoJSON Feature to a GeoJSON Vector Feature
22    fn to_vector(&self, build_bbox: Option<bool>) -> VectorFeature<M, P, D>;
23}
24
25impl<M: Clone, P: Clone + Default, D: Clone + Default> ConvertFeature<M, P, D>
26    for Feature<M, P, D>
27{
28    /// Convert a GeoJSON Feature to a GeoJSON Vector Feature
29    fn to_vector(&self, build_bbox: Option<bool>) -> VectorFeature<M, P, D> {
30        let build_bbox = build_bbox.unwrap_or(false);
31        let Feature { id, properties, metadata, geometry, .. } = self;
32        let vector_geo = convert_geometry_to_vector(geometry, build_bbox);
33        VectorFeature::new_wm(*id, properties.clone(), vector_geo, metadata.clone())
34    }
35}
36
37/// Underlying conversion mechanic to move GeoJSON Geometry to S2 Geometry
38pub trait ConvertVectorFeatureWM<
39    M: Clone = (),
40    P: Clone + Default = Properties,
41    D: Clone + Default = MValue,
42>
43{
44    /// Reproject GeoJSON geometry coordinates from lon-lat to a 0->1 coordinate system in place
45    fn to_unit_scale(&mut self);
46    /// Convert a 0->1 coordinate system to lon-lat
47    fn to_ll(&mut self);
48    /// Convert a GeoJSON Vector Feature to an S2 Feature
49    fn to_s2(&self) -> Vec<VectorFeature<M, P, D>>;
50    /// Convert a GeoJSON VectorFeature to a "flat" GeoJSON Feature
51    fn to_feature(&self, build_bbox: bool) -> Feature<M, P, D>;
52}
53
54impl<M: Clone, P: Clone + Default, D: Clone + Default> ConvertVectorFeatureWM<M, P, D>
55    for VectorFeature<M, P, D>
56{
57    /// Reproject GeoJSON geometry coordinates from lon-lat to a 0->1 coordinate system in place
58    fn to_unit_scale(&mut self) {
59        let mut bbox = BBox3D::default();
60        match &mut self.geometry {
61            VectorGeometry::Point(geo) => {
62                geo.coordinates.project(Some(&mut bbox));
63                geo.vec_bbox = Some(bbox);
64            }
65            VectorGeometry::LineString(geo) | VectorGeometry::MultiPoint(geo) => {
66                geo.coordinates.iter_mut().for_each(|p| p.project(Some(&mut bbox)));
67                geo.vec_bbox = Some(bbox);
68            }
69            VectorGeometry::Polygon(geo) | VectorGeometry::MultiLineString(geo) => {
70                geo.coordinates
71                    .iter_mut()
72                    .for_each(|p| p.iter_mut().for_each(|p| p.project(Some(&mut bbox))));
73                geo.vec_bbox = Some(bbox);
74            }
75            VectorGeometry::MultiPolygon(geo) => {
76                geo.coordinates.iter_mut().for_each(|p| {
77                    p.iter_mut().for_each(|p| p.iter_mut().for_each(|p| p.project(Some(&mut bbox))))
78                });
79                geo.vec_bbox = Some(bbox);
80            }
81        }
82    }
83
84    /// Reproject GeoJSON geometry coordinates from lon-lat to a 0->1 coordinate system in place
85    fn to_ll(&mut self) {
86        match &mut self.geometry {
87            VectorGeometry::Point(geo) => {
88                geo.coordinates.unproject();
89            }
90            VectorGeometry::LineString(geo) | VectorGeometry::MultiPoint(geo) => {
91                geo.coordinates.iter_mut().for_each(|p| p.unproject());
92            }
93            VectorGeometry::Polygon(geo) | VectorGeometry::MultiLineString(geo) => {
94                geo.coordinates.iter_mut().for_each(|p| p.iter_mut().for_each(|p| p.unproject()));
95            }
96            VectorGeometry::MultiPolygon(geo) => {
97                geo.coordinates.iter_mut().for_each(|p| {
98                    p.iter_mut().for_each(|p| p.iter_mut().for_each(|p| p.unproject()))
99                });
100            }
101        }
102    }
103
104    /// Convet a GeoJSON Feature to an S2Feature
105    fn to_s2(&self) -> Vec<VectorFeature<M, P, D>> {
106        let VectorFeature { _type, id, properties, metadata, geometry, .. } = self;
107        let mut res: Vec<VectorFeature<M, P, D>> = vec![];
108
109        if *_type == VectorFeatureType::S2Feature {
110            res.push(self.clone());
111        } else {
112            let vector_geo = convert_geometry_wm_to_s2(geometry);
113            for ConvertedGeometry { geometry, face } in vector_geo {
114                res.push(VectorFeature::<M, P, D>::new_s2(
115                    *id,
116                    face,
117                    properties.clone(),
118                    geometry,
119                    metadata.clone(),
120                ));
121            }
122        }
123
124        res
125    }
126
127    /// Convert a GeoJSON VectorFeature to a "flat" GeoJSON Feature
128    fn to_feature(&self, build_bbox: bool) -> Feature<M, P, D> {
129        if self._type == VectorFeatureType::S2Feature {
130            let VectorFeature { id, properties, metadata, geometry, .. } = &self.to_wm();
131            let geo = convert_vector_to_geometry(geometry, build_bbox);
132            Feature::new(*id, properties.clone(), geo, metadata.clone())
133        } else {
134            let VectorFeature { id, properties, metadata, geometry, .. } = self;
135            let geo = convert_vector_to_geometry(geometry, build_bbox);
136            Feature::new(*id, properties.clone(), geo, metadata.clone())
137        }
138    }
139}