1use crate::delaunay::{DelaunayTriangle, DelaunayTriangleHandle, TriangleId};
2use crate::ocl::prm::Float2;
3
4use std::fmt;
5use std::hash;
6
7use arena_system::{Arena, Handle, Index, RawHandle};
8use smallvec::SmallVec;
9
10pub type PointId = i64;
11
12#[derive(Debug, Default, Clone, PartialEq)]
14pub struct Point {
15 coords: Float2,
16
17 is_bounding: bool,
18 previous_in_outline: PointId,
19
20 triangle_fan: SmallVec<[TriangleId; 6]>,
21}
22
23impl Point {
24 pub fn new(x: f32, y: f32) -> Self {
26 Self {
27 coords: Float2::new(x, y),
28
29 is_bounding: false,
30 previous_in_outline: -1,
31
32 triangle_fan: SmallVec::new(),
33 }
34 }
35
36 pub fn with_is_bounding(x: f32, y: f32, is_bounding: bool) -> Self {
38 Self {
39 coords: Float2::new(x, y),
40
41 is_bounding,
42 previous_in_outline: -1,
43
44 triangle_fan: SmallVec::new(),
45 }
46 }
47
48 pub fn with_previous(x: f32, y: f32, previous_in_outline: PointId) -> Self {
50 Self {
51 coords: Float2::new(x, y),
52
53 is_bounding: false,
54 previous_in_outline,
55
56 triangle_fan: SmallVec::new(),
57 }
58 }
59
60 pub fn with_is_bounding_and_previous(
63 x: f32,
64 y: f32,
65 is_bounding: bool,
66 previous_in_outline: PointId,
67 ) -> Self {
68 Self {
69 coords: Float2::new(x, y),
70
71 is_bounding,
72 previous_in_outline,
73
74 triangle_fan: SmallVec::new(),
75 }
76 }
77
78 pub fn x(&self) -> f32 {
80 self.coords[0]
81 }
82
83 pub fn y(&self) -> f32 {
85 self.coords[1]
86 }
87
88 pub fn coords(&self) -> Float2 {
89 self.coords
90 }
91
92 pub fn set_coords(&mut self, coords: Float2) {
94 self.coords = coords;
95 }
96
97 pub fn is_bounding(&self) -> bool {
99 self.is_bounding
100 }
101
102 pub fn previous_in_outline(&self) -> PointId {
104 self.previous_in_outline
105 }
106
107 pub fn set_previous_in_outline(&mut self, previous_in_outline: PointId) {
109 self.previous_in_outline = previous_in_outline;
110 }
111
112 pub fn triangle_fan(&self) -> &SmallVec<[TriangleId; 6]> {
114 &self.triangle_fan
115 }
116
117 pub fn set_triangle_fan(&mut self, triangle_fan: SmallVec<[TriangleId; 6]>) {
119 self.triangle_fan = triangle_fan;
120 }
121
122 pub fn midpoint(&self, other: &Point) -> Point {
124 Point::new((self.x() + other.x()) / 2.0, (self.y() + other.y()) / 2.0)
125 }
126
127 pub fn distance_squared(&self, other: &Point) -> f32 {
129 let p = Point::new(self.x() - other.x(), self.y() - other.y());
130
131 p.x().powi(2) + p.y().powi(2)
132 }
133
134 pub fn distance(&self, other: &Point) -> f32 {
136 self.distance_squared(other).sqrt()
137 }
138}
139
140#[derive(Clone, Copy)]
142pub struct PointHandle<'arena> {
143 raw: RawHandle<'arena, Point>,
144 triangles: Option<&'arena Arena<DelaunayTriangle>>,
145}
146
147impl<'arena> PointHandle<'arena> {
148 pub fn x(&self) -> f32 {
150 self.get().unwrap().coords[0]
151 }
152
153 pub fn y(&self) -> f32 {
155 self.get().unwrap().coords[1]
156 }
157
158 pub fn coords(&self) -> Float2 {
160 self.get().unwrap().coords
161 }
162
163 pub fn set_coords(&mut self, coords: Float2) {
165 self.get_mut().unwrap().coords = coords;
166 }
167
168 pub fn is_bounding(&self) -> bool {
170 self.get().unwrap().is_bounding
171 }
172
173 pub fn previous_in_outline(&self) -> PointHandle<'arena> {
175 let this = self.get().expect("Can't get the point");
176
177 self.arena().handle(this.previous_in_outline().into(), self.triangles)
178 }
179
180 pub fn triangle_fan(&self) -> SmallVec<[DelaunayTriangleHandle<'arena>; 6]> {
182 self.get()
183 .unwrap()
184 .triangle_fan
185 .iter()
186 .copied()
187 .map(|i| i.into())
188 .map(|i| self.triangles.unwrap().handle(i, self.arena()))
189 .collect()
190 }
191
192 pub fn set_triangle_fan(
194 &mut self,
195 triangle_fan: SmallVec<[DelaunayTriangleHandle<'arena>; 6]>,
196 ) {
197 self.get_mut().unwrap().triangle_fan =
198 triangle_fan.into_iter().map(|h| h.index().into()).collect();
199 }
200
201 pub fn add_triangle_to_fan(&self, triangle: DelaunayTriangleHandle) {
203 let triangle_fan = &mut self.get_mut().unwrap().triangle_fan;
204
205 triangle_fan.push(triangle.index().into());
206 }
207
208 pub fn remove_triangle_from_fan(&self, triangle_index: Index) {
210 let triangle_fan = &mut self.get_mut().unwrap().triangle_fan;
211 let position = triangle_fan.iter().position(|t| *t == triangle_index.into());
212
213 if let Some(position) = position {
214 triangle_fan.remove(position);
215 }
216 }
217
218 pub fn is_connected_to(&self, other: PointHandle<'arena>) -> bool {
220 self.triangle_fan().into_iter().any(|t| t.points().contains(&other)) && *self != other
221 }
222
223 pub fn skew_product(&self, origin: &Self, other: &Self) -> f32 {
226 let a = Point::new(self.x() - origin.x(), self.y() - origin.y());
227 let b = Point::new(other.x() - origin.x(), other.y() - origin.y());
228
229 a.x() * b.y() - a.y() * b.x()
230 }
231
232 pub fn distance(&self, other: &PointHandle) -> f32 {
234 let this = self.get().expect("Can't get the point");
235 let other = other.get().expect("Can't get the other point");
236
237 this.distance(&other)
238 }
239}
240
241impl<'arena> Handle<'arena> for PointHandle<'arena> {
242 type Type = Point;
243 type Userdata = Option<&'arena Arena<DelaunayTriangle>>;
244
245 fn from_raw(raw: RawHandle<'arena, Self::Type>, userdata: Self::Userdata) -> Self {
246 Self { raw, triangles: userdata }
247 }
248
249 fn to_raw(&self) -> RawHandle<'arena, Self::Type> {
250 self.raw
251 }
252}
253
254impl fmt::Debug for PointHandle<'_> {
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 f.write_fmt(format_args!("PointHandle({:?})", self.to_raw()))
257 }
258}
259
260impl PartialEq for PointHandle<'_> {
261 fn eq(&self, other: &Self) -> bool {
262 self.to_raw() == other.to_raw()
263 }
264}
265impl Eq for PointHandle<'_> {}
266
267impl PartialOrd for PointHandle<'_> {
268 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
269 self.to_raw().partial_cmp(&other.to_raw())
270 }
271}
272
273impl Ord for PointHandle<'_> {
274 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
275 self.to_raw().cmp(&other.to_raw())
276 }
277}
278
279impl hash::Hash for PointHandle<'_> {
280 fn hash<H: hash::Hasher>(&self, state: &mut H) {
281 let index: i64 = self.index().into();
282 index.hash(state);
283 }
284}