1#[cfg(feature = "rayon")]
2use rayon::prelude::*;
3
4pub mod dcel;
5pub mod geom;
6
7pub use dcel::TrianglesDCEL;
8pub use geom::{Point, Triangle};
9
10const STACK_CAPACITY: usize = 512;
11
12#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
16pub struct OptionIndex(usize);
17
18impl OptionIndex {
19 #[inline]
21 pub fn some(idx: usize) -> OptionIndex {
22 debug_assert!(idx < std::usize::MAX);
23 OptionIndex(idx)
24 }
25
26 #[inline]
28 pub fn none() -> OptionIndex {
29 OptionIndex(std::usize::MAX)
30 }
31
32 #[inline]
34 pub fn is_some(self) -> bool {
35 self != OptionIndex::none()
36 }
37
38 #[inline]
40 pub fn is_none(self) -> bool {
41 self == OptionIndex::none()
42 }
43
44 #[inline]
46 pub fn get(self) -> Option<usize> {
47 if self.is_some() {
48 Some(self.0)
49 } else {
50 None
51 }
52 }
53}
54
55fn angular_hash(point: Point, center: Point, size: usize) -> usize {
57 let angle = geom::pseudo_angle(point.x - center.x, point.y - center.y);
58 (angle * size as f32) as usize % size
59}
60
61struct Hull {
63 next: Vec<usize>,
65
66 prev: Vec<usize>,
68
69 hash_table: Vec<OptionIndex>,
71
72 triangles: Vec<OptionIndex>,
74
75 center: Point,
77
78 start: usize,
80}
81
82impl Hull {
83 fn new(seed: [usize; 3], points: &[Point]) -> Hull {
84 let capacity = points.len();
85 let table_size = (capacity as f32).sqrt().ceil() as usize;
86
87 let center = Triangle(points[seed[0]], points[seed[1]], points[seed[2]]).circumcenter();
88
89 let mut hull = Hull {
90 next: vec![0; capacity],
91 prev: vec![0; capacity],
92 hash_table: vec![OptionIndex::none(); table_size],
93 triangles: vec![OptionIndex::none(); capacity],
94 start: seed[0],
95 center,
96 };
97
98 hull.next[seed[0]] = seed[1];
99 hull.next[seed[1]] = seed[2];
100 hull.next[seed[2]] = seed[0];
101
102 hull.prev[seed[0]] = seed[2];
103 hull.prev[seed[1]] = seed[0];
104 hull.prev[seed[2]] = seed[1];
105
106 hull.triangles[seed[0]] = OptionIndex::some(0);
107 hull.triangles[seed[1]] = OptionIndex::some(1);
108 hull.triangles[seed[2]] = OptionIndex::some(2);
109
110 hull.add_hash(seed[0], points[seed[0]]);
111 hull.add_hash(seed[1], points[seed[1]]);
112 hull.add_hash(seed[2], points[seed[2]]);
113
114 hull
115 }
116
117 fn add_hash(&mut self, index: usize, point: Point) {
119 let table_size = self.hash_table.len();
120 self.hash_table[angular_hash(point, self.center, table_size)] = OptionIndex::some(index);
121 }
122
123 fn find_visible_edge(&self, point: Point, points: &[Point]) -> Option<(usize, bool)> {
126 let table_size = self.hash_table.len();
127 let hash = angular_hash(point, self.center, table_size);
128
129 let mut start = OptionIndex::none();
130
131 for i in 0..table_size {
133 start = self.hash_table[(hash + i) % table_size];
134
135 if start.get().filter(|&e| e != self.next[e]).is_some() {
137 break;
138 }
139 }
140
141 let start = self.prev[start.get()?];
145 let mut edge = start;
146
147 loop {
148 let next = self.next[edge];
149 let tri = Triangle(point, points[edge], points[next]);
150
151 if tri.is_left_handed() {
152 break;
154 }
155
156 edge = next;
157 if edge == start {
158 return None;
160 }
161 }
162
163 Some((edge, edge == start))
167 }
168}
169
170fn find_center(points: &[Point]) -> Point {
172 let (x_sum, y_sum) = points
173 .iter()
174 .fold((0.0, 0.0), |(x, y), point| (x + point.x, y + point.y));
175
176 Point::new(x_sum / points.len() as f32, y_sum / points.len() as f32)
177}
178
179fn find_seed_triangle(points: &[Point]) -> Option<(Triangle, [usize; 3])> {
180 let center = find_center(&points);
181
182 #[cfg(feature = "rayon")]
183 let iter = points.par_iter();
184
185 #[cfg(not(feature = "rayon"))]
186 let iter = points.iter();
187
188 let (seed_idx, seed) = iter.clone().cloned().enumerate().min_by(|(_, a), (_, b)| {
189 a.distance_sq(center)
190 .partial_cmp(&b.distance_sq(center))
191 .unwrap()
192 })?;
193
194 let (nearest_idx, nearest, _) = iter
195 .clone()
196 .cloned()
197 .enumerate()
198 .filter(|&(i, _)| i != seed_idx)
199 .map(|(i, p)| (i, p, p.distance_sq(seed)))
200 .filter(|(_, _, d)| d.abs() > std::f32::EPSILON)
201 .min_by(|(_, _, a), (_, _, b)| a.partial_cmp(&b).unwrap())?;
202
203 let (third_idx, third) = iter
204 .cloned()
205 .enumerate()
206 .filter(|&(i, _)| i != seed_idx && i != nearest_idx)
207 .min_by(|&(_, a), &(_, b)| {
208 let t0 = Triangle(seed, nearest, a);
209 let t1 = Triangle(seed, nearest, b);
210
211 t0.circumradius_sq()
212 .partial_cmp(&t1.circumradius_sq())
213 .unwrap()
214 })?;
215
216 let tri = Triangle(seed, nearest, third);
217
218 if tri.is_right_handed() {
219 Some((tri, [seed_idx, nearest_idx, third_idx]))
220 } else {
221 let tri = Triangle(seed, third, nearest);
222 Some((tri, [seed_idx, third_idx, nearest_idx]))
223 }
224}
225
226pub struct Delaunay {
228 pub dcel: TrianglesDCEL,
229 hull: Hull,
230 stack: Vec<usize>,
231}
232
233impl Delaunay {
234 pub fn new(points: &[Point]) -> Option<Delaunay> {
236 let (seed, seed_indices) = find_seed_triangle(points)?;
237 let seed_circumcenter = seed.circumcenter();
238
239 let mut indices = (0..points.len())
240 .filter(|&i| i != seed_indices[0] && i != seed_indices[1] && i != seed_indices[2])
241 .collect::<Vec<_>>();
242
243 let cmp = |&a: &usize, &b: &usize| {
244 points[a]
245 .distance_sq(seed_circumcenter)
246 .partial_cmp(&points[b].distance_sq(seed_circumcenter))
247 .unwrap()
248 };
249
250 #[cfg(feature = "rayon")]
251 indices.par_sort_by(cmp);
252
253 #[cfg(not(feature = "rayon"))]
254 indices.sort_by(cmp);
255
256 let max_triangles = 2 * points.len() - 3 - 2;
257
258 let mut delaunay = Delaunay {
259 dcel: TrianglesDCEL::with_capacity(max_triangles),
260 hull: Hull::new(seed_indices, points),
261 stack: Vec::with_capacity(STACK_CAPACITY),
262 };
263
264 delaunay.dcel.add_triangle(seed_indices);
265
266 let mut prev_point: Option<Point> = None;
267
268 for &i in &indices {
269 let point = points[i];
270
271 if let Some(p) = prev_point {
272 if p.approx_eq(point) {
273 continue;
274 }
275 }
276
277 delaunay.add_point(i, points);
278 prev_point = Some(point);
279 }
280
281 Some(delaunay)
282 }
283
284 fn add_point(&mut self, index: usize, points: &[Point]) {
285 let point = points[index];
286
287 let (mut start, should_walk_back) = match self.hull.find_visible_edge(point, points) {
288 Some(v) => v,
289 None => return,
290 };
291
292 let mut end = self.hull.next[start];
293
294 let t = self.add_triangle(
295 [start, index, end],
296 [
297 OptionIndex::none(),
298 OptionIndex::none(),
299 self.hull.triangles[start],
300 ],
301 );
302
303 self.hull.triangles[index] = OptionIndex::some(self.legalize(t + 2, points));
304 self.hull.triangles[start] = OptionIndex::some(t);
305
306 loop {
307 let next = self.hull.next[end];
308 let tri = Triangle(point, points[next], points[end]);
309 if !tri.is_right_handed() {
310 break;
311 }
312
313 let t = self.add_triangle(
314 [end, index, next],
315 [
316 self.hull.triangles[index],
317 OptionIndex::none(),
318 self.hull.triangles[end],
319 ],
320 );
321
322 self.hull.triangles[index] = OptionIndex::some(self.legalize(t + 2, points));
323 self.hull.next[end] = end;
324 end = next;
325 }
326
327 if should_walk_back {
328 loop {
329 let prev = self.hull.prev[start];
330 let tri = Triangle(point, points[start], points[prev]);
331 if !tri.is_right_handed() {
332 break;
333 }
334
335 let t = self.add_triangle(
336 [prev, index, start],
337 [
338 OptionIndex::none(),
339 self.hull.triangles[start],
340 self.hull.triangles[prev],
341 ],
342 );
343
344 self.legalize(t + 2, points);
345
346 self.hull.triangles[prev] = OptionIndex::some(t);
347 self.hull.next[start] = start;
348 start = prev;
349 }
350 }
351
352 self.hull.start = start;
353 self.hull.next[start] = index;
354 self.hull.next[index] = end;
355
356 self.hull.prev[end] = index;
357 self.hull.prev[index] = start;
358
359 self.hull.add_hash(index, point);
360 self.hull.add_hash(start, points[start]);
361 }
362
363 fn add_triangle(&mut self, vertices: [usize; 3], halfedges: [OptionIndex; 3]) -> usize {
364 let t = self.dcel.add_triangle(vertices);
365
366 for (i, &halfedge) in halfedges.iter().enumerate() {
367 if let Some(e) = halfedge.get() {
368 self.dcel.link(t + i, e);
369 }
370 }
371
372 t
373 }
374
375 fn legalize(&mut self, index: usize, points: &[Point]) -> usize {
376 self.stack.push(index);
377
378 let mut output = 0;
379
380 while let Some(a) = self.stack.pop() {
381 let ar = self.dcel.prev_edge(a);
382 output = ar;
383
384 let b = match self.dcel.twin(a) {
385 Some(v) => v,
386 None => continue,
387 };
388
389 let br = self.dcel.next_edge(b);
390 let bl = self.dcel.prev_edge(b);
391
392 let [p0, pr, pl] = self.dcel.triangle_points(ar);
409 let p1 = self.dcel.triangle_points(bl)[0];
410
411 let illegal = Triangle(points[p0], points[pr], points[pl]).in_circumcircle(points[p1]);
412
413 if !illegal {
414 continue;
415 }
416
417 self.dcel.vertices[a] = p1;
418 self.dcel.vertices[b] = p0;
419
420 let hbl = self.dcel.twin(bl);
421
422 self.dcel.link_option(a, hbl);
423 self.dcel.link_option(b, self.dcel.twin(ar));
424 self.dcel.link(ar, bl);
425
426 if hbl.is_none() {
427 let mut edge = self.hull.start;
428
429 loop {
430 if self.hull.triangles[edge] == OptionIndex::some(bl) {
431 self.hull.triangles[edge] = OptionIndex::some(a);
432 break;
433 }
434
435 edge = self.hull.next[edge];
436
437 if edge == self.hull.start || edge == self.hull.next[edge] {
438 break;
439 }
440 }
441 }
442
443 if self.stack.len() >= STACK_CAPACITY - 1 {
444 continue;
445 }
446
447 self.stack.push(br);
448 self.stack.push(a);
449 }
450
451 output
452 }
453}