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}
226impl<M: Clone + Default> Default for VectorGeometry<M> {
227    fn default() -> Self {
228        VectorGeometry::Point(VectorPointGeometry::default())
229    }
230}
231
232/// BaseGeometry is the a generic geometry type
233#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
234pub struct VectorBaseGeometry<G = VectorGeometry, O = VectorOffsets> {
235    /// The geometry type
236    #[serde(rename = "type")]
237    pub _type: VectorGeometryType,
238    /// Specifies if the geometry is 3D or 2D
239    #[serde(rename = "is3D")]
240    pub is_3d: bool,
241    /// The geometry shape
242    pub coordinates: G,
243    /// The geometry offsets if applicable
244    #[serde(skip_serializing_if = "Option::is_none")]
245    pub offset: Option<O>,
246    /// The BBox shape - always in lon-lat
247    #[serde(skip_serializing_if = "Option::is_none")]
248    pub bbox: Option<BBox3D>,
249    /// temporary bbox to track 0->1 clipping
250    #[serde(skip)]
251    pub vec_bbox: Option<BBox3D>,
252    /// Polygon and MultiPolygon specific property
253    #[serde(skip_serializing_if = "Option::is_none")]
254    pub indices: Option<Vec<u32>>,
255    /// Polygon and MultiPolygon specific property
256    #[serde(skip_serializing_if = "Option::is_none")]
257    pub tessellation: Option<Vec<f64>>,
258}
259
260/// All possible geometry offsets
261#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
262pub enum VectorOffsets {
263    /// LineString offset
264    LineOffset(VectorLineOffset),
265    /// MultiLineString offset
266    MultiLineOffset(VectorMultiLineOffset),
267    /// Polygon offset
268    PolygonOffset(VectorPolygonOffset),
269    /// MultiPolygon offset
270    MultiPolygonOffset(VectorMultiPolygonOffset),
271}
272impl Default for VectorOffsets {
273    fn default() -> Self {
274        VectorOffsets::LineOffset(0.0)
275    }
276}
277/// An offset defines how far the starting line is from the original starting point pre-slice
278pub type VectorLineOffset = f64;
279/// A collection of offsets
280pub type VectorMultiLineOffset = Vec<VectorLineOffset>;
281/// A collection of offsets
282pub type VectorPolygonOffset = VectorMultiLineOffset;
283/// A collection of collections of offsets
284pub type VectorMultiPolygonOffset = Vec<VectorPolygonOffset>;
285
286/// PointGeometry is a point
287pub type VectorPointGeometry<M = MValue> = VectorBaseGeometry<VectorPoint<M>>;
288/// MultiPointGeometry contains multiple points
289pub type VectorMultiPointGeometry<M = MValue> =
290    VectorBaseGeometry<VectorMultiPoint<M>, VectorLineOffset>;
291/// LineStringGeometry is a line
292pub type VectorLineStringGeometry<M = MValue> =
293    VectorBaseGeometry<VectorLineString<M>, VectorLineOffset>;
294/// MultiLineStringGeometry contains multiple lines
295pub type VectorMultiLineStringGeometry<M = MValue> =
296    VectorBaseGeometry<VectorMultiLineString<M>, VectorMultiLineOffset>;
297/// PolygonGeometry is a polygon with potential holes
298pub type VectorPolygonGeometry<M = MValue> =
299    VectorBaseGeometry<VectorPolygon<M>, VectorPolygonOffset>;
300/// MultiPolygonGeometry is a polygon with multiple polygons with their own potential holes
301pub type VectorMultiPolygonGeometry<M = MValue> =
302    VectorBaseGeometry<VectorMultiPolygon<M>, VectorMultiPolygonOffset>;