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