Skip to main content

geometry_kernel/
types.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
4pub struct Coord {
5    pub x: f64,
6    pub y: f64,
7}
8
9impl Coord {
10    pub const fn new(x: f64, y: f64) -> Self {
11        Self { x, y }
12    }
13
14    pub fn distance_squared(self, other: Self) -> f64 {
15        let dx = self.x - other.x;
16        let dy = self.y - other.y;
17        dx * dx + dy * dy
18    }
19
20    pub fn distance(self, other: Self) -> f64 {
21        self.distance_squared(other).sqrt()
22    }
23}
24
25impl From<[f64; 2]> for Coord {
26    fn from(value: [f64; 2]) -> Self {
27        Self::new(value[0], value[1])
28    }
29}
30
31impl From<Coord> for [f64; 2] {
32    fn from(value: Coord) -> Self {
33        [value.x, value.y]
34    }
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38pub struct LineString {
39    pub coords: Vec<Coord>,
40}
41
42impl LineString {
43    pub fn new(coords: Vec<Coord>) -> Self {
44        Self { coords }
45    }
46
47    pub fn is_empty(&self) -> bool {
48        self.coords.is_empty()
49    }
50
51    pub fn segments(&self) -> impl Iterator<Item = (Coord, Coord)> + '_ {
52        self.coords.windows(2).map(|pair| (pair[0], pair[1]))
53    }
54}
55
56#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
57pub struct LinearRing {
58    pub coords: Vec<Coord>,
59}
60
61impl LinearRing {
62    pub fn new(mut coords: Vec<Coord>) -> Self {
63        close_coords(&mut coords);
64        Self { coords }
65    }
66
67    pub fn is_empty(&self) -> bool {
68        self.coords.is_empty()
69    }
70
71    pub fn segments(&self) -> impl Iterator<Item = (Coord, Coord)> + '_ {
72        self.coords.windows(2).map(|pair| (pair[0], pair[1]))
73    }
74}
75
76#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77pub struct Polygon {
78    pub exterior: LinearRing,
79    #[serde(default)]
80    pub holes: Vec<LinearRing>,
81}
82
83impl Polygon {
84    pub fn new(exterior: LinearRing, holes: Vec<LinearRing>) -> Self {
85        Self { exterior, holes }
86    }
87
88    pub fn empty() -> Self {
89        Self::new(LinearRing { coords: Vec::new() }, Vec::new())
90    }
91
92    pub fn is_empty(&self) -> bool {
93        self.exterior.coords.len() < 4
94    }
95}
96
97#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
98pub struct MultiPolygon {
99    #[serde(default)]
100    pub polygons: Vec<Polygon>,
101}
102
103impl MultiPolygon {
104    pub fn new(polygons: Vec<Polygon>) -> Self {
105        Self { polygons }
106    }
107
108    pub fn empty() -> Self {
109        Self {
110            polygons: Vec::new(),
111        }
112    }
113
114    pub fn is_empty(&self) -> bool {
115        self.polygons.is_empty()
116    }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
120pub struct BBox {
121    pub min: Coord,
122    pub max: Coord,
123}
124
125impl BBox {
126    pub fn from_coords(coords: &[Coord]) -> Option<Self> {
127        let first = *coords.first()?;
128        let mut bbox = Self {
129            min: first,
130            max: first,
131        };
132        for coord in &coords[1..] {
133            bbox.min.x = bbox.min.x.min(coord.x);
134            bbox.min.y = bbox.min.y.min(coord.y);
135            bbox.max.x = bbox.max.x.max(coord.x);
136            bbox.max.y = bbox.max.y.max(coord.y);
137        }
138        Some(bbox)
139    }
140
141    pub fn intersects(self, other: Self) -> bool {
142        self.min.x <= other.max.x
143            && self.max.x >= other.min.x
144            && self.min.y <= other.max.y
145            && self.max.y >= other.min.y
146    }
147}
148
149pub fn close_coords(coords: &mut Vec<Coord>) {
150    if let (Some(first), Some(last)) = (coords.first().copied(), coords.last().copied()) {
151        if first != last {
152            coords.push(first);
153        }
154    }
155}