s2json_core/geometry/
vector.rs

1use crate::*;
2use alloc::vec::Vec;
3use serde::{Deserialize, Serialize};
4
5/// Enum to represent specific vector geometry types as strings
6#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
7pub enum VectorGeometryType {
8    /// Point
9    #[default]
10    Point,
11    /// MultiPoint
12    MultiPoint,
13    /// LineString
14    LineString,
15    /// MultiLineString
16    MultiLineString,
17    /// Polygon
18    Polygon,
19    /// MultiPolygon
20    MultiPolygon,
21}
22impl From<&str> for VectorGeometryType {
23    fn from(s: &str) -> Self {
24        match s {
25            "Point" => VectorGeometryType::Point,
26            "MultiPoint" => VectorGeometryType::MultiPoint,
27            "LineString" => VectorGeometryType::LineString,
28            "MultiLineString" => VectorGeometryType::MultiLineString,
29            "Polygon" => VectorGeometryType::Polygon,
30            "MultiPolygon" => VectorGeometryType::MultiPolygon,
31            _ => panic!("Invalid vector geometry type: {}", s),
32        }
33    }
34}
35
36/// Definition of a Vector MultiPoint
37pub type VectorMultiPoint<M = MValue> = Vec<VectorPoint<M>>;
38/// Definition of a Vector LineString
39pub type VectorLineString<M = MValue> = Vec<VectorPoint<M>>;
40/// Definition of a Vector MultiLineString
41pub type VectorMultiLineString<M = MValue> = Vec<VectorLineString<M>>;
42/// Definition of a Vector Polygon
43pub type VectorPolygon<M = MValue> = Vec<VectorLineString<M>>;
44/// Definition of a Vector MultiPolygon
45pub type VectorMultiPolygon<M = MValue> = Vec<VectorPolygon<M>>;
46
47/// All possible geometry shapes
48#[derive(Clone, Serialize, Debug, PartialEq)]
49#[serde(untagged)]
50pub enum VectorGeometry<M: Clone + Default = MValue> {
51    /// Point Shape
52    Point(VectorPointGeometry<M>),
53    /// MultiPoint Shape
54    MultiPoint(VectorMultiPointGeometry<M>),
55    /// LineString Shape
56    LineString(VectorLineStringGeometry<M>),
57    /// MultiLineString Shape
58    MultiLineString(VectorMultiLineStringGeometry<M>),
59    /// Polygon Shape
60    Polygon(VectorPolygonGeometry<M>),
61    /// MultiPolygon Shape
62    MultiPolygon(VectorMultiPolygonGeometry<M>),
63}
64impl<M: Clone + Default> VectorGeometry<M> {
65    /// Get the bbox of the geometry
66    pub fn bbox(&self) -> &Option<BBox3D> {
67        match self {
68            VectorGeometry::Point(g) => &g.bbox,
69            VectorGeometry::MultiPoint(g) => &g.bbox,
70            VectorGeometry::LineString(g) => &g.bbox,
71            VectorGeometry::MultiLineString(g) => &g.bbox,
72            VectorGeometry::Polygon(g) => &g.bbox,
73            VectorGeometry::MultiPolygon(g) => &g.bbox,
74        }
75    }
76
77    /// Get the vec_bbox of the geometry
78    pub fn vec_bbox(&self) -> &Option<BBox3D> {
79        match self {
80            VectorGeometry::Point(g) => &g.vec_bbox,
81            VectorGeometry::MultiPoint(g) => &g.vec_bbox,
82            VectorGeometry::LineString(g) => &g.vec_bbox,
83            VectorGeometry::MultiLineString(g) => &g.vec_bbox,
84            VectorGeometry::Polygon(g) => &g.vec_bbox,
85            VectorGeometry::MultiPolygon(g) => &g.vec_bbox,
86        }
87    }
88
89    /// Get the geometry point
90    pub fn point(&self) -> Option<&VectorPoint<M>> {
91        match self {
92            VectorGeometry::Point(g) => Some(&g.coordinates),
93            _ => None,
94        }
95    }
96
97    /// Create a new point
98    pub fn new_point(coordinates: VectorPoint<M>, bbox: Option<BBox3D>) -> Self {
99        VectorGeometry::Point(VectorPointGeometry {
100            _type: VectorGeometryType::Point,
101            is_3d: coordinates.z.is_some(),
102            coordinates,
103            bbox,
104            ..Default::default()
105        })
106    }
107
108    /// Get the geometry multi point
109    pub fn multipoint(&self) -> Option<&VectorMultiPoint<M>> {
110        match self {
111            VectorGeometry::MultiPoint(g) => Some(&g.coordinates),
112            _ => None,
113        }
114    }
115
116    /// Create a new multipoint
117    pub fn new_multipoint(coordinates: VectorMultiPoint<M>, bbox: Option<BBox3D>) -> Self {
118        VectorGeometry::MultiPoint(VectorMultiPointGeometry {
119            _type: VectorGeometryType::MultiPoint,
120            is_3d: coordinates.iter().any(|point| point.z.is_some()),
121            coordinates,
122            bbox,
123            ..Default::default()
124        })
125    }
126
127    /// Get the geometry linestring
128    pub fn linestring(&self) -> Option<&VectorLineString<M>> {
129        match self {
130            VectorGeometry::LineString(g) => Some(&g.coordinates),
131            _ => None,
132        }
133    }
134
135    /// Create a new linestring
136    pub fn new_linestring(coordinates: VectorLineString<M>, bbox: Option<BBox3D>) -> Self {
137        VectorGeometry::LineString(VectorLineStringGeometry {
138            _type: VectorGeometryType::LineString,
139            is_3d: coordinates.iter().any(|point| point.z.is_some()),
140            coordinates,
141            bbox,
142            ..Default::default()
143        })
144    }
145
146    /// Get the geometry multilinestring
147    pub fn multilinestring(&self) -> Option<&VectorMultiLineString<M>> {
148        match self {
149            VectorGeometry::MultiLineString(g) => Some(&g.coordinates),
150            _ => None,
151        }
152    }
153
154    /// Create a new multilinestring
155    pub fn new_multilinestring(
156        coordinates: VectorMultiLineString<M>,
157        bbox: Option<BBox3D>,
158    ) -> Self {
159        VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
160            _type: VectorGeometryType::MultiLineString,
161            is_3d: coordinates.iter().any(|line| line.iter().any(|point| point.z.is_some())),
162            coordinates,
163            bbox,
164            ..Default::default()
165        })
166    }
167
168    /// Get the geometry polygon
169    pub fn polygon(&self) -> Option<&VectorPolygon<M>> {
170        match self {
171            VectorGeometry::Polygon(g) => Some(&g.coordinates),
172            _ => None,
173        }
174    }
175
176    /// Create a new polygon
177    pub fn new_polygon(coordinates: VectorPolygon<M>, bbox: Option<BBox3D>) -> Self {
178        VectorGeometry::Polygon(VectorPolygonGeometry {
179            _type: VectorGeometryType::Polygon,
180            is_3d: coordinates.iter().any(|ring| ring.iter().any(|point| point.z.is_some())),
181            coordinates,
182            bbox,
183            ..Default::default()
184        })
185    }
186
187    /// Get the geometry multipolygon
188    pub fn multipolygon(&self) -> Option<&VectorMultiPolygon<M>> {
189        match self {
190            VectorGeometry::MultiPolygon(g) => Some(&g.coordinates),
191            _ => None,
192        }
193    }
194
195    /// Create a new multipolygon
196    pub fn new_multipolygon(coordinates: VectorMultiPolygon<M>, bbox: Option<BBox3D>) -> Self {
197        VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
198            _type: VectorGeometryType::MultiPolygon,
199            is_3d: coordinates.iter().any(|polygon| {
200                polygon.iter().any(|ring| ring.iter().any(|point| point.z.is_some()))
201            }),
202            coordinates,
203            bbox,
204            ..Default::default()
205        })
206    }
207
208    /// set the tessellation of the geometry (polygon and multipolygon only)
209    pub fn set_tess(&mut self, tessellation: Vec<f64>) {
210        match self {
211            VectorGeometry::Polygon(g) => g.tessellation = Some(tessellation),
212            VectorGeometry::MultiPolygon(g) => g.tessellation = Some(tessellation),
213            _ => {}
214        }
215    }
216
217    /// set the indices of the geometry (polygon and multipolygon only)
218    pub fn set_indices(&mut self, indices: Vec<u32>) {
219        match self {
220            VectorGeometry::Polygon(g) => g.indices = Some(indices),
221            VectorGeometry::MultiPolygon(g) => g.indices = Some(indices),
222            _ => {}
223        }
224    }
225
226    /// Convert the geometry so that all m-values are MValue rather then user defined
227    pub fn to_m_geometry(&self) -> VectorGeometry<MValue>
228    where
229        M: MValueCompatible,
230    {
231        match self {
232            VectorGeometry::Point(g) => VectorGeometry::Point(VectorPointGeometry {
233                _type: g._type,
234                is_3d: g.is_3d,
235                coordinates: g.coordinates.to_m_value(),
236                offset: g.offset.clone(),
237                bbox: g.bbox,
238                vec_bbox: g.vec_bbox,
239                ..Default::default()
240            }),
241            VectorGeometry::MultiPoint(g) => VectorGeometry::MultiPoint(VectorMultiPointGeometry {
242                _type: g._type,
243                is_3d: g.is_3d,
244                coordinates: g.coordinates.iter().map(|point| point.to_m_value()).collect(),
245                offset: g.offset,
246                bbox: g.bbox,
247                vec_bbox: g.vec_bbox,
248                ..Default::default()
249            }),
250            VectorGeometry::LineString(g) => VectorGeometry::LineString(VectorLineStringGeometry {
251                _type: g._type,
252                is_3d: g.is_3d,
253                coordinates: g.coordinates.iter().map(|point| point.to_m_value()).collect(),
254                offset: g.offset,
255                bbox: g.bbox,
256                vec_bbox: g.vec_bbox,
257                ..Default::default()
258            }),
259            VectorGeometry::MultiLineString(g) => {
260                VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
261                    _type: g._type,
262                    is_3d: g.is_3d,
263                    coordinates: g
264                        .coordinates
265                        .iter()
266                        .map(|line| line.iter().map(|point| point.to_m_value()).collect())
267                        .collect(),
268                    offset: g.offset.clone(),
269                    bbox: g.bbox,
270                    vec_bbox: g.vec_bbox,
271                    ..Default::default()
272                })
273            }
274            VectorGeometry::Polygon(g) => VectorGeometry::Polygon(VectorPolygonGeometry {
275                _type: g._type,
276                is_3d: g.is_3d,
277                coordinates: g
278                    .coordinates
279                    .iter()
280                    .map(|ring| ring.iter().map(|point| point.to_m_value()).collect())
281                    .collect(),
282                offset: g.offset.clone(),
283                bbox: g.bbox,
284                vec_bbox: g.vec_bbox,
285                ..Default::default()
286            }),
287            VectorGeometry::MultiPolygon(g) => {
288                VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
289                    _type: g._type,
290                    is_3d: g.is_3d,
291                    coordinates: g
292                        .coordinates
293                        .iter()
294                        .map(|polygon| {
295                            polygon
296                                .iter()
297                                .map(|ring| ring.iter().map(|point| point.to_m_value()).collect())
298                                .collect()
299                        })
300                        .collect(),
301                    offset: g.offset.clone(),
302                    bbox: g.bbox,
303                    vec_bbox: g.vec_bbox,
304                    ..Default::default()
305                })
306            }
307        }
308    }
309}
310impl<M: Clone + Default> Default for VectorGeometry<M> {
311    fn default() -> Self {
312        VectorGeometry::Point(VectorPointGeometry::default())
313    }
314}
315
316/// BaseGeometry is the a generic geometry type
317#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
318pub struct VectorBaseGeometry<G = VectorGeometry, O = VectorOffsets> {
319    /// The geometry type
320    #[serde(rename = "type")]
321    pub _type: VectorGeometryType,
322    /// Specifies if the geometry is 3D or 2D
323    #[serde(rename = "is3D")]
324    pub is_3d: bool,
325    /// The geometry shape
326    pub coordinates: G,
327    /// The geometry offsets if applicable
328    #[serde(skip_serializing_if = "Option::is_none")]
329    pub offset: Option<O>,
330    /// The BBox shape - always in lon-lat
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub bbox: Option<BBox3D>,
333    /// temporary bbox to track 0->1 clipping
334    #[serde(skip)]
335    pub vec_bbox: Option<BBox3D>,
336    /// Polygon and MultiPolygon specific property
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub indices: Option<Vec<u32>>,
339    /// Polygon and MultiPolygon specific property
340    #[serde(skip_serializing_if = "Option::is_none")]
341    pub tessellation: Option<Vec<f64>>,
342}
343
344/// All possible geometry offsets
345#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
346pub enum VectorOffsets {
347    /// LineString offset
348    LineOffset(VectorLineOffset),
349    /// MultiLineString offset
350    MultiLineOffset(VectorMultiLineOffset),
351    /// Polygon offset
352    PolygonOffset(VectorPolygonOffset),
353    /// MultiPolygon offset
354    MultiPolygonOffset(VectorMultiPolygonOffset),
355}
356impl Default for VectorOffsets {
357    fn default() -> Self {
358        VectorOffsets::LineOffset(0.0)
359    }
360}
361/// An offset defines how far the starting line is from the original starting point pre-slice
362pub type VectorLineOffset = f64;
363/// A collection of offsets
364pub type VectorMultiLineOffset = Vec<VectorLineOffset>;
365/// A collection of offsets
366pub type VectorPolygonOffset = VectorMultiLineOffset;
367/// A collection of collections of offsets
368pub type VectorMultiPolygonOffset = Vec<VectorPolygonOffset>;
369
370/// PointGeometry is a point
371pub type VectorPointGeometry<M = MValue> = VectorBaseGeometry<VectorPoint<M>>;
372/// MultiPointGeometry contains multiple points
373pub type VectorMultiPointGeometry<M = MValue> =
374    VectorBaseGeometry<VectorMultiPoint<M>, VectorLineOffset>;
375/// LineStringGeometry is a line
376pub type VectorLineStringGeometry<M = MValue> =
377    VectorBaseGeometry<VectorLineString<M>, VectorLineOffset>;
378/// MultiLineStringGeometry contains multiple lines
379pub type VectorMultiLineStringGeometry<M = MValue> =
380    VectorBaseGeometry<VectorMultiLineString<M>, VectorMultiLineOffset>;
381/// PolygonGeometry is a polygon with potential holes
382pub type VectorPolygonGeometry<M = MValue> =
383    VectorBaseGeometry<VectorPolygon<M>, VectorPolygonOffset>;
384/// MultiPolygonGeometry is a polygon with multiple polygons with their own potential holes
385pub type VectorMultiPolygonGeometry<M = MValue> =
386    VectorBaseGeometry<VectorMultiPolygon<M>, VectorMultiPolygonOffset>;