s2json_core/geometry/
primitive.rs

1use crate::*;
2use alloc::vec::Vec;
3use core::cmp::Ordering;
4use serde::{Deserialize, Serialize};
5
6/// Definition of a Point. May represent WebMercator Lon-Lat or S2Geometry S-T
7#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Default)]
8pub struct Point(pub f64, pub f64);
9/// Definition of a MultiPoint
10pub type MultiPoint = Vec<Point>;
11/// Definition of a LineString
12pub type LineString = Vec<Point>;
13/// Definition of a MultiLineString
14pub type MultiLineString = Vec<LineString>;
15/// Definition of a Polygon
16pub type Polygon = Vec<Vec<Point>>;
17/// Definition of a MultiPolygon
18pub type MultiPolygon = Vec<Polygon>;
19/// Definition of a 3D Point. May represent WebMercator Lon-Lat or S2Geometry S-T with a z-value
20#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Default)]
21pub struct Point3D(pub f64, pub f64, pub f64);
22/// Definition of a 3D MultiPoint
23pub type MultiPoint3D = Vec<Point3D>;
24/// Definition of a 3D LineString
25pub type LineString3D = Vec<Point3D>;
26/// Definition of a 3D MultiLineString
27pub type MultiLineString3D = Vec<LineString3D>;
28/// Definition of a 3D Polygon
29pub type Polygon3D = Vec<Vec<Point3D>>;
30/// Definition of a 3D MultiPolygon
31pub type MultiPolygon3D = Vec<Polygon3D>;
32/// Define a Point or Point3D
33#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Default)]
34pub struct PointOrPoint3D(pub f64, pub f64, pub Option<f64>);
35impl From<Point> for PointOrPoint3D {
36    fn from(p: Point) -> Self {
37        PointOrPoint3D(p.0, p.1, None)
38    }
39}
40impl From<Point3D> for PointOrPoint3D {
41    fn from(p: Point3D) -> Self {
42        PointOrPoint3D(p.0, p.1, Some(p.2))
43    }
44}
45
46// GET
47
48impl GetXY for Point {
49    fn x(&self) -> f64 {
50        self.0
51    }
52    fn y(&self) -> f64 {
53        self.1
54    }
55}
56impl GetZ for Point {
57    fn z(&self) -> Option<f64> {
58        None
59    }
60}
61impl GetXY for Point3D {
62    fn x(&self) -> f64 {
63        self.0
64    }
65    fn y(&self) -> f64 {
66        self.1
67    }
68}
69impl GetXY for PointOrPoint3D {
70    fn x(&self) -> f64 {
71        self.0
72    }
73    fn y(&self) -> f64 {
74        self.1
75    }
76}
77impl GetZ for Point3D {
78    fn z(&self) -> Option<f64> {
79        Some(self.2)
80    }
81}
82impl GetZ for PointOrPoint3D {
83    fn z(&self) -> Option<f64> {
84        self.2
85    }
86}
87
88// SET
89
90impl SetXY for Point {
91    fn set_x(&mut self, x: f64) {
92        self.0 = x;
93    }
94    fn set_y(&mut self, y: f64) {
95        self.1 = y;
96    }
97    fn set_xy(&mut self, x: f64, y: f64) {
98        self.0 = x;
99        self.1 = y;
100    }
101}
102impl SetXY for Point3D {
103    fn set_x(&mut self, x: f64) {
104        self.0 = x;
105    }
106    fn set_y(&mut self, y: f64) {
107        self.1 = y;
108    }
109}
110impl SetZ for Point3D {
111    fn set_z(&mut self, z: f64) {
112        self.2 = z;
113    }
114}
115impl SetXY for PointOrPoint3D {
116    fn set_x(&mut self, x: f64) {
117        self.0 = x;
118    }
119    fn set_y(&mut self, y: f64) {
120        self.1 = y;
121    }
122}
123impl SetZ for PointOrPoint3D {
124    fn set_z(&mut self, z: f64) {
125        self.2 = Some(z);
126    }
127}
128
129// NEW
130
131impl NewXY for Point {
132    fn new_xy(x: f64, y: f64) -> Self {
133        Self(x, y)
134    }
135}
136impl NewXY for Point3D {
137    fn new_xy(x: f64, y: f64) -> Self {
138        Self(x, y, 0.0)
139    }
140}
141impl NewXY for PointOrPoint3D {
142    fn new_xy(x: f64, y: f64) -> Self {
143        Self(x, y, None)
144    }
145}
146impl NewXYZ for Point3D {
147    fn new_xyz(x: f64, y: f64, z: f64) -> Self {
148        Self(x, y, z)
149    }
150}
151impl NewXYZ for PointOrPoint3D {
152    fn new_xyz(x: f64, y: f64, z: f64) -> Self {
153        Self(x, y, Some(z))
154    }
155}
156
157// Equalities
158
159impl Eq for Point {}
160impl Ord for Point {
161    fn cmp(&self, other: &Point) -> Ordering {
162        match self.0.partial_cmp(&other.0) {
163            Some(Ordering::Equal) => {}
164            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `x` comparison is not equal */
165        }
166        match self.1.partial_cmp(&other.1) {
167            Some(Ordering::Equal) => Ordering::Equal,
168            other => other.unwrap_or(Ordering::Greater), /* Handle cases where `y` comparison is not equal */
169        }
170    }
171}
172impl PartialOrd for Point {
173    fn partial_cmp(&self, other: &Point) -> Option<Ordering> {
174        Some(self.cmp(other))
175    }
176}
177
178impl Eq for Point3D {}
179impl Ord for Point3D {
180    fn cmp(&self, other: &Point3D) -> Ordering {
181        match self.0.partial_cmp(&other.0) {
182            Some(Ordering::Equal) => {}
183            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `x` comparison is not equal */
184        }
185        match self.1.partial_cmp(&other.1) {
186            Some(Ordering::Equal) => {}
187            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `y` comparison is not equal */
188        }
189        match self.2.partial_cmp(&other.2) {
190            Some(order) => order,
191            None => Ordering::Equal, // This handles the NaN case safely
192        }
193    }
194}
195impl PartialOrd for Point3D {
196    fn partial_cmp(&self, other: &Point3D) -> Option<Ordering> {
197        Some(self.cmp(other))
198    }
199}
200
201impl Eq for PointOrPoint3D {}
202impl Ord for PointOrPoint3D {
203    fn cmp(&self, other: &PointOrPoint3D) -> Ordering {
204        match self.0.partial_cmp(&other.0) {
205            Some(Ordering::Equal) => {}
206            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `x` comparison is not equal */
207        }
208        match self.1.partial_cmp(&other.1) {
209            Some(Ordering::Equal) => {}
210            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `y` comparison is not equal */
211        }
212        match self.2.partial_cmp(&other.2) {
213            Some(order) => order,
214            None => Ordering::Equal, // This handles the NaN case safely
215        }
216    }
217}
218impl PartialOrd for PointOrPoint3D {
219    fn partial_cmp(&self, other: &PointOrPoint3D) -> Option<Ordering> {
220        Some(self.cmp(other))
221    }
222}
223
224/// Enum to represent specific geometry types as strings
225#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
226pub enum GeometryType {
227    /// Point
228    #[default]
229    Point,
230    /// MultiPoint
231    MultiPoint,
232    /// LineString
233    LineString,
234    /// MultiLineString
235    MultiLineString,
236    /// Polygon
237    Polygon,
238    /// MultiPolygon
239    MultiPolygon,
240    /// 3D Point
241    Point3D,
242    /// 3D MultiPoint
243    MultiPoint3D,
244    /// 3D LineString
245    LineString3D,
246    /// 3D MultiLineString
247    MultiLineString3D,
248    /// 3D Polygon
249    Polygon3D,
250    /// 3D MultiPolygon
251    MultiPolygon3D,
252}
253impl From<&str> for GeometryType {
254    fn from(s: &str) -> Self {
255        match s {
256            "Point" => GeometryType::Point,
257            "MultiPoint" => GeometryType::MultiPoint,
258            "LineString" => GeometryType::LineString,
259            "MultiLineString" => GeometryType::MultiLineString,
260            "Polygon" => GeometryType::Polygon,
261            "MultiPolygon" => GeometryType::MultiPolygon,
262            "Point3D" => GeometryType::Point3D,
263            "MultiPoint3D" => GeometryType::MultiPoint3D,
264            "LineString3D" => GeometryType::LineString3D,
265            "MultiLineString3D" => GeometryType::MultiLineString3D,
266            "Polygon3D" => GeometryType::Polygon3D,
267            "MultiPolygon3D" => GeometryType::MultiPolygon3D,
268            _ => panic!("Invalid geometry type: {}", s),
269        }
270    }
271}
272
273/// All possible geometry shapes
274#[derive(Clone, Serialize, Debug, PartialEq)]
275#[serde(untagged)]
276pub enum Geometry<M: Clone + Default = MValue> {
277    /// Point Shape
278    Point(PointGeometry<M>),
279    /// MultiPoint Shape
280    MultiPoint(MultiPointGeometry<M>),
281    /// LineString Shape
282    LineString(LineStringGeometry<M>),
283    /// MultiLineString Shape
284    MultiLineString(MultiLineStringGeometry<M>),
285    /// Polygon Shape
286    Polygon(PolygonGeometry<M>),
287    /// MultiPolygon Shape
288    MultiPolygon(MultiPolygonGeometry<M>),
289    /// Point3D Shape
290    Point3D(Point3DGeometry<M>),
291    /// MultiPoint3D Shape
292    MultiPoint3D(MultiPoint3DGeometry<M>),
293    /// LineString3D Shape
294    LineString3D(LineString3DGeometry<M>),
295    /// MultiLineString3D Shape
296    MultiLineString3D(MultiLineString3DGeometry<M>),
297    /// Polygon3D Shape
298    Polygon3D(Polygon3DGeometry<M>),
299    /// MultiPolygon3D Shape
300    MultiPolygon3D(MultiPolygon3DGeometry<M>),
301}
302impl<M: Clone + Default> Default for Geometry<M> {
303    fn default() -> Self {
304        Geometry::Point(PointGeometry::<M>::default())
305    }
306}
307
308/// BaseGeometry is the a generic geometry type
309#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
310pub struct BaseGeometry<M = MValue, G = Geometry<M>, B = BBOX> {
311    /// The geometry type
312    #[serde(rename = "type")]
313    pub _type: GeometryType,
314    /// The geometry shape
315    pub coordinates: G,
316    /// The M-Values shape
317    #[serde(rename = "mValues", skip_serializing_if = "Option::is_none")]
318    pub m_values: Option<M>,
319    /// The BBox shape
320    #[serde(skip_serializing_if = "Option::is_none")]
321    pub bbox: Option<B>,
322}
323
324/// PointGeometry is a point
325pub type PointGeometry<M = MValue> = BaseGeometry<M, Point, BBox>;
326/// MultiPointGeometry contains multiple points
327pub type MultiPointGeometry<M = MValue> = BaseGeometry<LineStringMValues<M>, MultiPoint, BBox>;
328/// LineStringGeometry is a line
329pub type LineStringGeometry<M = MValue> = BaseGeometry<LineStringMValues<M>, LineString, BBox>;
330/// MultiLineStringGeometry contains multiple lines
331pub type MultiLineStringGeometry<M = MValue> =
332    BaseGeometry<MultiLineStringMValues<M>, MultiLineString, BBox>;
333/// PolygonGeometry is a polygon with potential holes
334pub type PolygonGeometry<M = MValue> = BaseGeometry<PolygonMValues<M>, Polygon, BBox>;
335/// MultiPolygonGeometry is a polygon with multiple polygons with their own potential holes
336pub type MultiPolygonGeometry<M = MValue> =
337    BaseGeometry<MultiPolygonMValues<M>, MultiPolygon, BBox>;
338/// Point3DGeometry is a 3D point
339pub type Point3DGeometry<M = MValue> = BaseGeometry<M, Point3D, BBox3D>;
340/// MultiPoint3DGeometry contains multiple 3D points
341pub type MultiPoint3DGeometry<M = MValue> =
342    BaseGeometry<LineStringMValues<M>, MultiPoint3D, BBox3D>;
343/// LineString3DGeometry is a 3D line
344pub type LineString3DGeometry<M = MValue> =
345    BaseGeometry<LineStringMValues<M>, LineString3D, BBox3D>;
346/// MultiLineString3DGeometry contains multiple 3D lines
347pub type MultiLineString3DGeometry<M = MValue> =
348    BaseGeometry<MultiLineStringMValues<M>, MultiLineString3D, BBox3D>;
349/// Polygon3DGeometry is a 3D polygon with potential holes
350pub type Polygon3DGeometry<M = MValue> = BaseGeometry<PolygonMValues<M>, Polygon3D, BBox3D>;
351/// MultiPolygon3DGeometry is a 3D polygon with multiple polygons with their own potential holes
352pub type MultiPolygon3DGeometry<M = MValue> =
353    BaseGeometry<MultiPolygonMValues<M>, MultiPolygon3D, BBox3D>;