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