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: MValueCompatible = 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}
64#[doc(hidden)]
65#[allow(unused_extern_crates, clippy::useless_attribute)]
66extern crate serde as _serde;
67#[automatically_derived]
68#[coverage(off)]
69impl<'de, M: MValueCompatible> _serde::Deserialize<'de> for VectorGeometry<M>
70where
71    M: _serde::Deserialize<'de>,
72{
73    fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
74    where
75        __D: _serde::Deserializer<'de>,
76    {
77        let __content =
78            <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?;
79        let __deserializer =
80            _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
81        if let _serde::__private::Ok(__ok) = _serde::__private::Result::map(
82            <VectorPointGeometry<M> as _serde::Deserialize>::deserialize(__deserializer),
83            VectorGeometry::Point,
84        ) {
85            return _serde::__private::Ok(__ok);
86        }
87        // Attempt to deserialize as MultiPoint, then check for LineString
88        if let _serde::__private::Ok(__ok) = _serde::__private::Result::map(
89            <VectorMultiPointGeometry<M> as _serde::Deserialize>::deserialize(__deserializer),
90            VectorGeometry::MultiPoint,
91        ) {
92            // pull out the MultiPoint variant
93            if let VectorGeometry::MultiPoint(multipoint) = &__ok {
94                if multipoint._type == VectorGeometryType::LineString {
95                    // If deserialization succeeds as MultiPoint, check if content is LineString
96                    if let _serde::__private::Ok(__ok2) = _serde::__private::Result::map(
97                        <VectorLineStringGeometry<M> as _serde::Deserialize>::deserialize(
98                            __deserializer,
99                        ),
100                        VectorGeometry::LineString,
101                    ) {
102                        // If LineString is found, return LineString variant
103                        return _serde::__private::Ok(__ok2);
104                    }
105                }
106            }
107            return _serde::__private::Ok(__ok);
108        }
109        // Attempt to deserialize as MultiLineString, then check for Polygon
110        if let _serde::__private::Ok(__ok) = _serde::__private::Result::map(
111            <VectorMultiLineStringGeometry<M> as _serde::Deserialize>::deserialize(__deserializer),
112            VectorGeometry::MultiLineString,
113        ) {
114            // pull out the MultiLineString variant
115            if let VectorGeometry::MultiLineString(multilinestring) = &__ok {
116                if multilinestring._type == VectorGeometryType::Polygon {
117                    // If deserialization succeeds as MultiLineString, check if content is Polygon
118                    if let _serde::__private::Ok(__ok2) = _serde::__private::Result::map(
119                        <VectorPolygonGeometry<M> as _serde::Deserialize>::deserialize(
120                            __deserializer,
121                        ),
122                        VectorGeometry::Polygon,
123                    ) {
124                        // If Polygon is found, return Polygon variant
125                        return _serde::__private::Ok(__ok2);
126                    }
127                }
128            }
129            return _serde::__private::Ok(__ok);
130        }
131        if let _serde::__private::Ok(__ok) = _serde::__private::Result::map(
132            <VectorMultiPolygonGeometry<M> as _serde::Deserialize>::deserialize(__deserializer),
133            VectorGeometry::MultiPolygon,
134        ) {
135            return _serde::__private::Ok(__ok);
136        }
137        _serde::__private::Err(_serde::de::Error::custom(
138            "data did not match any variant of untagged enum VectorGeometry",
139        ))
140    }
141}
142impl<M: MValueCompatible> VectorGeometry<M> {
143    /// Get the bbox of the geometry
144    pub fn bbox(&self) -> &Option<BBox3D> {
145        match self {
146            VectorGeometry::Point(g) => &g.bbox,
147            VectorGeometry::MultiPoint(g) => &g.bbox,
148            VectorGeometry::LineString(g) => &g.bbox,
149            VectorGeometry::MultiLineString(g) => &g.bbox,
150            VectorGeometry::Polygon(g) => &g.bbox,
151            VectorGeometry::MultiPolygon(g) => &g.bbox,
152        }
153    }
154
155    /// Get the vec_bbox of the geometry
156    pub fn vec_bbox(&self) -> &Option<BBox3D> {
157        match self {
158            VectorGeometry::Point(g) => &g.vec_bbox,
159            VectorGeometry::MultiPoint(g) => &g.vec_bbox,
160            VectorGeometry::LineString(g) => &g.vec_bbox,
161            VectorGeometry::MultiLineString(g) => &g.vec_bbox,
162            VectorGeometry::Polygon(g) => &g.vec_bbox,
163            VectorGeometry::MultiPolygon(g) => &g.vec_bbox,
164        }
165    }
166
167    /// Create a new point
168    pub fn new_point(coordinates: VectorPoint<M>, bbox: Option<BBox3D>) -> Self {
169        VectorGeometry::Point(VectorPointGeometry {
170            _type: VectorGeometryType::Point,
171            is_3d: coordinates.z.is_some(),
172            coordinates,
173            bbox,
174            ..Default::default()
175        })
176    }
177
178    /// Create a new multipoint
179    pub fn new_multipoint(coordinates: VectorMultiPoint<M>, bbox: Option<BBox3D>) -> Self {
180        VectorGeometry::MultiPoint(VectorMultiPointGeometry {
181            _type: VectorGeometryType::MultiPoint,
182            is_3d: coordinates[0].z.is_some(),
183            coordinates,
184            bbox,
185            ..Default::default()
186        })
187    }
188
189    /// Create a new linestring
190    pub fn new_linestring(coordinates: VectorLineString<M>, bbox: Option<BBox3D>) -> Self {
191        VectorGeometry::LineString(VectorLineStringGeometry {
192            _type: VectorGeometryType::LineString,
193            is_3d: coordinates[0].z.is_some(),
194            coordinates,
195            bbox,
196            ..Default::default()
197        })
198    }
199
200    /// Create a new multilinestring
201    pub fn new_multilinestring(
202        coordinates: VectorMultiLineString<M>,
203        bbox: Option<BBox3D>,
204    ) -> Self {
205        VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
206            _type: VectorGeometryType::MultiLineString,
207            is_3d: coordinates[0][0].z.is_some(),
208            coordinates,
209            bbox,
210            ..Default::default()
211        })
212    }
213
214    /// Create a new polygon
215    pub fn new_polygon(coordinates: VectorPolygon<M>, bbox: Option<BBox3D>) -> Self {
216        VectorGeometry::Polygon(VectorPolygonGeometry {
217            _type: VectorGeometryType::Polygon,
218            is_3d: coordinates[0][0].z.is_some(),
219            coordinates,
220            bbox,
221            ..Default::default()
222        })
223    }
224
225    /// Create a new multipolygon
226    pub fn new_multipolygon(coordinates: VectorMultiPolygon<M>, bbox: Option<BBox3D>) -> Self {
227        VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
228            _type: VectorGeometryType::MultiPolygon,
229            is_3d: coordinates[0][0][0].z.is_some(),
230            coordinates,
231            bbox,
232            ..Default::default()
233        })
234    }
235}
236impl<M: MValueCompatible> Default for VectorGeometry<M> {
237    fn default() -> Self {
238        VectorGeometry::Point(VectorPointGeometry::default())
239    }
240}
241
242/// BaseGeometry is the a generic geometry type
243#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
244pub struct VectorBaseGeometry<G = VectorGeometry, O = VectorOffsets> {
245    /// The geometry type
246    #[serde(rename = "type")]
247    pub _type: VectorGeometryType,
248    /// Specifies if the geometry is 3D or 2D
249    #[serde(rename = "is3D")]
250    pub is_3d: bool,
251    /// The geometry shape
252    pub coordinates: G,
253    /// The geometry offsets if applicable
254    #[serde(skip_serializing_if = "Option::is_none")]
255    pub offset: Option<O>,
256    /// The BBox shape - always in lon-lat
257    #[serde(skip_serializing_if = "Option::is_none")]
258    pub bbox: Option<BBox3D>,
259    /// temporary bbox to track 0->1 clipping
260    #[serde(skip)]
261    pub vec_bbox: Option<BBox3D>,
262    /// Polygon and MultiPolygon specific property
263    pub indices: Option<Vec<u32>>,
264    /// Polygon and MultiPolygon specific property
265    pub tesselation: Option<f64>,
266}
267
268/// All possible geometry offsets
269#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
270pub enum VectorOffsets {
271    /// LineString offset
272    LineOffset(VectorLineOffset),
273    /// MultiLineString offset
274    MultiLineOffset(VectorMultiLineOffset),
275    /// Polygon offset
276    PolygonOffset(VectorPolygonOffset),
277    /// MultiPolygon offset
278    MultiPolygonOffset(VectorMultiPolygonOffset),
279}
280impl Default for VectorOffsets {
281    fn default() -> Self {
282        VectorOffsets::LineOffset(0.0)
283    }
284}
285/// An offset defines how far the starting line is from the original starting point pre-slice
286pub type VectorLineOffset = f64;
287/// A collection of offsets
288pub type VectorMultiLineOffset = Vec<VectorLineOffset>;
289/// A collection of offsets
290pub type VectorPolygonOffset = VectorMultiLineOffset;
291/// A collection of collections of offsets
292pub type VectorMultiPolygonOffset = Vec<VectorPolygonOffset>;
293
294/// PointGeometry is a point
295pub type VectorPointGeometry<M = MValue> = VectorBaseGeometry<VectorPoint<M>>;
296/// MultiPointGeometry contains multiple points
297pub type VectorMultiPointGeometry<M = MValue> =
298    VectorBaseGeometry<VectorMultiPoint<M>, VectorLineOffset>;
299/// LineStringGeometry is a line
300pub type VectorLineStringGeometry<M = MValue> =
301    VectorBaseGeometry<VectorLineString<M>, VectorLineOffset>;
302/// MultiLineStringGeometry contains multiple lines
303pub type VectorMultiLineStringGeometry<M = MValue> =
304    VectorBaseGeometry<VectorMultiLineString<M>, VectorMultiLineOffset>;
305/// PolygonGeometry is a polygon with potential holes
306pub type VectorPolygonGeometry<M = MValue> =
307    VectorBaseGeometry<VectorPolygon<M>, VectorPolygonOffset>;
308/// MultiPolygonGeometry is a polygon with multiple polygons with their own potential holes
309pub type VectorMultiPolygonGeometry<M = MValue> =
310    VectorBaseGeometry<VectorMultiPolygon<M>, VectorMultiPolygonOffset>;