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    /// Create a new point
90    pub fn new_point(coordinates: VectorPoint<M>, bbox: Option<BBox3D>) -> Self {
91        VectorGeometry::Point(VectorPointGeometry {
92            _type: VectorGeometryType::Point,
93            is_3d: coordinates.z.is_some(),
94            coordinates,
95            bbox,
96            ..Default::default()
97        })
98    }
99
100    /// Create a new multipoint
101    pub fn new_multipoint(coordinates: VectorMultiPoint<M>, bbox: Option<BBox3D>) -> Self {
102        VectorGeometry::MultiPoint(VectorMultiPointGeometry {
103            _type: VectorGeometryType::MultiPoint,
104            is_3d: coordinates.iter().any(|point| point.z.is_some()),
105            coordinates,
106            bbox,
107            ..Default::default()
108        })
109    }
110
111    /// Create a new linestring
112    pub fn new_linestring(coordinates: VectorLineString<M>, bbox: Option<BBox3D>) -> Self {
113        VectorGeometry::LineString(VectorLineStringGeometry {
114            _type: VectorGeometryType::LineString,
115            is_3d: coordinates.iter().any(|point| point.z.is_some()),
116            coordinates,
117            bbox,
118            ..Default::default()
119        })
120    }
121
122    /// Create a new multilinestring
123    pub fn new_multilinestring(
124        coordinates: VectorMultiLineString<M>,
125        bbox: Option<BBox3D>,
126    ) -> Self {
127        VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
128            _type: VectorGeometryType::MultiLineString,
129            is_3d: coordinates.iter().any(|line| line.iter().any(|point| point.z.is_some())),
130            coordinates,
131            bbox,
132            ..Default::default()
133        })
134    }
135
136    /// Create a new polygon
137    pub fn new_polygon(coordinates: VectorPolygon<M>, bbox: Option<BBox3D>) -> Self {
138        VectorGeometry::Polygon(VectorPolygonGeometry {
139            _type: VectorGeometryType::Polygon,
140            is_3d: coordinates.iter().any(|ring| ring.iter().any(|point| point.z.is_some())),
141            coordinates,
142            bbox,
143            ..Default::default()
144        })
145    }
146
147    /// Create a new multipolygon
148    pub fn new_multipolygon(coordinates: VectorMultiPolygon<M>, bbox: Option<BBox3D>) -> Self {
149        VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
150            _type: VectorGeometryType::MultiPolygon,
151            is_3d: coordinates.iter().any(|polygon| {
152                polygon.iter().any(|ring| ring.iter().any(|point| point.z.is_some()))
153            }),
154            coordinates,
155            bbox,
156            ..Default::default()
157        })
158    }
159}
160impl<M: Clone + Default> Default for VectorGeometry<M> {
161    fn default() -> Self {
162        VectorGeometry::Point(VectorPointGeometry::default())
163    }
164}
165
166/// BaseGeometry is the a generic geometry type
167#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
168pub struct VectorBaseGeometry<G = VectorGeometry, O = VectorOffsets> {
169    /// The geometry type
170    #[serde(rename = "type")]
171    pub _type: VectorGeometryType,
172    /// Specifies if the geometry is 3D or 2D
173    #[serde(rename = "is3D")]
174    pub is_3d: bool,
175    /// The geometry shape
176    pub coordinates: G,
177    /// The geometry offsets if applicable
178    #[serde(skip_serializing_if = "Option::is_none")]
179    pub offset: Option<O>,
180    /// The BBox shape - always in lon-lat
181    #[serde(skip_serializing_if = "Option::is_none")]
182    pub bbox: Option<BBox3D>,
183    /// temporary bbox to track 0->1 clipping
184    #[serde(skip)]
185    pub vec_bbox: Option<BBox3D>,
186    /// Polygon and MultiPolygon specific property
187    pub indices: Option<Vec<u32>>,
188    /// Polygon and MultiPolygon specific property
189    pub tesselation: Option<f64>,
190}
191
192/// All possible geometry offsets
193#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
194pub enum VectorOffsets {
195    /// LineString offset
196    LineOffset(VectorLineOffset),
197    /// MultiLineString offset
198    MultiLineOffset(VectorMultiLineOffset),
199    /// Polygon offset
200    PolygonOffset(VectorPolygonOffset),
201    /// MultiPolygon offset
202    MultiPolygonOffset(VectorMultiPolygonOffset),
203}
204impl Default for VectorOffsets {
205    fn default() -> Self {
206        VectorOffsets::LineOffset(0.0)
207    }
208}
209/// An offset defines how far the starting line is from the original starting point pre-slice
210pub type VectorLineOffset = f64;
211/// A collection of offsets
212pub type VectorMultiLineOffset = Vec<VectorLineOffset>;
213/// A collection of offsets
214pub type VectorPolygonOffset = VectorMultiLineOffset;
215/// A collection of collections of offsets
216pub type VectorMultiPolygonOffset = Vec<VectorPolygonOffset>;
217
218/// PointGeometry is a point
219pub type VectorPointGeometry<M = MValue> = VectorBaseGeometry<VectorPoint<M>>;
220/// MultiPointGeometry contains multiple points
221pub type VectorMultiPointGeometry<M = MValue> =
222    VectorBaseGeometry<VectorMultiPoint<M>, VectorLineOffset>;
223/// LineStringGeometry is a line
224pub type VectorLineStringGeometry<M = MValue> =
225    VectorBaseGeometry<VectorLineString<M>, VectorLineOffset>;
226/// MultiLineStringGeometry contains multiple lines
227pub type VectorMultiLineStringGeometry<M = MValue> =
228    VectorBaseGeometry<VectorMultiLineString<M>, VectorMultiLineOffset>;
229/// PolygonGeometry is a polygon with potential holes
230pub type VectorPolygonGeometry<M = MValue> =
231    VectorBaseGeometry<VectorPolygon<M>, VectorPolygonOffset>;
232/// MultiPolygonGeometry is a polygon with multiple polygons with their own potential holes
233pub type VectorMultiPolygonGeometry<M = MValue> =
234    VectorBaseGeometry<VectorMultiPolygon<M>, VectorMultiPolygonOffset>;