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)]
71#[serde(untagged)]
72pub enum VectorGeometry<M: Clone + Default = MValue> {
73 Point(VectorPointGeometry<M>),
75 MultiPoint(VectorMultiPointGeometry<M>),
77 LineString(VectorLineStringGeometry<M>),
79 MultiLineString(VectorMultiLineStringGeometry<M>),
81 Polygon(VectorPolygonGeometry<M>),
83 MultiPolygon(VectorMultiPolygonGeometry<M>),
85}
86impl<M: Clone + Default> VectorGeometry<M> {
87 pub fn bbox(&mut self) -> BBox3D {
89 match self {
90 VectorGeometry::Point(g) => {
91 if g.bbox.is_none() {
92 g.bbox = Some(BBox3D::from_point(&g.coordinates));
93 }
94 g.bbox.unwrap()
95 }
96 VectorGeometry::MultiPoint(g) => {
97 if g.bbox.is_none() {
98 g.bbox = Some(BBox3D::from_linestring(&g.coordinates));
99 }
100 g.bbox.unwrap()
101 }
102 VectorGeometry::LineString(g) => {
103 if g.bbox.is_none() {
104 g.bbox = Some(BBox3D::from_linestring(&g.coordinates));
105 }
106 g.bbox.unwrap()
107 }
108 VectorGeometry::MultiLineString(g) => {
109 if g.bbox.is_none() {
110 g.bbox = Some(BBox3D::from_multi_linestring(&g.coordinates));
111 }
112 g.bbox.unwrap()
113 }
114 VectorGeometry::Polygon(g) => {
115 if g.bbox.is_none() {
116 g.bbox = Some(BBox3D::from_polygon(&g.coordinates));
117 }
118 g.bbox.unwrap()
119 }
120 VectorGeometry::MultiPolygon(g) => {
121 if g.bbox.is_none() {
122 g.bbox = Some(BBox3D::from_multi_polygon(&g.coordinates));
123 }
124 g.bbox.unwrap()
125 }
126 }
127 }
128
129 pub fn vec_bbox(&self) -> &Option<BBox3D> {
131 match self {
132 VectorGeometry::Point(g) => &g.vec_bbox,
133 VectorGeometry::MultiPoint(g) => &g.vec_bbox,
134 VectorGeometry::LineString(g) => &g.vec_bbox,
135 VectorGeometry::MultiLineString(g) => &g.vec_bbox,
136 VectorGeometry::Polygon(g) => &g.vec_bbox,
137 VectorGeometry::MultiPolygon(g) => &g.vec_bbox,
138 }
139 }
140
141 pub fn point(&self) -> Option<&VectorPoint<M>> {
143 match self {
144 VectorGeometry::Point(g) => Some(&g.coordinates),
145 _ => None,
146 }
147 }
148
149 pub fn new_point(coordinates: VectorPoint<M>, bbox: Option<BBox3D>) -> Self {
151 VectorGeometry::Point(VectorPointGeometry {
152 _type: VectorGeometryType::Point,
153 is_3d: coordinates.z.is_some(),
154 coordinates,
155 bbox,
156 ..Default::default()
157 })
158 }
159
160 pub fn multipoint(&self) -> Option<&VectorMultiPoint<M>> {
162 match self {
163 VectorGeometry::MultiPoint(g) => Some(&g.coordinates),
164 _ => None,
165 }
166 }
167
168 pub fn new_multipoint(coordinates: VectorMultiPoint<M>, bbox: Option<BBox3D>) -> Self {
170 VectorGeometry::MultiPoint(VectorMultiPointGeometry {
171 _type: VectorGeometryType::MultiPoint,
172 is_3d: coordinates.iter().any(|point| point.z.is_some()),
173 coordinates,
174 bbox,
175 ..Default::default()
176 })
177 }
178
179 pub fn linestring(&self) -> Option<&VectorLineString<M>> {
181 match self {
182 VectorGeometry::LineString(g) => Some(&g.coordinates),
183 _ => None,
184 }
185 }
186
187 pub fn new_linestring(coordinates: VectorLineString<M>, bbox: Option<BBox3D>) -> Self {
189 VectorGeometry::LineString(VectorLineStringGeometry {
190 _type: VectorGeometryType::LineString,
191 is_3d: coordinates.iter().any(|point| point.z.is_some()),
192 coordinates,
193 bbox,
194 ..Default::default()
195 })
196 }
197
198 pub fn multilinestring(&self) -> Option<&VectorMultiLineString<M>> {
200 match self {
201 VectorGeometry::MultiLineString(g) => Some(&g.coordinates),
202 _ => None,
203 }
204 }
205
206 pub fn new_multilinestring(
208 coordinates: VectorMultiLineString<M>,
209 bbox: Option<BBox3D>,
210 ) -> Self {
211 VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
212 _type: VectorGeometryType::MultiLineString,
213 is_3d: coordinates.iter().any(|line| line.iter().any(|point| point.z.is_some())),
214 coordinates,
215 bbox,
216 ..Default::default()
217 })
218 }
219
220 pub fn polygon(&self) -> Option<&VectorPolygon<M>> {
222 match self {
223 VectorGeometry::Polygon(g) => Some(&g.coordinates),
224 _ => None,
225 }
226 }
227
228 pub fn new_polygon(coordinates: VectorPolygon<M>, bbox: Option<BBox3D>) -> Self {
230 VectorGeometry::Polygon(VectorPolygonGeometry {
231 _type: VectorGeometryType::Polygon,
232 is_3d: coordinates.iter().any(|ring| ring.iter().any(|point| point.z.is_some())),
233 coordinates,
234 bbox,
235 ..Default::default()
236 })
237 }
238
239 pub fn multipolygon(&self) -> Option<&VectorMultiPolygon<M>> {
241 match self {
242 VectorGeometry::MultiPolygon(g) => Some(&g.coordinates),
243 _ => None,
244 }
245 }
246
247 pub fn new_multipolygon(coordinates: VectorMultiPolygon<M>, bbox: Option<BBox3D>) -> Self {
249 VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
250 _type: VectorGeometryType::MultiPolygon,
251 is_3d: coordinates.iter().any(|polygon| {
252 polygon.iter().any(|ring| ring.iter().any(|point| point.z.is_some()))
253 }),
254 coordinates,
255 bbox,
256 ..Default::default()
257 })
258 }
259
260 pub fn set_tess(&mut self, tessellation: Vec<f64>) {
262 match self {
263 VectorGeometry::Polygon(g) => g.tessellation = Some(tessellation),
264 VectorGeometry::MultiPolygon(g) => g.tessellation = Some(tessellation),
265 _ => {}
266 }
267 }
268
269 pub fn set_indices(&mut self, indices: Vec<u32>) {
271 match self {
272 VectorGeometry::Polygon(g) => g.indices = Some(indices),
273 VectorGeometry::MultiPolygon(g) => g.indices = Some(indices),
274 _ => {}
275 }
276 }
277
278 pub fn to_m_geometry(&self) -> VectorGeometry<MValue>
280 where
281 M: MValueCompatible,
282 {
283 match self {
284 VectorGeometry::Point(g) => VectorGeometry::Point(VectorPointGeometry {
285 _type: g._type,
286 is_3d: g.is_3d,
287 coordinates: g.coordinates.to_m_value(),
288 offset: g.offset.clone(),
289 bbox: g.bbox,
290 vec_bbox: g.vec_bbox,
291 ..Default::default()
292 }),
293 VectorGeometry::MultiPoint(g) => VectorGeometry::MultiPoint(VectorMultiPointGeometry {
294 _type: g._type,
295 is_3d: g.is_3d,
296 coordinates: g.coordinates.iter().map(|point| point.to_m_value()).collect(),
297 offset: g.offset,
298 bbox: g.bbox,
299 vec_bbox: g.vec_bbox,
300 ..Default::default()
301 }),
302 VectorGeometry::LineString(g) => VectorGeometry::LineString(VectorLineStringGeometry {
303 _type: g._type,
304 is_3d: g.is_3d,
305 coordinates: g.coordinates.iter().map(|point| point.to_m_value()).collect(),
306 offset: g.offset,
307 bbox: g.bbox,
308 vec_bbox: g.vec_bbox,
309 ..Default::default()
310 }),
311 VectorGeometry::MultiLineString(g) => {
312 VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
313 _type: g._type,
314 is_3d: g.is_3d,
315 coordinates: g
316 .coordinates
317 .iter()
318 .map(|line| line.iter().map(|point| point.to_m_value()).collect())
319 .collect(),
320 offset: g.offset.clone(),
321 bbox: g.bbox,
322 vec_bbox: g.vec_bbox,
323 ..Default::default()
324 })
325 }
326 VectorGeometry::Polygon(g) => VectorGeometry::Polygon(VectorPolygonGeometry {
327 _type: g._type,
328 is_3d: g.is_3d,
329 coordinates: g
330 .coordinates
331 .iter()
332 .map(|ring| ring.iter().map(|point| point.to_m_value()).collect())
333 .collect(),
334 offset: g.offset.clone(),
335 bbox: g.bbox,
336 vec_bbox: g.vec_bbox,
337 ..Default::default()
338 }),
339 VectorGeometry::MultiPolygon(g) => {
340 VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
341 _type: g._type,
342 is_3d: g.is_3d,
343 coordinates: g
344 .coordinates
345 .iter()
346 .map(|polygon| {
347 polygon
348 .iter()
349 .map(|ring| ring.iter().map(|point| point.to_m_value()).collect())
350 .collect()
351 })
352 .collect(),
353 offset: g.offset.clone(),
354 bbox: g.bbox,
355 vec_bbox: g.vec_bbox,
356 ..Default::default()
357 })
358 }
359 }
360 }
361}
362impl<M: Clone + Default> Default for VectorGeometry<M> {
363 fn default() -> Self {
364 VectorGeometry::Point(VectorPointGeometry::default())
365 }
366}
367
368#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
370pub struct VectorBaseGeometry<G = VectorGeometry, O = VectorOffsets> {
371 #[serde(rename = "type")]
373 pub _type: VectorGeometryType,
374 #[serde(rename = "is3D", default)]
376 pub is_3d: bool,
377 pub coordinates: G,
379 #[serde(skip_serializing_if = "Option::is_none")]
381 pub offset: Option<O>,
382 #[serde(skip_serializing_if = "Option::is_none")]
384 pub bbox: Option<BBox3D>,
385 #[serde(skip)]
387 pub vec_bbox: Option<BBox3D>,
388 #[serde(skip_serializing_if = "Option::is_none")]
390 pub indices: Option<Vec<u32>>,
391 #[serde(skip_serializing_if = "Option::is_none")]
393 pub tessellation: Option<Vec<f64>>,
394}
395
396#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
398pub enum VectorOffsets {
399 LineOffset(VectorLineOffset),
401 MultiLineOffset(VectorMultiLineOffset),
403 PolygonOffset(VectorPolygonOffset),
405 MultiPolygonOffset(VectorMultiPolygonOffset),
407}
408impl Default for VectorOffsets {
409 fn default() -> Self {
410 VectorOffsets::LineOffset(0.0)
411 }
412}
413pub type VectorLineOffset = f64;
415pub type VectorMultiLineOffset = Vec<VectorLineOffset>;
417pub type VectorPolygonOffset = VectorMultiLineOffset;
419pub type VectorMultiPolygonOffset = Vec<VectorPolygonOffset>;
421
422pub type VectorPointGeometry<M = MValue> = VectorBaseGeometry<VectorPoint<M>>;
424pub type VectorMultiPointGeometry<M = MValue> =
426 VectorBaseGeometry<VectorMultiPoint<M>, VectorLineOffset>;
427pub type VectorLineStringGeometry<M = MValue> =
429 VectorBaseGeometry<VectorLineString<M>, VectorLineOffset>;
430pub type VectorMultiLineStringGeometry<M = MValue> =
432 VectorBaseGeometry<VectorMultiLineString<M>, VectorMultiLineOffset>;
433pub type VectorPolygonGeometry<M = MValue> =
435 VectorBaseGeometry<VectorPolygon<M>, VectorPolygonOffset>;
436pub type VectorMultiPolygonGeometry<M = MValue> =
438 VectorBaseGeometry<VectorMultiPolygon<M>, VectorMultiPolygonOffset>;