ovtile/
geometry.rs

1use crate::open::{LineStringMValues, MValue};
2
3use core::cmp::Ordering;
4
5use alloc::vec::Vec;
6
7/// The Bounding box, whether the tile bounds or lon-lat bounds or whatever.
8#[derive(Default, Copy, Clone, Debug, PartialEq, PartialOrd, Eq)]
9pub struct BBox<T = f64> {
10    /// left most point; Also represents the left-most longitude
11    pub left: T,
12    /// bottom most point; Also represents the bottom-most latitude
13    pub bottom: T,
14    /// right most point; Also represents the right-most longitude
15    pub right: T,
16    /// top most point; Also represents the top-most latitude
17    pub top: T,
18}
19impl<T> BBox<T> {
20    /// Create a new BBox
21    pub fn new(left: T, bottom: T, right: T, top: T) -> Self {
22        Self { left, bottom, right, top }
23    }
24}
25
26/// A BBOX is defined in lon-lat space and helps with zooming motion to
27/// see the entire 3D line or polygon
28#[derive(Default, Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
29pub struct BBox3D<T = f64> {
30    /// left most longitude (WG) or S (S2)
31    pub left: T,
32    /// bottom most latitude (WG) or T (S2)
33    pub bottom: T,
34    /// right most longitude (WG) or T (S2)
35    pub right: T,
36    /// top most latitude (WG) or S (S2)
37    pub top: T,
38    /// back most height (WG) or T (S2)
39    /// generic height is relative to the surface of the earth in meters
40    pub far: T,
41    /// front most height (WG) or T (S2)
42    /// generic height is relative to the surface of the earth in meters
43    pub near: T,
44}
45impl<T> BBox3D<T> {
46    /// Create a new BBox3D
47    pub fn new(left: T, bottom: T, right: T, top: T, near: T, far: T) -> Self {
48        Self { left, bottom, right, top, near, far }
49    }
50}
51
52/// BBox or BBox3D
53#[derive(Copy, Clone, Debug, PartialEq)]
54pub enum BBOX {
55    /// 2D bounding box
56    BBox(BBox),
57    /// 3D bounding box
58    BBox3D(BBox3D),
59}
60impl Eq for BBOX {}
61impl PartialOrd for BBOX {
62    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
63        Some(self.cmp(other))
64    }
65}
66impl Ord for BBOX {
67    fn cmp(&self, other: &Self) -> Ordering {
68        match (self, other) {
69            (BBOX::BBox(a), BBOX::BBox(b)) => a.partial_cmp(b).unwrap_or(Ordering::Equal),
70            (BBOX::BBox3D(a), BBOX::BBox3D(b)) => a.partial_cmp(b).unwrap_or(Ordering::Equal),
71            // Ensure that BBox and BBox3D are ordered correctly
72            (BBOX::BBox(_), BBOX::BBox3D(_)) => Ordering::Less,
73            (BBOX::BBox3D(_), BBOX::BBox(_)) => Ordering::Greater,
74        }
75    }
76}
77
78/// Open Vector Spec can be an x,y but also may contain an MValue if the
79/// geometry is a line or polygon
80#[derive(Debug, Clone, PartialEq)]
81pub struct Point {
82    /// x value
83    pub x: i32,
84    /// y value
85    pub y: i32,
86    /// M value
87    pub m: Option<MValue>,
88}
89impl Point {
90    /// Create a new point
91    pub fn new(x: i32, y: i32) -> Point {
92        Point { x, y, m: None }
93    }
94
95    /// Create a new point with an MValue
96    pub fn new_with_m(x: i32, y: i32, m: MValue) -> Point {
97        Point { x, y, m: Some(m) }
98    }
99}
100impl PartialOrd for Point {
101    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
102        // only compare x and y
103        Some(core::cmp::Ord::cmp(self, other))
104    }
105}
106impl Eq for Point {}
107impl Ord for Point {
108    fn cmp(&self, other: &Self) -> Ordering {
109        // only compare x and y
110        self.x.cmp(&other.x).then(self.y.cmp(&other.y))
111    }
112}
113/// Open Vector Spec can be an x,y,z but also may contain an MValue
114/// if the geometry is a line or polygon
115#[derive(Debug, Clone, PartialEq)]
116pub struct Point3D {
117    /// x value
118    pub x: i32,
119    /// y value
120    pub y: i32,
121    /// z value
122    pub z: i32,
123    /// M value
124    pub m: Option<MValue>,
125}
126impl Point3D {
127    /// Create a new point
128    pub fn new(x: i32, y: i32, z: i32) -> Point3D {
129        Point3D { x, y, z, m: None }
130    }
131
132    /// Create a new point with an MValue
133    pub fn new_with_m(x: i32, y: i32, z: i32, m: MValue) -> Point3D {
134        Point3D { x, y, z, m: Some(m) }
135    }
136}
137impl PartialOrd for Point3D {
138    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
139        // only compare x and y
140        Some(core::cmp::Ord::cmp(self, other))
141    }
142}
143impl Eq for Point3D {}
144impl Ord for Point3D {
145    fn cmp(&self, other: &Self) -> Ordering {
146        // only compare x and y
147        self.x.cmp(&other.x).then(self.y.cmp(&other.y)).then(self.z.cmp(&other.z))
148    }
149}
150
151/// Built array line data with associated offset to help render dashed lines across tiles.
152#[derive(Debug, Clone, PartialEq)]
153pub struct VectorLineWithOffset {
154    /// the offset of the line to start processing the dash position
155    pub offset: f64,
156    /// the line data
157    pub geometry: VectorLine,
158}
159impl From<&[Point]> for VectorLineWithOffset {
160    fn from(p: &[Point]) -> Self {
161        Self { offset: 0.0, geometry: p.to_vec() }
162    }
163}
164impl VectorLineWithOffset {
165    /// Create a new VectorLineWithOffset
166    pub fn new(offset: f64, geometry: VectorLine) -> Self {
167        Self { offset, geometry }
168    }
169
170    /// check if the line has an offset. 0.0 is considered no offset
171    pub fn has_offset(&self) -> bool {
172        self.offset != 0.0
173    }
174
175    /// check if the line has M values
176    pub fn has_m_values(&self) -> bool {
177        self.geometry.iter().any(|p| p.m.is_some())
178    }
179
180    /// Get the M values for the line
181    pub fn m_values(&self) -> Option<LineStringMValues> {
182        if !self.has_m_values() {
183            return None;
184        }
185        Some(self.geometry.iter().map(|p| p.m.clone().unwrap_or_default()).collect())
186    }
187}
188/// Built array line data with associated offset to help render dashed lines across tiles.
189pub type VectorLinesWithOffset = Vec<VectorLineWithOffset>;
190
191/// Built array line data with associated offset to help render dashed lines across tiles.
192#[derive(Debug, Clone, PartialEq)]
193pub struct VectorLine3DWithOffset {
194    /// the offset of the line to start processing the dash position
195    pub offset: f64,
196    /// the line data
197    pub geometry: VectorLine3D,
198}
199impl VectorLine3DWithOffset {
200    /// Create a new VectorLine3DWithOffset
201    pub fn new(offset: f64, geometry: VectorLine3D) -> Self {
202        Self { offset, geometry }
203    }
204
205    /// check if the line has an offset. 0.0 is considered no offset
206    pub fn has_offset(&self) -> bool {
207        self.offset != 0.0
208    }
209
210    /// check if the line has M values
211    pub fn has_m_values(&self) -> bool {
212        self.geometry.iter().any(|p| p.m.is_some())
213    }
214
215    /// Get the M values for the line
216    pub fn m_values(&self) -> Option<LineStringMValues> {
217        if !self.has_m_values() {
218            return None;
219        }
220        Some(self.geometry.iter().map(|p| p.m.clone().unwrap_or_default()).collect())
221    }
222}
223/// Built array line data with associated offset to help render dashed lines across tiles.
224pub type VectorLines3DWithOffset = Vec<VectorLine3DWithOffset>;
225
226/// A set of points
227pub type VectorPoints = Vec<Point>;
228/// A set of 3D points
229pub type VectorPoints3D = Vec<Point3D>;
230/// A set of points
231pub type VectorLine = Vec<Point>;
232/// A set of 3D points
233pub type VectorLine3D = Vec<Point3D>;
234/// A set of lines
235pub type VectorLines = Vec<VectorLine>;
236/// A set of 3D lines
237pub type VectorLines3D = Vec<VectorLine3D>;
238/// A set of polygons
239pub type VectorPoly = Vec<VectorLine>;
240/// A set of 3D polygons
241pub type VectorPoly3D = Vec<VectorLine3D>;
242/// A set of multiple polygons
243pub type VectorMultiPoly = Vec<VectorPoly>;
244/// A set of multiple 3D polygons
245pub type VectorMultiPoly3D = Vec<VectorPoly3D>;
246/// An enumeration of all the geometry types
247#[derive(Debug, Clone, PartialEq)]
248pub enum VectorGeometry {
249    /// points
250    VectorPoints(VectorPoints),
251    /// lines
252    VectorLines(VectorLinesWithOffset),
253    /// polygons
254    VectorPolys(Vec<VectorLinesWithOffset>),
255    /// 3D points
256    VectorPoints3D(VectorPoints3D),
257    /// 3D lines
258    VectorLines3D(VectorLines3DWithOffset),
259    /// 3D polygons
260    VectorPolys3D(Vec<VectorLines3DWithOffset>),
261}