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}