gistools/geometry/s2/
convert.rs

1use crate::geometry::{LonLat, S2Point};
2use s2json::{
3    Face, MValue, Properties, VectorFeature, VectorFeatureType, VectorGeometry, VectorPoint,
4};
5
6/// Underlying conversion mechanic to move S2 Geometry to GeoJSON Geometry
7pub trait ConvertVectorFeatureS2<
8    M: Clone = (),
9    P: Clone + Default = Properties,
10    D: Clone + Default = MValue,
11>
12{
13    /// Convert an S2 Feature to a GeoJSON Vector Feature
14    fn to_wm(&self) -> Self;
15}
16
17impl<M: Clone, P: Clone + Default, D: Clone + Default> ConvertVectorFeatureS2<M, P, D>
18    for VectorFeature<M, P, D>
19{
20    /// Convert an S2 Feature to a GeoJSON Vector Feature
21    fn to_wm(&self) -> Self {
22        if self._type == VectorFeatureType::VectorFeature {
23            return self.clone();
24        }
25        let mut geometry = self.geometry.clone();
26        convert_geometry(self.face, &mut geometry);
27        VectorFeature::<M, P, D>::new_wm(
28            self.id,
29            self.properties.clone(),
30            geometry,
31            self.metadata.clone(),
32        )
33    }
34}
35
36/// Underlying conversion mechanic to move S2Geometry to GeoJSON Geometry
37fn convert_geometry<M: Clone + Default>(face: Face, geometry: &mut VectorGeometry<M>) {
38    match geometry {
39        VectorGeometry::Point(point) => convert_geometry_point(face, &mut point.coordinates),
40        VectorGeometry::LineString(points) | VectorGeometry::MultiPoint(points) => {
41            points.coordinates.iter_mut().for_each(|point| convert_geometry_point(face, point))
42        }
43        VectorGeometry::Polygon(lines) | VectorGeometry::MultiLineString(lines) => lines
44            .coordinates
45            .iter_mut()
46            .for_each(|line| line.iter_mut().for_each(|point| convert_geometry_point(face, point))),
47        VectorGeometry::MultiPolygon(polygons) => {
48            polygons.coordinates.iter_mut().for_each(|polygon| {
49                polygon.iter_mut().for_each(|line| {
50                    line.iter_mut().for_each(|point| convert_geometry_point(face, point))
51                })
52            })
53        }
54    }
55}
56
57/// Mutate an S2 Point to a GeoJSON Point
58fn convert_geometry_point<M: Clone + Default>(face: Face, point: &mut VectorPoint<M>) {
59    let ll: LonLat = (&S2Point::from_face_st(face.into(), point.x, point.y)).into();
60    point.x = ll.lon();
61    point.y = ll.lat();
62}