gistools/geometry/wm/convert/
vector.rs

1use alloc::{vec, vec::Vec};
2use s2json::{
3    BBox3D, BaseGeometry, Geometry, LineStringMValues, MultiLineStringMValues, MultiPolygonMValues,
4    PointOrPoint3D, VectorGeometry, VectorPoint,
5};
6
7// TODO: Consider taking m-value data rather then clones
8
9/// Convert a GeoJSON Geometry to an Vector Geometry
10pub fn convert_geometry_to_vector<M: Clone + Default>(
11    geometry: &Geometry<M>,
12    build_bbox: bool,
13) -> VectorGeometry<M> {
14    let mut bbox = if build_bbox { Some(BBox3D::default()) } else { None };
15    match geometry {
16        Geometry::Point(geo) => {
17            let coords = to_vector_point(geo, &mut bbox);
18            VectorGeometry::new_point(coords, bbox)
19        }
20        Geometry::Point3D(geo) => {
21            let coords = to_vector_point(geo, &mut bbox);
22            VectorGeometry::new_point(coords, bbox)
23        }
24        Geometry::MultiPoint(geo) => {
25            let coords = to_vector_multipoint(geo, &mut bbox);
26            VectorGeometry::new_multipoint(coords, bbox)
27        }
28        Geometry::MultiPoint3D(geo) => {
29            let coords = to_vector_multipoint(geo, &mut bbox);
30            VectorGeometry::new_multipoint(coords, bbox)
31        }
32        Geometry::LineString(geo) => {
33            let coords = to_vector_multipoint(geo, &mut bbox);
34            VectorGeometry::new_linestring(coords, bbox)
35        }
36        Geometry::LineString3D(geo) => {
37            let coords = to_vector_multipoint(geo, &mut bbox);
38            VectorGeometry::new_linestring(coords, bbox)
39        }
40        Geometry::MultiLineString(geo) => {
41            let coords = to_vector_multilinestring(geo, &mut bbox);
42            VectorGeometry::new_multilinestring(coords, bbox)
43        }
44        Geometry::MultiLineString3D(geo) => {
45            let coords = to_vector_multilinestring(geo, &mut bbox);
46            VectorGeometry::new_multilinestring(coords, bbox)
47        }
48        Geometry::Polygon(geo) => {
49            let coords = to_vector_multilinestring(geo, &mut bbox);
50            VectorGeometry::new_polygon(coords, bbox)
51        }
52        Geometry::Polygon3D(geo) => {
53            let coords = to_vector_multilinestring(geo, &mut bbox);
54            VectorGeometry::new_polygon(coords, bbox)
55        }
56        Geometry::MultiPolygon(geo) => {
57            let coords = to_vector_multipolygon(geo, &mut bbox);
58            VectorGeometry::new_multipolygon(coords, bbox)
59        }
60        Geometry::MultiPolygon3D(geo) => {
61            let coords = to_vector_multipolygon(geo, &mut bbox);
62            VectorGeometry::new_multipolygon(coords, bbox)
63        }
64    }
65}
66
67fn convert_point<M: Clone + Default>(
68    point: PointOrPoint3D,
69    m: Option<M>,
70    bbox: &mut Option<BBox3D>,
71) -> VectorPoint<M> {
72    let new_point = VectorPoint::new(point.0, point.1, point.2, m);
73    if let Some(b) = bbox {
74        b.extend_from_point(&new_point);
75    }
76    new_point
77}
78
79fn to_vector_point<M: Clone + Default, G: Copy, B>(
80    geo: &BaseGeometry<M, G, B>,
81    bbox: &mut Option<BBox3D>,
82) -> VectorPoint<M>
83where
84    PointOrPoint3D: core::convert::From<G>,
85{
86    convert_point(geo.coordinates.into(), geo.m_values.clone(), bbox)
87}
88
89fn to_vector_multipoint<M: Clone + Default, G: Copy, B>(
90    geo: &BaseGeometry<LineStringMValues<M>, Vec<G>, B>,
91    bbox: &mut Option<BBox3D>,
92) -> Vec<VectorPoint<M>>
93where
94    PointOrPoint3D: core::convert::From<G>,
95{
96    let binding = vec![];
97    let m_values = geo.m_values.as_ref().unwrap_or(&binding);
98    geo.coordinates
99        .iter()
100        .enumerate()
101        .map(|(i, p)| convert_point((*p).into(), m_values.get(i).cloned(), bbox))
102        .collect()
103}
104
105fn to_vector_multilinestring<M: Clone + Default, G: Copy, B>(
106    geo: &BaseGeometry<MultiLineStringMValues<M>, Vec<Vec<G>>, B>,
107    bbox: &mut Option<BBox3D>,
108) -> Vec<Vec<VectorPoint<M>>>
109where
110    PointOrPoint3D: core::convert::From<G>,
111{
112    let binding = vec![];
113    let m_values = geo.m_values.as_ref().unwrap_or(&binding);
114    geo.coordinates
115        .iter()
116        .enumerate()
117        .map(|(i, line)| {
118            line.iter()
119                .enumerate()
120                .map(|(j, p)| {
121                    let m_value = m_values.get(i).and_then(|m| m.get(j)).cloned();
122                    convert_point((*p).into(), m_value, bbox)
123                })
124                .collect()
125        })
126        .collect()
127}
128
129fn to_vector_multipolygon<M: Clone + Default, G: Copy, B>(
130    geo: &BaseGeometry<MultiPolygonMValues<M>, Vec<Vec<Vec<G>>>, B>,
131    bbox: &mut Option<BBox3D>,
132) -> Vec<Vec<Vec<VectorPoint<M>>>>
133where
134    PointOrPoint3D: core::convert::From<G>,
135{
136    let binding = vec![];
137    let m_values = geo.m_values.as_ref().unwrap_or(&binding);
138    geo.coordinates
139        .iter()
140        .enumerate()
141        .map(|(i, polygon)| {
142            polygon
143                .iter()
144                .enumerate()
145                .map(|(j, line)| {
146                    line.iter()
147                        .enumerate()
148                        .map(|(k, p)| {
149                            let m_value = m_values
150                                .get(i)
151                                .and_then(|m| m.get(j))
152                                .and_then(|m| m.get(k))
153                                .cloned();
154                            convert_point((*p).into(), m_value, bbox)
155                        })
156                        .collect()
157                })
158                .collect()
159        })
160        .collect()
161}