1use crate::*;
2use alloc::vec::Vec;
3use serde::{Deserialize, Serialize};
4
5#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
7pub enum VectorGeometryType {
8    #[default]
10    Point,
11    MultiPoint,
13    LineString,
15    MultiLineString,
17    Polygon,
19    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
36pub type VectorMultiPoint<M = MValue> = Vec<VectorPoint<M>>;
38pub type VectorLineString<M = MValue> = Vec<VectorPoint<M>>;
40pub type VectorMultiLineString<M = MValue> = Vec<VectorLineString<M>>;
42pub type VectorPolygon<M = MValue> = Vec<VectorLineString<M>>;
44pub type VectorMultiPolygon<M = MValue> = Vec<VectorPolygon<M>>;
46
47#[derive(Clone, Serialize, Debug, PartialEq)]
49#[serde(untagged)]
50pub enum VectorGeometry<M: Clone + Default = MValue> {
51    Point(VectorPointGeometry<M>),
53    MultiPoint(VectorMultiPointGeometry<M>),
55    LineString(VectorLineStringGeometry<M>),
57    MultiLineString(VectorMultiLineStringGeometry<M>),
59    Polygon(VectorPolygonGeometry<M>),
61    MultiPolygon(VectorMultiPolygonGeometry<M>),
63}
64impl<M: Clone + Default> VectorGeometry<M> {
65    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    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    pub fn point(&self) -> Option<&VectorPoint<M>> {
91        match self {
92            VectorGeometry::Point(g) => Some(&g.coordinates),
93            _ => None,
94        }
95    }
96
97    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    pub fn multipoint(&self) -> Option<&VectorMultiPoint<M>> {
110        match self {
111            VectorGeometry::MultiPoint(g) => Some(&g.coordinates),
112            _ => None,
113        }
114    }
115
116    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    pub fn linestring(&self) -> Option<&VectorLineString<M>> {
129        match self {
130            VectorGeometry::LineString(g) => Some(&g.coordinates),
131            _ => None,
132        }
133    }
134
135    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    pub fn multilinestring(&self) -> Option<&VectorMultiLineString<M>> {
148        match self {
149            VectorGeometry::MultiLineString(g) => Some(&g.coordinates),
150            _ => None,
151        }
152    }
153
154    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    pub fn polygon(&self) -> Option<&VectorPolygon<M>> {
170        match self {
171            VectorGeometry::Polygon(g) => Some(&g.coordinates),
172            _ => None,
173        }
174    }
175
176    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    pub fn multipolygon(&self) -> Option<&VectorMultiPolygon<M>> {
189        match self {
190            VectorGeometry::MultiPolygon(g) => Some(&g.coordinates),
191            _ => None,
192        }
193    }
194
195    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    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    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    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#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
318pub struct VectorBaseGeometry<G = VectorGeometry, O = VectorOffsets> {
319    #[serde(rename = "type")]
321    pub _type: VectorGeometryType,
322    #[serde(rename = "is3D", default)]
324    pub is_3d: bool,
325    pub coordinates: G,
327    #[serde(skip_serializing_if = "Option::is_none")]
329    pub offset: Option<O>,
330    #[serde(skip_serializing_if = "Option::is_none")]
332    pub bbox: Option<BBox3D>,
333    #[serde(skip)]
335    pub vec_bbox: Option<BBox3D>,
336    #[serde(skip_serializing_if = "Option::is_none")]
338    pub indices: Option<Vec<u32>>,
339    #[serde(skip_serializing_if = "Option::is_none")]
341    pub tessellation: Option<Vec<f64>>,
342}
343
344#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
346pub enum VectorOffsets {
347    LineOffset(VectorLineOffset),
349    MultiLineOffset(VectorMultiLineOffset),
351    PolygonOffset(VectorPolygonOffset),
353    MultiPolygonOffset(VectorMultiPolygonOffset),
355}
356impl Default for VectorOffsets {
357    fn default() -> Self {
358        VectorOffsets::LineOffset(0.0)
359    }
360}
361pub type VectorLineOffset = f64;
363pub type VectorMultiLineOffset = Vec<VectorLineOffset>;
365pub type VectorPolygonOffset = VectorMultiLineOffset;
367pub type VectorMultiPolygonOffset = Vec<VectorPolygonOffset>;
369
370pub type VectorPointGeometry<M = MValue> = VectorBaseGeometry<VectorPoint<M>>;
372pub type VectorMultiPointGeometry<M = MValue> =
374    VectorBaseGeometry<VectorMultiPoint<M>, VectorLineOffset>;
375pub type VectorLineStringGeometry<M = MValue> =
377    VectorBaseGeometry<VectorLineString<M>, VectorLineOffset>;
378pub type VectorMultiLineStringGeometry<M = MValue> =
380    VectorBaseGeometry<VectorMultiLineString<M>, VectorMultiLineOffset>;
381pub type VectorPolygonGeometry<M = MValue> =
383    VectorBaseGeometry<VectorPolygon<M>, VectorPolygonOffset>;
384pub type VectorMultiPolygonGeometry<M = MValue> =
386    VectorBaseGeometry<VectorMultiPolygon<M>, VectorMultiPolygonOffset>;