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 NewXYZ for Point3D {
162    fn new_xyz(x: f64, y: f64, z: f64) -> Self {
163        Self(x, y, z)
164    }
165}
166impl NewXYZ for PointOrPoint3D {
167    fn new_xyz(x: f64, y: f64, z: f64) -> Self {
168        Self(x, y, Some(z))
169    }
170}
171
172// Equalities
173
174impl Eq for Point {}
175impl Ord for Point {
176    fn cmp(&self, other: &Point) -> Ordering {
177        match self.0.partial_cmp(&other.0) {
178            Some(Ordering::Equal) => {}
179            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `x` comparison is not equal */
180        }
181        match self.1.partial_cmp(&other.1) {
182            Some(Ordering::Equal) => Ordering::Equal,
183            other => other.unwrap_or(Ordering::Greater), /* Handle cases where `y` comparison is not equal */
184        }
185    }
186}
187impl PartialOrd for Point {
188    fn partial_cmp(&self, other: &Point) -> Option<Ordering> {
189        Some(self.cmp(other))
190    }
191}
192
193impl Eq for Point3D {}
194impl Ord for Point3D {
195    fn cmp(&self, other: &Point3D) -> Ordering {
196        match self.0.partial_cmp(&other.0) {
197            Some(Ordering::Equal) => {}
198            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `x` comparison is not equal */
199        }
200        match self.1.partial_cmp(&other.1) {
201            Some(Ordering::Equal) => {}
202            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `y` comparison is not equal */
203        }
204        match self.2.partial_cmp(&other.2) {
205            Some(order) => order,
206            None => Ordering::Equal, // This handles the NaN case safely
207        }
208    }
209}
210impl PartialOrd for Point3D {
211    fn partial_cmp(&self, other: &Point3D) -> Option<Ordering> {
212        Some(self.cmp(other))
213    }
214}
215
216impl Eq for PointOrPoint3D {}
217impl Ord for PointOrPoint3D {
218    fn cmp(&self, other: &PointOrPoint3D) -> Ordering {
219        match self.0.partial_cmp(&other.0) {
220            Some(Ordering::Equal) => {}
221            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `x` comparison is not equal */
222        }
223        match self.1.partial_cmp(&other.1) {
224            Some(Ordering::Equal) => {}
225            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `y` comparison is not equal */
226        }
227        match self.2.partial_cmp(&other.2) {
228            Some(order) => order,
229            None => Ordering::Equal, // This handles the NaN case safely
230        }
231    }
232}
233impl PartialOrd for PointOrPoint3D {
234    fn partial_cmp(&self, other: &PointOrPoint3D) -> Option<Ordering> {
235        Some(self.cmp(other))
236    }
237}
238
239/// Enum to represent specific geometry types as strings
240#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
241pub enum GeometryType {
242    /// Point
243    #[default]
244    Point,
245    /// MultiPoint
246    MultiPoint,
247    /// LineString
248    LineString,
249    /// MultiLineString
250    MultiLineString,
251    /// Polygon
252    Polygon,
253    /// MultiPolygon
254    MultiPolygon,
255    /// 3D Point
256    Point3D,
257    /// 3D MultiPoint
258    MultiPoint3D,
259    /// 3D LineString
260    LineString3D,
261    /// 3D MultiLineString
262    MultiLineString3D,
263    /// 3D Polygon
264    Polygon3D,
265    /// 3D MultiPolygon
266    MultiPolygon3D,
267}
268impl From<&str> for GeometryType {
269    fn from(s: &str) -> Self {
270        match s {
271            "Point" => GeometryType::Point,
272            "MultiPoint" => GeometryType::MultiPoint,
273            "LineString" => GeometryType::LineString,
274            "MultiLineString" => GeometryType::MultiLineString,
275            "Polygon" => GeometryType::Polygon,
276            "MultiPolygon" => GeometryType::MultiPolygon,
277            "Point3D" => GeometryType::Point3D,
278            "MultiPoint3D" => GeometryType::MultiPoint3D,
279            "LineString3D" => GeometryType::LineString3D,
280            "MultiLineString3D" => GeometryType::MultiLineString3D,
281            "Polygon3D" => GeometryType::Polygon3D,
282            "MultiPolygon3D" => GeometryType::MultiPolygon3D,
283            _ => panic!("Invalid geometry type: {}", s),
284        }
285    }
286}
287
288/// All possible geometry shapes
289#[derive(Clone, Serialize, Debug, PartialEq)]
290#[serde(untagged)]
291pub enum Geometry<M: Clone + Default = MValue> {
292    /// Point Shape
293    Point(PointGeometry<M>),
294    /// MultiPoint Shape
295    MultiPoint(MultiPointGeometry<M>),
296    /// LineString Shape
297    LineString(LineStringGeometry<M>),
298    /// MultiLineString Shape
299    MultiLineString(MultiLineStringGeometry<M>),
300    /// Polygon Shape
301    Polygon(PolygonGeometry<M>),
302    /// MultiPolygon Shape
303    MultiPolygon(MultiPolygonGeometry<M>),
304    /// Point3D Shape
305    Point3D(Point3DGeometry<M>),
306    /// MultiPoint3D Shape
307    MultiPoint3D(MultiPoint3DGeometry<M>),
308    /// LineString3D Shape
309    LineString3D(LineString3DGeometry<M>),
310    /// MultiLineString3D Shape
311    MultiLineString3D(MultiLineString3DGeometry<M>),
312    /// Polygon3D Shape
313    Polygon3D(Polygon3DGeometry<M>),
314    /// MultiPolygon3D Shape
315    MultiPolygon3D(MultiPolygon3DGeometry<M>),
316}
317impl<M: Clone + Default> Default for Geometry<M> {
318    fn default() -> Self {
319        Geometry::Point(PointGeometry::<M>::default())
320    }
321}
322
323/// BaseGeometry is the a generic geometry type
324#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
325pub struct BaseGeometry<M = MValue, G = Geometry<M>, B = BBOX> {
326    /// The geometry type
327    #[serde(rename = "type")]
328    pub _type: GeometryType,
329    /// The geometry shape
330    pub coordinates: G,
331    /// The M-Values shape
332    #[serde(rename = "mValues", skip_serializing_if = "Option::is_none")]
333    pub m_values: Option<M>,
334    /// The BBox shape
335    #[serde(skip_serializing_if = "Option::is_none")]
336    pub bbox: Option<B>,
337}
338
339/// PointGeometry is a point
340pub type PointGeometry<M = MValue> = BaseGeometry<M, Point, BBox>;
341/// MultiPointGeometry contains multiple points
342pub type MultiPointGeometry<M = MValue> = BaseGeometry<LineStringMValues<M>, MultiPoint, BBox>;
343/// LineStringGeometry is a line
344pub type LineStringGeometry<M = MValue> = BaseGeometry<LineStringMValues<M>, LineString, BBox>;
345/// MultiLineStringGeometry contains multiple lines
346pub type MultiLineStringGeometry<M = MValue> =
347    BaseGeometry<MultiLineStringMValues<M>, MultiLineString, BBox>;
348/// PolygonGeometry is a polygon with potential holes
349pub type PolygonGeometry<M = MValue> = BaseGeometry<PolygonMValues<M>, Polygon, BBox>;
350/// MultiPolygonGeometry is a polygon with multiple polygons with their own potential holes
351pub type MultiPolygonGeometry<M = MValue> =
352    BaseGeometry<MultiPolygonMValues<M>, MultiPolygon, BBox>;
353/// Point3DGeometry is a 3D point
354pub type Point3DGeometry<M = MValue> = BaseGeometry<M, Point3D, BBox3D>;
355/// MultiPoint3DGeometry contains multiple 3D points
356pub type MultiPoint3DGeometry<M = MValue> =
357    BaseGeometry<LineStringMValues<M>, MultiPoint3D, BBox3D>;
358/// LineString3DGeometry is a 3D line
359pub type LineString3DGeometry<M = MValue> =
360    BaseGeometry<LineStringMValues<M>, LineString3D, BBox3D>;
361/// MultiLineString3DGeometry contains multiple 3D lines
362pub type MultiLineString3DGeometry<M = MValue> =
363    BaseGeometry<MultiLineStringMValues<M>, MultiLineString3D, BBox3D>;
364/// Polygon3DGeometry is a 3D polygon with potential holes
365pub type Polygon3DGeometry<M = MValue> = BaseGeometry<PolygonMValues<M>, Polygon3D, BBox3D>;
366/// MultiPolygon3DGeometry is a 3D polygon with multiple polygons with their own potential holes
367pub type MultiPolygon3DGeometry<M = MValue> =
368    BaseGeometry<MultiPolygonMValues<M>, MultiPolygon3D, BBox3D>;