open_vector_tile/
geometry.rs

1use alloc::vec::Vec;
2use core::cmp::Ordering;
3use libm::round;
4use s2json::{LineStringMValues, MValue, MValueCompatible, VectorPoint};
5
6/// Open Vector Spec can be an x,y but also may contain an MValue if the
7/// geometry is a line or polygon
8#[derive(Debug, Clone, PartialEq)]
9pub struct Point {
10    /// x value
11    pub x: i32,
12    /// y value
13    pub y: i32,
14    /// M value
15    pub m: Option<MValue>,
16}
17impl Point {
18    /// Create a new point
19    pub fn new(x: i32, y: i32) -> Point {
20        Point { x, y, m: None }
21    }
22
23    /// Create a new point with an MValue
24    pub fn new_with_m(x: i32, y: i32, m: MValue) -> Point {
25        Point { x, y, m: Some(m) }
26    }
27}
28impl<D: MValueCompatible> From<&VectorPoint<D>> for Point {
29    fn from(vp: &VectorPoint<D>) -> Self {
30        Point { x: round(vp.x) as i32, y: round(vp.y) as i32, m: vp.m.clone().map(|m| m.into()) }
31    }
32}
33impl PartialOrd for Point {
34    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
35        // only compare x and y
36        Some(core::cmp::Ord::cmp(self, other))
37    }
38}
39impl Eq for Point {}
40impl Ord for Point {
41    fn cmp(&self, other: &Self) -> Ordering {
42        // only compare x and y
43        self.x.cmp(&other.x).then(self.y.cmp(&other.y))
44    }
45}
46/// Open Vector Spec can be an x,y,z but also may contain an MValue
47/// if the geometry is a line or polygon
48#[derive(Debug, Clone, PartialEq)]
49pub struct Point3D {
50    /// x value
51    pub x: i32,
52    /// y value
53    pub y: i32,
54    /// z value
55    pub z: i32,
56    /// M value
57    pub m: Option<MValue>,
58}
59impl Point3D {
60    /// Create a new point
61    pub fn new(x: i32, y: i32, z: i32) -> Point3D {
62        Point3D { x, y, z, m: None }
63    }
64
65    /// Create a new point with an MValue
66    pub fn new_with_m(x: i32, y: i32, z: i32, m: MValue) -> Point3D {
67        Point3D { x, y, z, m: Some(m) }
68    }
69}
70impl<D: MValueCompatible> From<&VectorPoint<D>> for Point3D {
71    fn from(vp: &VectorPoint<D>) -> Self {
72        Point3D {
73            x: round(vp.x) as i32,
74            y: round(vp.y) as i32,
75            z: round(vp.z.unwrap_or_default()) as i32,
76            m: vp.m.clone().map(|m| m.into()),
77        }
78    }
79}
80impl PartialOrd for Point3D {
81    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
82        // only compare x and y
83        Some(core::cmp::Ord::cmp(self, other))
84    }
85}
86impl Eq for Point3D {}
87impl Ord for Point3D {
88    fn cmp(&self, other: &Self) -> Ordering {
89        // only compare x and y
90        self.x.cmp(&other.x).then(self.y.cmp(&other.y)).then(self.z.cmp(&other.z))
91    }
92}
93
94/// Built array line data with associated offset to help render dashed lines across tiles.
95#[derive(Debug, Clone, PartialEq)]
96pub struct VectorLineWithOffset {
97    /// the offset of the line to start processing the dash position
98    pub offset: f64,
99    /// the line data
100    pub geometry: VectorLine,
101}
102impl From<&[Point]> for VectorLineWithOffset {
103    fn from(p: &[Point]) -> Self {
104        Self { offset: 0.0, geometry: p.to_vec() }
105    }
106}
107impl VectorLineWithOffset {
108    /// Create a new VectorLineWithOffset
109    pub fn new(offset: f64, geometry: VectorLine) -> Self {
110        Self { offset, geometry }
111    }
112
113    /// check if the line has an offset. 0.0 is considered no offset
114    pub fn has_offset(&self) -> bool {
115        self.offset != 0.0
116    }
117
118    /// check if the line has M values
119    pub fn has_m_values(&self) -> bool {
120        self.geometry.iter().any(|p| p.m.is_some())
121    }
122
123    /// Get the M values for the line
124    pub fn m_values(&self) -> Option<LineStringMValues> {
125        if !self.has_m_values() {
126            return None;
127        }
128        Some(self.geometry.iter().map(|p| p.m.clone().unwrap_or_default()).collect())
129    }
130}
131/// Built array line data with associated offset to help render dashed lines across tiles.
132pub type VectorLinesWithOffset = Vec<VectorLineWithOffset>;
133
134/// Built array line data with associated offset to help render dashed lines across tiles.
135#[derive(Debug, Clone, PartialEq)]
136pub struct VectorLine3DWithOffset {
137    /// the offset of the line to start processing the dash position
138    pub offset: f64,
139    /// the line data
140    pub geometry: VectorLine3D,
141}
142impl VectorLine3DWithOffset {
143    /// Create a new VectorLine3DWithOffset
144    pub fn new(offset: f64, geometry: VectorLine3D) -> Self {
145        Self { offset, geometry }
146    }
147
148    /// check if the line has an offset. 0.0 is considered no offset
149    pub fn has_offset(&self) -> bool {
150        self.offset != 0.0
151    }
152
153    /// check if the line has M values
154    pub fn has_m_values(&self) -> bool {
155        self.geometry.iter().any(|p| p.m.is_some())
156    }
157
158    /// Get the M values for the line
159    pub fn m_values(&self) -> Option<LineStringMValues> {
160        if !self.has_m_values() {
161            return None;
162        }
163        Some(self.geometry.iter().map(|p| p.m.clone().unwrap_or_default()).collect())
164    }
165}
166/// Built array line data with associated offset to help render dashed lines across tiles.
167pub type VectorLines3DWithOffset = Vec<VectorLine3DWithOffset>;
168
169/// A set of points
170pub type VectorPoints = Vec<Point>;
171/// A set of 3D points
172pub type VectorPoints3D = Vec<Point3D>;
173/// A set of points
174pub type VectorLine = Vec<Point>;
175/// A set of 3D points
176pub type VectorLine3D = Vec<Point3D>;
177/// A set of lines
178pub type VectorLines = Vec<VectorLine>;
179/// A set of 3D lines
180pub type VectorLines3D = Vec<VectorLine3D>;
181/// A set of polygons
182pub type VectorPoly = Vec<VectorLine>;
183/// A set of 3D polygons
184pub type VectorPoly3D = Vec<VectorLine3D>;
185/// A set of multiple polygons
186pub type VectorMultiPoly = Vec<VectorPoly>;
187/// A set of multiple 3D polygons
188pub type VectorMultiPoly3D = Vec<VectorPoly3D>;
189/// An enumeration of all the geometry types
190#[derive(Debug, Clone, PartialEq)]
191pub enum VectorGeometry {
192    /// points
193    VectorPoints(VectorPoints),
194    /// lines
195    VectorLines(VectorLinesWithOffset),
196    /// polygons
197    VectorPolys(Vec<VectorLinesWithOffset>),
198    /// 3D points
199    VectorPoints3D(VectorPoints3D),
200    /// 3D lines
201    VectorLines3D(VectorLines3DWithOffset),
202    /// 3D polygons
203    VectorPolys3D(Vec<VectorLines3DWithOffset>),
204}