1use serde::de::{self, SeqAccess, Visitor};
2use serde::ser::SerializeTuple;
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5use alloc::fmt;
6use alloc::vec::Vec;
7
8use core::f64::consts::PI;
9
10use libm::{atan, log, pow, sin, sinh, sqrt};
11
12use crate::values::*;
14use crate::Face;
15
16#[derive(Debug, PartialEq, Eq, Clone, Copy)]
18pub enum Axis {
19 X = 0,
21 Y = 1,
23}
24
25#[derive(Copy, Clone, Default, Debug, PartialEq, PartialOrd)]
31pub struct BBox<T = f64> {
32 pub left: T,
34 pub bottom: T,
36 pub right: T,
38 pub top: T,
40}
41impl<T> BBox<T> {
42 pub fn new(left: T, bottom: T, right: T, top: T) -> Self
44 where
45 T: Copy,
46 {
47 BBox { left, bottom, right, top }
48 }
49
50 pub fn point_overlap(&self, point: VectorPoint) -> bool
52 where
53 T: Into<f64> + Copy, {
55 point.x >= self.left.into()
56 && point.x <= self.right.into()
57 && point.y >= self.bottom.into()
58 && point.y <= self.top.into()
59 }
60
61 pub fn merge(&self, other: &BBox<T>) -> BBox<T>
63 where
64 T: PartialOrd + Copy,
65 {
66 let mut new_bbox = *self;
67 new_bbox.left = if new_bbox.left < other.left { new_bbox.left } else { other.left };
68 new_bbox.bottom =
69 if new_bbox.bottom < other.bottom { new_bbox.bottom } else { other.bottom };
70 new_bbox.right = if new_bbox.right > other.right { new_bbox.right } else { other.right };
71 new_bbox.top = if new_bbox.top > other.top { new_bbox.top } else { other.top };
72
73 new_bbox
74 }
75
76 pub fn overlap(&self, other: &BBox<T>) -> Option<BBox<T>>
78 where
79 T: PartialOrd + Copy,
80 {
81 if self.left > other.right
82 || self.right < other.left
83 || self.bottom > other.top
84 || self.top < other.bottom
85 {
86 None
87 } else {
88 let left = if self.left > other.left { self.left } else { other.left };
89 let bottom = if self.bottom > other.bottom { self.bottom } else { other.bottom };
90 let right = if self.right < other.right { self.right } else { other.right };
91 let top = if self.top < other.top { self.top } else { other.top };
92
93 Some(BBox { left, bottom, right, top })
94 }
95 }
96
97 pub fn clip(&self, axis: Axis, k1: T, k2: T) -> BBox<T>
99 where
100 T: PartialOrd + Copy,
101 {
102 let mut new_bbox = *self;
103 if axis == Axis::X {
104 new_bbox.left = if new_bbox.left > k1 { new_bbox.left } else { k1 };
105 new_bbox.right = if new_bbox.right < k2 { new_bbox.right } else { k2 };
106 } else {
107 new_bbox.bottom = if new_bbox.bottom > k1 { new_bbox.bottom } else { k1 };
108 new_bbox.top = if new_bbox.top < k2 { new_bbox.top } else { k2 };
109 }
110
111 new_bbox
112 }
113}
114impl BBox<f64> {
115 pub fn from_point(point: &VectorPoint) -> Self {
117 BBox::new(point.x, point.y, point.x, point.y)
118 }
119
120 pub fn extend_from_point(&mut self, point: &VectorPoint) {
122 *self = self.merge(&BBox::from_point(point));
123 }
124
125 pub fn from_uv_zoom(u: f64, v: f64, zoom: u8) -> Self {
127 let division_factor = 2. / (1 << zoom) as f64;
128
129 BBox {
130 left: division_factor * u - 1.0,
131 bottom: division_factor * v - 1.0,
132 right: division_factor * (u + 1.0) - 1.0,
133 top: division_factor * (v + 1.0) - 1.0,
134 }
135 }
136
137 pub fn from_st_zoom(s: f64, t: f64, zoom: u8) -> Self {
139 let division_factor = (2. / (1 << zoom) as f64) * 0.5;
140
141 BBox {
142 left: division_factor * s,
143 bottom: division_factor * t,
144 right: division_factor * (s + 1.),
145 top: division_factor * (t + 1.),
146 }
147 }
148}
149impl<T> Serialize for BBox<T>
150where
151 T: Serialize + Copy,
152{
153 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
154 where
155 S: Serializer,
156 {
157 let mut seq = serializer.serialize_tuple(4)?;
158 seq.serialize_element(&self.left)?;
159 seq.serialize_element(&self.bottom)?;
160 seq.serialize_element(&self.right)?;
161 seq.serialize_element(&self.top)?;
162 seq.end()
163 }
164}
165impl<'de, T> Deserialize<'de> for BBox<T>
166where
167 T: Deserialize<'de> + Copy,
168{
169 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
170 where
171 D: Deserializer<'de>,
172 {
173 struct BBoxVisitor<T> {
174 marker: core::marker::PhantomData<T>,
175 }
176
177 impl<'de, T> Visitor<'de> for BBoxVisitor<T>
178 where
179 T: Deserialize<'de> + Copy,
180 {
181 type Value = BBox<T>;
182
183 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
184 formatter.write_str("a sequence of four numbers")
185 }
186
187 fn visit_seq<V>(self, mut seq: V) -> Result<BBox<T>, V::Error>
188 where
189 V: SeqAccess<'de>,
190 {
191 let left =
192 seq.next_element()?.ok_or_else(|| de::Error::invalid_length(0, &self))?;
193 let bottom =
194 seq.next_element()?.ok_or_else(|| de::Error::invalid_length(1, &self))?;
195 let right =
196 seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?;
197 let top = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(3, &self))?;
198 Ok(BBox { left, bottom, right, top })
199 }
200 }
201
202 deserializer.deserialize_tuple(4, BBoxVisitor { marker: core::marker::PhantomData })
203 }
204}
205
206#[derive(Copy, Clone, Default, Debug, PartialEq, PartialOrd)]
209pub struct BBox3D<T = f64> {
210 pub left: T,
212 pub bottom: T,
214 pub right: T,
216 pub top: T,
218 pub near: T,
221 pub far: T,
224}
225impl<T> BBox3D<T> {
226 pub fn new(left: T, bottom: T, right: T, top: T, near: T, far: T) -> Self
228 where
229 T: Copy,
230 {
231 BBox3D { left, bottom, right, top, near, far }
232 }
233
234 pub fn point_overlap(&self, point: VectorPoint) -> bool
236 where
237 T: Into<f64> + Copy, {
239 let z = point.z.unwrap_or_default();
240 point.x >= self.left.into()
241 && point.x <= self.right.into()
242 && point.y >= self.bottom.into()
243 && point.y <= self.top.into()
244 && z >= self.near.into()
245 && z <= self.far.into()
246 }
247
248 pub fn merge(&self, other: &BBox3D<T>) -> BBox3D<T>
250 where
251 T: PartialOrd + Copy,
252 {
253 let mut new_bbox = *self;
254 new_bbox.left = if new_bbox.left < other.left { new_bbox.left } else { other.left };
255 new_bbox.bottom =
256 if new_bbox.bottom < other.bottom { new_bbox.bottom } else { other.bottom };
257 new_bbox.right = if new_bbox.right > other.right { new_bbox.right } else { other.right };
258 new_bbox.top = if new_bbox.top > other.top { new_bbox.top } else { other.top };
259 new_bbox.near = if new_bbox.near < other.near { new_bbox.near } else { other.near };
260 new_bbox.far = if new_bbox.far > other.far { new_bbox.far } else { other.far };
261
262 new_bbox
263 }
264
265 pub fn overlap(&self, other: &BBox3D<T>) -> Option<BBox3D<T>>
267 where
268 T: PartialOrd + Copy,
269 {
270 if self.left > other.right
271 || self.right < other.left
272 || self.bottom > other.top
273 || self.top < other.bottom
274 || self.near > other.far
275 || self.far < other.near
276 {
277 None
278 } else {
279 let left = if self.left > other.left { self.left } else { other.left };
280 let bottom = if self.bottom > other.bottom { self.bottom } else { other.bottom };
281 let right = if self.right < other.right { self.right } else { other.right };
282 let top = if self.top < other.top { self.top } else { other.top };
283
284 let near = if self.near > other.near { self.near } else { other.near };
285 let far = if self.far < other.far { self.far } else { other.far };
286
287 Some(BBox3D { left, bottom, right, top, near, far })
288 }
289 }
290
291 pub fn clip(&self, axis: Axis, k1: T, k2: T) -> BBox3D<T>
293 where
294 T: PartialOrd + Copy,
295 {
296 let mut new_bbox = *self;
297 if axis == Axis::X {
298 new_bbox.left = if new_bbox.left > k1 { new_bbox.left } else { k1 };
299 new_bbox.right = if new_bbox.right < k2 { new_bbox.right } else { k2 };
300 } else {
301 new_bbox.bottom = if new_bbox.bottom > k1 { new_bbox.bottom } else { k1 };
302 new_bbox.top = if new_bbox.top < k2 { new_bbox.top } else { k2 };
303 }
304
305 new_bbox
306 }
307}
308impl<T> Serialize for BBox3D<T>
309where
310 T: Serialize + Copy,
311{
312 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
313 where
314 S: Serializer,
315 {
316 let mut seq = serializer.serialize_tuple(6)?;
317 seq.serialize_element(&self.left)?;
318 seq.serialize_element(&self.bottom)?;
319 seq.serialize_element(&self.right)?;
320 seq.serialize_element(&self.top)?;
321 seq.serialize_element(&self.near)?;
322 seq.serialize_element(&self.far)?;
323 seq.end()
324 }
325}
326impl BBox3D<f64> {
327 pub fn from_point(point: &VectorPoint) -> Self {
329 BBox3D::new(
330 point.x,
331 point.y,
332 point.x,
333 point.y,
334 point.z.unwrap_or(0.),
335 point.z.unwrap_or(1.),
336 )
337 }
338
339 pub fn from_bbox(bbox: &BBox) -> Self {
341 BBox3D::new(bbox.left, bbox.bottom, bbox.right, bbox.top, 0., 1.)
342 }
343
344 pub fn extend_from_point(&mut self, point: &VectorPoint) {
346 *self = self.merge(&BBox3D::from_point(point));
347 }
348
349 pub fn from_uv_zoom(u: f64, v: f64, zoom: u8) -> Self {
351 let division_factor = 2. / (1 << zoom) as f64;
352
353 BBox3D {
354 left: division_factor * u - 1.0,
355 bottom: division_factor * v - 1.0,
356 right: division_factor * (u + 1.0) - 1.0,
357 top: division_factor * (v + 1.0) - 1.0,
358 near: 0.,
359 far: 1.,
360 }
361 }
362
363 pub fn from_st_zoom(s: f64, t: f64, zoom: u8) -> Self {
365 let division_factor = (2. / (1 << zoom) as f64) * 0.5;
366
367 BBox3D {
368 left: division_factor * s,
369 bottom: division_factor * t,
370 right: division_factor * (s + 1.),
371 top: division_factor * (t + 1.),
372 near: 0.,
373 far: 1.,
374 }
375 }
376}
377impl From<&BBox> for BBox3D<f64> {
378 fn from(bbox: &BBox) -> Self {
379 BBox3D::from_bbox(bbox)
380 }
381}
382impl<'de, T> Deserialize<'de> for BBox3D<T>
383where
384 T: Deserialize<'de> + Copy,
385{
386 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
387 where
388 D: Deserializer<'de>,
389 {
390 struct BBox3DVisitor<T> {
391 marker: core::marker::PhantomData<T>,
392 }
393
394 impl<'de, T> Visitor<'de> for BBox3DVisitor<T>
395 where
396 T: Deserialize<'de> + Copy,
397 {
398 type Value = BBox3D<T>;
399
400 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
401 formatter.write_str("a sequence of six numbers")
402 }
403
404 fn visit_seq<V>(self, mut seq: V) -> Result<BBox3D<T>, V::Error>
405 where
406 V: SeqAccess<'de>,
407 {
408 let left =
409 seq.next_element()?.ok_or_else(|| de::Error::invalid_length(0, &self))?;
410 let bottom =
411 seq.next_element()?.ok_or_else(|| de::Error::invalid_length(1, &self))?;
412 let right =
413 seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?;
414 let top = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(3, &self))?;
415 let near =
416 seq.next_element()?.ok_or_else(|| de::Error::invalid_length(4, &self))?;
417 let far = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(5, &self))?;
418 Ok(BBox3D { left, bottom, right, top, near, far })
419 }
420 }
421
422 deserializer.deserialize_tuple(6, BBox3DVisitor { marker: core::marker::PhantomData })
423 }
424}
425
426#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
428pub enum BBOX {
429 BBox(BBox),
431 BBox3D(BBox3D),
433}
434impl Default for BBOX {
435 fn default() -> Self {
436 BBOX::BBox(BBox::default())
437 }
438}
439
440#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
442pub struct STPoint {
443 pub face: Face,
445 pub s: f64,
447 pub t: f64,
449 pub z: Option<f64>,
451 pub m: Option<MValue>,
453}
454
455#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
457pub enum GeometryType {
458 Point,
460 MultiPoint,
462 LineString,
464 MultiLineString,
466 Polygon,
468 MultiPolygon,
470 Point3D,
472 MultiPoint3D,
474 LineString3D,
476 MultiLineString3D,
478 Polygon3D,
480 MultiPolygon3D,
482}
483impl From<&str> for GeometryType {
484 fn from(s: &str) -> Self {
485 match s {
486 "Point" => GeometryType::Point,
487 "MultiPoint" => GeometryType::MultiPoint,
488 "LineString" => GeometryType::LineString,
489 "MultiLineString" => GeometryType::MultiLineString,
490 "Polygon" => GeometryType::Polygon,
491 "MultiPolygon" => GeometryType::MultiPolygon,
492 "Point3D" => GeometryType::Point3D,
493 "MultiPoint3D" => GeometryType::MultiPoint3D,
494 "LineString3D" => GeometryType::LineString3D,
495 "MultiLineString3D" => GeometryType::MultiLineString3D,
496 "Polygon3D" => GeometryType::Polygon3D,
497 "MultiPolygon3D" => GeometryType::MultiPolygon3D,
498 _ => GeometryType::Point,
499 }
500 }
501}
502
503pub type Point = (f64, f64);
505pub type MultiPoint = Vec<Point>;
507pub type LineString = Vec<Point>;
509pub type MultiLineString = Vec<LineString>;
511pub type Polygon = Vec<Vec<Point>>;
513pub type MultiPolygon = Vec<Polygon>;
515pub type Point3D = (f64, f64, f64);
517pub type MultiPoint3D = Vec<Point3D>;
519pub type LineString3D = Vec<Point3D>;
521pub type MultiLineString3D = Vec<LineString3D>;
523pub type Polygon3D = Vec<Vec<Point3D>>;
525pub type MultiPolygon3D = Vec<Polygon3D>;
527
528#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
530pub enum Geometry {
531 Point(PointGeometry),
533 MultiPoint(MultiPointGeometry),
535 LineString(LineStringGeometry),
537 MultiLineString(MultiLineStringGeometry),
539 Polygon(PolygonGeometry),
541 MultiPolygon(MultiPolygonGeometry),
543 Point3D(Point3DGeometry),
545 MultiPoint3D(MultiPoint3DGeometry),
547 LineString3D(LineString3DGeometry),
549 MultiLineString3D(MultiLineString3DGeometry),
551 Polygon3D(Polygon3DGeometry),
553 MultiPolygon3D(MultiPolygon3DGeometry),
555}
556
557#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
559pub struct BaseGeometry<G = Geometry, M = MValues, B = BBOX> {
560 #[serde(rename = "type")]
562 pub _type: GeometryType,
563 pub coordinates: G,
565 #[serde(rename = "mValues", skip_serializing_if = "Option::is_none")]
567 pub m_values: Option<M>,
568 #[serde(skip_serializing_if = "Option::is_none")]
570 pub bbox: Option<B>,
571}
572
573pub type PointGeometry = BaseGeometry<Point, MValue, BBox>;
575pub type MultiPointGeometry = BaseGeometry<MultiPoint, LineStringMValues, BBox>;
577pub type LineStringGeometry = BaseGeometry<LineString, LineStringMValues, BBox>;
579pub type MultiLineStringGeometry = BaseGeometry<MultiLineString, MultiLineStringMValues, BBox>;
581pub type PolygonGeometry = BaseGeometry<Polygon, PolygonMValues, BBox>;
583pub type MultiPolygonGeometry = BaseGeometry<MultiPolygon, MultiPolygonMValues, BBox>;
585pub type Point3DGeometry = BaseGeometry<Point3D, MValue, BBox3D>;
587pub type MultiPoint3DGeometry = BaseGeometry<MultiPoint3D, LineStringMValues, BBox3D>;
589pub type LineString3DGeometry = BaseGeometry<LineString3D, LineStringMValues, BBox3D>;
591pub type MultiLineString3DGeometry =
593 BaseGeometry<MultiLineString3D, MultiLineStringMValues, BBox3D>;
594pub type Polygon3DGeometry = BaseGeometry<Polygon3D, PolygonMValues, BBox3D>;
596pub type MultiPolygon3DGeometry = BaseGeometry<MultiPolygon3D, MultiPolygonMValues, BBox3D>;
598
599#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
601pub enum VectorGeometryType {
602 #[default]
604 Point,
605 MultiPoint,
607 LineString,
609 MultiLineString,
611 Polygon,
613 MultiPolygon,
615}
616impl From<&str> for VectorGeometryType {
617 fn from(s: &str) -> Self {
618 match s {
619 "Point" => VectorGeometryType::Point,
620 "MultiPoint" => VectorGeometryType::MultiPoint,
621 "LineString" => VectorGeometryType::LineString,
622 "MultiLineString" => VectorGeometryType::MultiLineString,
623 "Polygon" => VectorGeometryType::Polygon,
624 "MultiPolygon" => VectorGeometryType::MultiPolygon,
625 _ => VectorGeometryType::Point,
626 }
627 }
628}
629
630#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
632pub struct VectorPoint {
633 pub x: f64,
635 pub y: f64,
637 pub z: Option<f64>,
639 #[serde(skip_serializing_if = "Option::is_none")]
641 pub m: Option<MValue>,
642 #[serde(skip)]
644 pub t: Option<f64>,
645}
646impl VectorPoint {
647 pub fn new(x: f64, y: f64, z: Option<f64>) -> Self {
649 Self { x, y, z, m: None, t: None }
650 }
651
652 pub fn project(&mut self, bbox: &mut Option<BBox3D>) {
654 let y = self.y;
655 let x = self.x;
656 let sin = sin((y * PI) / 180.);
657 let y2 = 0.5 - (0.25 * log((1. + sin) / (1. - sin))) / PI;
658 self.x = x / 360. + 0.5;
659 self.y = y2.clamp(0., 1.);
660
661 match bbox {
662 Some(bbox) => bbox.extend_from_point(self),
663 None => *bbox = Some(BBox3D::from_point(self)),
664 };
665 }
666
667 pub fn unproject(&mut self) {
669 let lon = (self.x - 0.5) * 360.;
670 let y2 = 0.5 - self.y;
671 let lat = atan(sinh(PI * (y2 * 2.))).to_degrees();
672
673 self.x = lon;
674 self.y = lat;
675 }
676
677 pub fn distance(&self, other: &VectorPoint) -> f64 {
679 sqrt(pow(other.x - self.x, 2.) + pow(other.y - self.y, 2.))
680 }
681}
682impl From<&Point> for VectorPoint {
683 fn from(p: &Point) -> Self {
684 Self { x: p.0, y: p.1, z: None, m: None, t: None }
685 }
686}
687impl From<&Point3D> for VectorPoint {
688 fn from(p: &Point3D) -> Self {
689 Self { x: p.0, y: p.1, z: Some(p.2), m: None, t: None }
690 }
691}
692pub type VectorMultiPoint = Vec<VectorPoint>;
694pub type VectorLineString = Vec<VectorPoint>;
696pub type VectorMultiLineString = Vec<VectorLineString>;
698pub type VectorPolygon = Vec<VectorLineString>;
700pub type VectorMultiPolygon = Vec<VectorPolygon>;
702
703#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
705pub enum VectorGeometry {
706 Point(VectorPointGeometry),
708 MultiPoint(VectorMultiPointGeometry),
710 LineString(VectorLineStringGeometry),
712 MultiLineString(VectorMultiLineStringGeometry),
714 Polygon(VectorPolygonGeometry),
716 MultiPolygon(VectorMultiPolygonGeometry),
718}
719impl VectorGeometry {
720 pub fn vec_bbox(&self) -> &Option<BBox3D> {
722 match self {
723 VectorGeometry::Point(g) => &g.vec_bbox,
724 VectorGeometry::MultiPoint(g) => &g.vec_bbox,
725 VectorGeometry::LineString(g) => &g.vec_bbox,
726 VectorGeometry::MultiLineString(g) => &g.vec_bbox,
727 VectorGeometry::Polygon(g) => &g.vec_bbox,
728 VectorGeometry::MultiPolygon(g) => &g.vec_bbox,
729 }
730 }
731}
732
733#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
735pub struct VectorBaseGeometry<G = VectorGeometry, O = VectorOffsets> {
736 #[serde(rename = "type")]
738 pub _type: VectorGeometryType,
739 #[serde(rename = "is3D")]
741 pub is_3d: bool,
742 pub coordinates: G,
744 #[serde(skip_serializing_if = "Option::is_none")]
746 pub offset: Option<O>,
747 #[serde(skip_serializing_if = "Option::is_none")]
749 pub bbox: Option<BBox3D>,
750 #[serde(skip)]
752 pub vec_bbox: Option<BBox3D>,
753 pub indices: Option<Vec<u32>>,
755 pub tesselation: Option<f64>,
757}
758
759#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
761pub enum VectorOffsets {
762 LineOffset(VectorLineOffset),
764 MultiLineOffset(VectorMultiLineOffset),
766 PolygonOffset(VectorPolygonOffset),
768 MultiPolygonOffset(VectorMultiPolygonOffset),
770}
771pub type VectorLineOffset = f64;
773pub type VectorMultiLineOffset = Vec<VectorLineOffset>;
775pub type VectorPolygonOffset = VectorMultiLineOffset;
777pub type VectorMultiPolygonOffset = Vec<VectorPolygonOffset>;
779
780pub type VectorPointGeometry = VectorBaseGeometry<VectorPoint>;
782pub type VectorMultiPointGeometry = VectorBaseGeometry<VectorMultiPoint, VectorLineOffset>;
784pub type VectorLineStringGeometry = VectorBaseGeometry<VectorLineString, VectorLineOffset>;
786pub type VectorMultiLineStringGeometry =
788 VectorBaseGeometry<VectorMultiLineString, VectorMultiLineOffset>;
789pub type VectorPolygonGeometry = VectorBaseGeometry<VectorPolygon, VectorPolygonOffset>;
791pub type VectorMultiPolygonGeometry =
793 VectorBaseGeometry<VectorMultiPolygon, VectorMultiPolygonOffset>;
794
795#[cfg(test)]
796mod tests {
797 use super::*;
798 use alloc::vec;
799
800 #[test]
801 fn test_bbox() {
802 let bbox = BBox { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0 };
803 assert_eq!(bbox, BBox { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0 });
804 let bbox_str = serde_json::to_string(&bbox).unwrap();
805 assert_eq!(bbox_str, "[0.0,0.0,1.0,1.0]");
806 let str_bbox: BBox = serde_json::from_str(&bbox_str).unwrap();
807 assert_eq!(str_bbox, bbox);
808
809 let default_bbox = BBox::default();
810 assert_eq!(default_bbox, BBox { left: 0.0, bottom: 0.0, right: 0.0, top: 0.0 });
811
812 let default_bbox_2 = BBOX::default();
813 assert_eq!(
814 default_bbox_2,
815 BBOX::BBox(BBox { left: 0.0, bottom: 0.0, right: 0.0, top: 0.0 })
816 );
817 }
818
819 #[test]
820 fn test_bbox_functions() {
821 let bbox = BBox::new(0., 0., 1., 1.);
822 assert!(bbox.point_overlap(VectorPoint::new(0.5, 0.5, None)));
823 assert!(!bbox.point_overlap(VectorPoint::new(2.0, 2.0, None)));
824 let bbox2 = BBox { left: 0.5, bottom: 0.5, right: 1.5, top: 1.5 };
825 assert_eq!(
826 bbox.overlap(&bbox2),
827 Some(BBox { left: 0.5, bottom: 0.5, right: 1.0, top: 1.0 })
828 );
829 let bbox3 = BBox { left: 2.0, bottom: 2.0, right: 3.0, top: 3.0 };
830 assert_eq!(bbox3.overlap(&bbox), None);
831 }
832
833 #[test]
834 fn test_bbox_functions_2() {
835 let bbox = BBox::from_st_zoom(0., 0., 0);
836 assert_eq!(bbox, BBox { left: 0.0, bottom: 0.0, right: 1., top: 1. });
837
838 let bbox = BBox::from_st_zoom(1., 0., 1);
839 assert_eq!(bbox, BBox { left: 0.5, bottom: 0.0, right: 1., top: 0.5 });
840
841 let bbox = BBox::from_st_zoom(2., 0., 2);
842 assert_eq!(bbox, BBox { left: 0.5, bottom: 0.0, right: 0.75, top: 0.25 });
843
844 let bbox = BBox::from_uv_zoom(0., 0., 0);
845 assert_eq!(bbox, BBox { left: -1.0, bottom: -1.0, right: 1., top: 1. });
846
847 let bbox = BBox::from_uv_zoom(1., 0., 1);
848 assert_eq!(bbox, BBox { left: 0., bottom: -1.0, right: 1., top: 0. });
849
850 let bbox = BBox::from_uv_zoom(2., 0., 2);
851 assert_eq!(bbox, BBox { left: 0., bottom: -1.0, right: 0.5, top: -0.5 });
852 }
853
854 #[test]
855 fn test_bbox3d() {
856 let bbox = BBox3D { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0, near: 0.0, far: 1.0 };
857 assert_eq!(
858 bbox,
859 BBox3D { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0, near: 0.0, far: 1.0 }
860 );
861 let bbox_str = serde_json::to_string(&bbox).unwrap();
862 assert_eq!(bbox_str, "[0.0,0.0,1.0,1.0,0.0,1.0]");
863 let str_bbox: BBox3D = serde_json::from_str(&bbox_str).unwrap();
864 assert_eq!(str_bbox, bbox);
865
866 let default_bbox = BBox3D::default();
867 assert_eq!(
868 default_bbox,
869 BBox3D { left: 0.0, bottom: 0.0, right: 0.0, top: 0.0, near: 0.0, far: 0.0 }
870 );
871 }
872
873 #[test]
874 fn test_point_geometry() {
875 let point = PointGeometry {
876 _type: "Point".into(),
877 coordinates: (0.0, 0.0),
878 m_values: None,
879 bbox: None,
880 };
881 assert_eq!(
882 point,
883 PointGeometry {
884 _type: "Point".into(),
885 coordinates: (0.0, 0.0),
886 m_values: None,
887 bbox: None
888 }
889 );
890 let point_str = serde_json::to_string(&point).unwrap();
891 assert_eq!(point_str, "{\"type\":\"Point\",\"coordinates\":[0.0,0.0]}");
892 let str_point: PointGeometry = serde_json::from_str(&point_str).unwrap();
893 assert_eq!(str_point, point);
894 }
895
896 #[test]
897 fn test_point3d_geometry() {
898 let point = Point3DGeometry {
899 _type: "Point3D".into(),
900 coordinates: (0.0, 0.0, 0.0),
901 m_values: None,
902 bbox: Some(BBox3D {
903 left: 0.0,
904 bottom: 0.0,
905 right: 1.0,
906 top: 1.0,
907 near: 0.0,
908 far: 1.0,
909 }),
910 };
911 assert_eq!(
912 point,
913 Point3DGeometry {
914 _type: "Point3D".into(),
915 coordinates: (0.0, 0.0, 0.0),
916 m_values: None,
917 bbox: Some(BBox3D {
918 left: 0.0,
919 bottom: 0.0,
920 right: 1.0,
921 top: 1.0,
922 near: 0.0,
923 far: 1.0
924 })
925 }
926 );
927 let point_str = serde_json::to_string(&point).unwrap();
928 assert_eq!(
929 point_str,
930 "{\"type\":\"Point3D\",\"coordinates\":[0.0,0.0,0.0],\"bbox\":[0.0,0.0,1.0,1.0,0.0,1.\
931 0]}"
932 );
933 let str_point: Point3DGeometry = serde_json::from_str(&point_str).unwrap();
934 assert_eq!(str_point, point);
935 }
936
937 #[test]
938 fn test_line_string_geometry() {
939 let line = LineStringGeometry {
940 _type: "LineString".into(),
941 coordinates: vec![(0.0, 0.0), (1.0, 1.0)],
942 m_values: None,
943 bbox: None,
944 };
945 assert_eq!(
946 line,
947 LineStringGeometry {
948 _type: "LineString".into(),
949 coordinates: vec![(0.0, 0.0), (1.0, 1.0)],
950 m_values: None,
951 bbox: None
952 }
953 );
954 let line_str = serde_json::to_string(&line).unwrap();
955 assert_eq!(line_str, "{\"type\":\"LineString\",\"coordinates\":[[0.0,0.0],[1.0,1.0]]}");
956 let str_line: LineStringGeometry = serde_json::from_str(&line_str).unwrap();
957 assert_eq!(str_line, line);
958 }
959
960 #[test]
961 fn test_line_string3d_geometry() {
962 let line = LineString3DGeometry {
963 _type: "LineString3D".into(),
964 coordinates: vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
965 m_values: None,
966 bbox: None,
967 };
968 assert_eq!(
969 line,
970 LineString3DGeometry {
971 _type: "LineString3D".into(),
972 coordinates: vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
973 m_values: None,
974 bbox: None
975 }
976 );
977 let line_str = serde_json::to_string(&line).unwrap();
978 assert_eq!(
979 line_str,
980 "{\"type\":\"LineString3D\",\"coordinates\":[[0.0,0.0,0.0],[1.0,1.0,1.0]]}"
981 );
982 let str_line: LineString3DGeometry = serde_json::from_str(&line_str).unwrap();
983 assert_eq!(str_line, line);
984 }
985
986 #[test]
987 fn test_multi_point_geometry() {
988 let multi_point = MultiPointGeometry {
989 _type: "MultiPoint".into(),
990 coordinates: vec![(0.0, 0.0), (1.0, 1.0)],
991 m_values: None,
992 bbox: None,
993 };
994 assert_eq!(
995 multi_point,
996 MultiPointGeometry {
997 _type: "MultiPoint".into(),
998 coordinates: vec![(0.0, 0.0), (1.0, 1.0)],
999 m_values: None,
1000 bbox: None
1001 }
1002 );
1003 let multi_point_str = serde_json::to_string(&multi_point).unwrap();
1004 assert_eq!(
1005 multi_point_str,
1006 "{\"type\":\"MultiPoint\",\"coordinates\":[[0.0,0.0],[1.0,1.0]]}"
1007 );
1008 let str_multi_point: MultiPointGeometry = serde_json::from_str(&multi_point_str).unwrap();
1009 assert_eq!(str_multi_point, multi_point);
1010 }
1011
1012 #[test]
1013 fn test_multi_point3d_geometry() {
1014 let multi_point = MultiPoint3DGeometry {
1015 _type: "MultiPoint3D".into(),
1016 coordinates: vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
1017 m_values: None,
1018 bbox: None,
1019 };
1020 assert_eq!(
1021 multi_point,
1022 MultiPoint3DGeometry {
1023 _type: "MultiPoint3D".into(),
1024 coordinates: vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
1025 m_values: None,
1026 bbox: None
1027 }
1028 );
1029 let multi_point_str = serde_json::to_string(&multi_point).unwrap();
1030 assert_eq!(
1031 multi_point_str,
1032 "{\"type\":\"MultiPoint3D\",\"coordinates\":[[0.0,0.0,0.0],[1.0,1.0,1.0]]}"
1033 );
1034 let str_multi_point: MultiPoint3DGeometry = serde_json::from_str(&multi_point_str).unwrap();
1035 assert_eq!(str_multi_point, multi_point);
1036 }
1037
1038 #[test]
1039 fn test_polygon_geometry() {
1040 let polygon = PolygonGeometry {
1041 _type: "Polygon".into(),
1042 coordinates: vec![vec![(0.0, 0.0), (1.0, 1.0), (0.0, 1.0)]],
1043 m_values: None,
1044 bbox: None,
1045 };
1046 assert_eq!(
1047 polygon,
1048 PolygonGeometry {
1049 _type: "Polygon".into(),
1050 coordinates: vec![vec![(0.0, 0.0), (1.0, 1.0), (0.0, 1.0)]],
1051 m_values: None,
1052 bbox: None
1053 }
1054 );
1055 let polygon_str = serde_json::to_string(&polygon).unwrap();
1056 assert_eq!(
1057 polygon_str,
1058 "{\"type\":\"Polygon\",\"coordinates\":[[[0.0,0.0],[1.0,1.0],[0.0,1.0]]]}"
1059 );
1060 let str_polygon: PolygonGeometry = serde_json::from_str(&polygon_str).unwrap();
1061 assert_eq!(str_polygon, polygon);
1062 }
1063
1064 #[test]
1065 fn test_polygon3d_geometry() {
1066 let polygon = Polygon3DGeometry {
1067 _type: "Polygon3D".into(),
1068 coordinates: vec![vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (0.0, 1.0, 1.0)]],
1069 m_values: None,
1070 bbox: None,
1071 };
1072 assert_eq!(
1073 polygon,
1074 Polygon3DGeometry {
1075 _type: "Polygon3D".into(),
1076 coordinates: vec![vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (0.0, 1.0, 1.0)]],
1077 m_values: None,
1078 bbox: None
1079 }
1080 );
1081 let polygon_str = serde_json::to_string(&polygon).unwrap();
1082 assert_eq!(
1083 polygon_str,
1084 "{\"type\":\"Polygon3D\",\"coordinates\":[[[0.0,0.0,0.0],[1.0,1.0,1.0],[0.0,1.0,1.\
1085 0]]]}"
1086 );
1087 let str_polygon: Polygon3DGeometry = serde_json::from_str(&polygon_str).unwrap();
1088 assert_eq!(str_polygon, polygon);
1089 }
1090
1091 #[test]
1092 fn test_multi_polygon_geometry() {
1093 let multi_polygon = MultiPolygonGeometry {
1094 _type: "MultiPolygon".into(),
1095 coordinates: vec![vec![vec![(0.0, 0.0), (1.0, 1.0), (0.0, 1.0)]]],
1096 m_values: None,
1097 bbox: None,
1098 };
1099 assert_eq!(
1100 multi_polygon,
1101 MultiPolygonGeometry {
1102 _type: "MultiPolygon".into(),
1103 coordinates: vec![vec![vec![(0.0, 0.0), (1.0, 1.0), (0.0, 1.0)]]],
1104 m_values: None,
1105 bbox: None
1106 }
1107 );
1108 let multi_polygon_str = serde_json::to_string(&multi_polygon).unwrap();
1109 assert_eq!(
1110 multi_polygon_str,
1111 "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0.0,0.0],[1.0,1.0],[0.0,1.0]]]]}"
1112 );
1113 let str_multi_polygon: MultiPolygonGeometry =
1114 serde_json::from_str(&multi_polygon_str).unwrap();
1115 assert_eq!(str_multi_polygon, multi_polygon);
1116 }
1117
1118 #[test]
1119 fn test_multi_polygon3d_geometry() {
1120 let multi_polygon = MultiPolygon3DGeometry {
1121 _type: "MultiPolygon3D".into(),
1122 coordinates: vec![vec![vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (0.0, 1.0, 1.0)]]],
1123 m_values: None,
1124 bbox: None,
1125 };
1126 assert_eq!(
1127 multi_polygon,
1128 MultiPolygon3DGeometry {
1129 _type: "MultiPolygon3D".into(),
1130 coordinates: vec![vec![vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (0.0, 1.0, 1.0)]]],
1131 m_values: None,
1132 bbox: None
1133 }
1134 );
1135 let multi_polygon_str = serde_json::to_string(&multi_polygon).unwrap();
1136 assert_eq!(
1137 multi_polygon_str,
1138 "{\"type\":\"MultiPolygon3D\",\"coordinates\":[[[[0.0,0.0,0.0],[1.0,1.0,1.0],[0.0,1.0,\
1139 1.0]]]]}"
1140 );
1141 let str_multi_polygon: MultiPolygon3DGeometry =
1142 serde_json::from_str(&multi_polygon_str).unwrap();
1143 assert_eq!(str_multi_polygon, multi_polygon);
1144 }
1145}