1use itertools::Itertools;
2use std::{cmp, iter, ops};
3
4static DIM: usize = 2;
5static NULL: usize = 0;
6
7#[cfg(test)]
8mod tests;
9
10#[doc(hidden)]
11pub mod legacy;
12
13pub use legacy::deviation;
14pub use legacy::flatten;
15
16type LinkedListNodeIndex = usize;
17type VerticesIndex = usize;
18
19pub trait Float: num_traits::float::Float {}
20
21impl<T> Float for T where T: num_traits::float::Float {}
22
23#[derive(Debug, PartialEq, Copy, Clone)]
24#[non_exhaustive]
25pub enum Error {
26 Unknown,
27}
28
29impl std::fmt::Display for Error {
30 fn fmt(&self, mut f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 match self {
32 Error::Unknown => write!(&mut f, "Unknown error"),
33 }
34 }
35}
36
37impl std::error::Error for Error {}
38
39#[derive(Clone, Copy, Debug, PartialEq)]
40struct Coord<T: Float> {
41 x: T,
42 y: T,
43}
44
45impl<T: Float> Coord<T> {
46 #[inline(always)]
49 fn zorder(&self, invsize: T) -> Result<i32, Error> {
50 let x: i64 = num_traits::cast::<T, i64>(self.x * invsize).ok_or(Error::Unknown)?;
53 let y: i64 = num_traits::cast::<T, i64>(self.y * invsize).ok_or(Error::Unknown)?;
54 let mut xy: i64 = x << 32 | y;
55
56 xy = (xy | (xy << 8)) & 0x00FF00FF00FF00FF;
58 xy = (xy | (xy << 4)) & 0x0F0F0F0F0F0F0F0F;
59 xy = (xy | (xy << 2)) & 0x3333333333333333;
60 xy = (xy | (xy << 1)) & 0x5555555555555555;
61
62 Ok(((xy >> 32) | (xy << 1)) as i32)
63 }
64}
65
66#[derive(Clone, Copy, Debug)]
67struct LinkedListNode<T: Float> {
68 vertices_index: VerticesIndex,
70 coord: Coord<T>,
72 prev_linked_list_node_index: LinkedListNodeIndex,
74 next_linked_list_node_index: LinkedListNodeIndex,
76 z: i32,
78 prevz_idx: LinkedListNodeIndex,
80 nextz_idx: LinkedListNodeIndex,
82 is_steiner_point: bool,
84 idx: LinkedListNodeIndex,
86}
87
88impl<T: Float> LinkedListNode<T> {
89 fn new(i: VerticesIndex, coord: Coord<T>, idx: LinkedListNodeIndex) -> LinkedListNode<T> {
90 LinkedListNode {
91 vertices_index: i,
92 coord,
93 prev_linked_list_node_index: NULL,
94 next_linked_list_node_index: NULL,
95 z: 0,
96 nextz_idx: NULL,
97 prevz_idx: NULL,
98 is_steiner_point: false,
99 idx,
100 }
101 }
102
103 fn xy_eq(&self, other: LinkedListNode<T>) -> bool {
105 self.coord == other.coord
106 }
107
108 fn prev_linked_list_node(&self, linked_list_nodes: &LinkedLists<T>) -> LinkedListNode<T> {
109 linked_list_nodes.nodes[self.prev_linked_list_node_index]
110 }
111
112 fn next_linked_list_node(&self, linked_list_nodes: &LinkedLists<T>) -> LinkedListNode<T> {
113 linked_list_nodes.nodes[self.next_linked_list_node_index]
114 }
115}
116
117pub struct LinkedLists<T: Float> {
118 nodes: Vec<LinkedListNode<T>>,
119 invsize: T,
120 min: Coord<T>,
121 max: Coord<T>,
122 usehash: bool,
123}
124
125struct Vertices<'a, T: Float>(&'a [T]);
126
127impl<'a, T: Float> Vertices<'a, T> {
128 fn is_empty(&'a self) -> bool {
129 self.0.is_empty()
130 }
131
132 fn len(&'a self) -> usize {
133 self.0.len()
134 }
135
136 fn signed_area(&self, start: VerticesIndex, end: VerticesIndex) -> T {
137 let i = (start..end).step_by(DIM);
138 let j = (start..end).cycle().skip((end - DIM) - start).step_by(DIM);
139 let zero = T::zero();
140 i.zip(j).fold(zero, |s, (i, j)| {
141 s + (self.0[j] - self.0[i]) * (self.0[i + 1] + self.0[j + 1])
142 })
143 }
144}
145
146macro_rules! next {
148 ($ll:expr,$idx:expr) => {
149 $ll.nodes[$ll.nodes[$idx].next_linked_list_node_index]
150 };
151}
152macro_rules! nextref {
153 ($ll:expr,$idx:expr) => {
154 &$ll.nodes[$ll.nodes[$idx].next_linked_list_node_index]
155 };
156}
157macro_rules! prev {
158 ($ll:expr,$idx:expr) => {
159 $ll.nodes[$ll.nodes[$idx].prev_linked_list_node_index]
160 };
161}
162macro_rules! prevref {
163 ($ll:expr,$idx:expr) => {
164 &$ll.nodes[$ll.nodes[$idx].prev_linked_list_node_index]
165 };
166}
167
168impl<T: Float> LinkedLists<T> {
169 fn iter(&self, r: ops::Range<LinkedListNodeIndex>) -> NodeIterator<T> {
170 NodeIterator::new(self, r.start, r.end)
171 }
172
173 fn iter_pairs(&self, r: ops::Range<LinkedListNodeIndex>) -> NodePairIterator<T> {
174 NodePairIterator::new(self, r.start, r.end)
175 }
176
177 fn insert_node(
178 &mut self,
179 i: VerticesIndex,
180 coord: Coord<T>,
181 last: Option<LinkedListNodeIndex>,
182 ) -> LinkedListNodeIndex {
183 let mut p = LinkedListNode::new(i, coord, self.nodes.len());
184 match last {
185 None => {
186 p.next_linked_list_node_index = p.idx;
187 p.prev_linked_list_node_index = p.idx;
188 }
189 Some(last) => {
190 p.next_linked_list_node_index = self.nodes[last].next_linked_list_node_index;
191 p.prev_linked_list_node_index = last;
192 let lastnextidx = self.nodes[last].next_linked_list_node_index;
193 self.nodes[lastnextidx].prev_linked_list_node_index = p.idx;
194 self.nodes[last].next_linked_list_node_index = p.idx;
195 }
196 }
197 let result = p.idx;
198 self.nodes.push(p);
199 result
200 }
201 fn remove_node(&mut self, p_idx: LinkedListNodeIndex) {
202 let pi = self.nodes[p_idx].prev_linked_list_node_index;
203 let ni = self.nodes[p_idx].next_linked_list_node_index;
204 let pz = self.nodes[p_idx].prevz_idx;
205 let nz = self.nodes[p_idx].nextz_idx;
206 self.nodes[pi].next_linked_list_node_index = ni;
207 self.nodes[ni].prev_linked_list_node_index = pi;
208 self.nodes[pz].nextz_idx = nz;
209 self.nodes[nz].prevz_idx = pz;
210 }
211 fn new(size_hint: usize) -> LinkedLists<T> {
212 let mut ll = LinkedLists {
213 nodes: Vec::with_capacity(size_hint),
214 invsize: T::zero(),
215 min: Coord {
216 x: T::max_value(),
217 y: T::max_value(),
218 },
219 max: Coord {
220 x: T::min_value(),
221 y: T::min_value(),
222 },
223 usehash: true,
224 };
225 ll.nodes.push(LinkedListNode {
227 vertices_index: 0,
228 coord: Coord {
229 x: T::zero(),
230 y: T::zero(),
231 },
232 prev_linked_list_node_index: 0,
233 next_linked_list_node_index: 0,
234 z: 0,
235 nextz_idx: 0,
236 prevz_idx: 0,
237 is_steiner_point: false,
238 idx: 0,
239 });
240 ll
241 }
242
243 fn index_curve(&mut self, start: LinkedListNodeIndex) -> Result<(), Error> {
245 let invsize = self.invsize;
246 let mut p = start;
247 loop {
248 if self.nodes[p].z == 0 {
249 self.nodes[p].z = self.nodes[p].coord.zorder(invsize)?;
250 }
251 self.nodes[p].prevz_idx = self.nodes[p].prev_linked_list_node_index;
252 self.nodes[p].nextz_idx = self.nodes[p].next_linked_list_node_index;
253 p = self.nodes[p].next_linked_list_node_index;
254 if p == start {
255 break;
256 }
257 }
258
259 let pzi = self.nodes[start].prevz_idx;
260 self.nodes[pzi].nextz_idx = NULL;
261 self.nodes[start].prevz_idx = NULL;
262 self.sort_linked(start);
263 Ok(())
264 }
265
266 fn eliminate_hole(
269 &mut self,
270 hole_idx: LinkedListNodeIndex,
271 outer_node_idx: LinkedListNodeIndex,
272 ) {
273 let test_idx = find_hole_bridge(self, hole_idx, outer_node_idx);
274 let b = split_bridge_polygon(self, test_idx, hole_idx);
275 let ni = self.nodes[b].next_linked_list_node_index;
276 filter_points(self, b, Some(ni));
277 }
278
279 fn sort_linked(&mut self, mut list: LinkedListNodeIndex) {
282 let mut p;
283 let mut q;
284 let mut e;
285 let mut nummerges;
286 let mut psize;
287 let mut qsize;
288 let mut insize = 1;
289 let mut tail;
290
291 loop {
292 p = list;
293 list = NULL;
294 tail = NULL;
295 nummerges = 0;
296
297 while p != NULL {
298 nummerges += 1;
299 q = p;
300 psize = 0;
301 while q != NULL && psize < insize {
302 psize += 1;
303 q = self.nodes[q].nextz_idx;
304 }
305 qsize = insize;
306
307 while psize > 0 || (qsize > 0 && q != NULL) {
308 if psize > 0 && (qsize == 0 || q == NULL || self.nodes[p].z <= self.nodes[q].z)
309 {
310 e = p;
311 p = self.nodes[p].nextz_idx;
312 psize -= 1;
313 } else {
314 e = q;
315 q = self.nodes[q].nextz_idx;
316 qsize -= 1;
317 }
318
319 if tail != NULL {
320 self.nodes[tail].nextz_idx = e;
321 } else {
322 list = e;
323 }
324
325 self.nodes[e].prevz_idx = tail;
326 tail = e;
327 }
328
329 p = q;
330 }
331
332 self.nodes[tail].nextz_idx = NULL;
333 insize *= 2;
334 if nummerges <= 1 {
335 break;
336 }
337 }
338 }
339
340 fn add_contour(
342 &mut self,
343 vertices: &Vertices<T>,
344 start: VerticesIndex,
345 end: VerticesIndex,
346 clockwise: bool,
347 ) -> Result<(LinkedListNodeIndex, LinkedListNodeIndex), Error> {
348 if start > vertices.len() || end > vertices.len() || vertices.is_empty() {
349 return Err(Error::Unknown);
350 }
351
352 if end < DIM || end - DIM < start {
353 return Err(Error::Unknown);
354 }
355
356 if end < DIM {
357 return Err(Error::Unknown);
358 }
359
360 let mut lastidx = None;
361 let mut leftmost_idx = None;
362 let mut contour_minx = T::max_value();
363
364 let clockwise_iter = vertices.0[start..end].iter().copied().enumerate();
365
366 let mut iter_body = |x_index: usize, x: T, y_index: usize, y: T| {
367 lastidx = Some(self.insert_node((start + x_index) / DIM, Coord { x, y }, lastidx));
368 if contour_minx > x {
369 contour_minx = x;
370 leftmost_idx = lastidx
371 };
372 if self.usehash {
373 self.min.y = vertices.0[y_index].min(self.min.y);
374 self.max.x = vertices.0[x_index].max(self.max.x);
375 self.max.y = vertices.0[y_index].max(self.max.y);
376 }
377 };
378
379 if clockwise == (vertices.signed_area(start, end) > T::zero()) {
380 for ((x_index, x), (y_index, y)) in clockwise_iter.tuples() {
381 iter_body(x_index, x, y_index, y);
382 }
383 } else {
384 for ((y_index, y), (x_index, x)) in clockwise_iter.rev().tuples() {
385 iter_body(x_index, x, y_index, y);
386 }
387 }
388
389 self.min.x = contour_minx.min(self.min.x);
390
391 if self.nodes[lastidx.unwrap()].xy_eq(*nextref!(self, lastidx.unwrap())) {
392 self.remove_node(lastidx.unwrap());
393 lastidx = Some(self.nodes[lastidx.unwrap()].next_linked_list_node_index);
394 }
395 Ok((lastidx.unwrap(), leftmost_idx.unwrap()))
396 }
397
398 fn is_valid_diagonal(&self, a: &LinkedListNode<T>, b: &LinkedListNode<T>) -> bool {
401 next!(self, a.idx).vertices_index != b.vertices_index
402 && prev!(self, a.idx).vertices_index != b.vertices_index
403 && !intersects_polygon(self, *a, *b)
404 && locally_inside(self, a, b)
405 && locally_inside(self, b, a)
406 && middle_inside(self, a, b)
407 }
408}
409
410struct NodeIterator<'a, T: Float> {
411 cur: LinkedListNodeIndex,
412 end: LinkedListNodeIndex,
413 ll: &'a LinkedLists<T>,
414 pending_result: Option<&'a LinkedListNode<T>>,
415}
416
417impl<'a, T: Float> NodeIterator<'a, T> {
418 fn new(
419 ll: &LinkedLists<T>,
420 start: LinkedListNodeIndex,
421 end: LinkedListNodeIndex,
422 ) -> NodeIterator<T> {
423 NodeIterator {
424 pending_result: Some(&ll.nodes[start]),
425 cur: start,
426 end,
427 ll,
428 }
429 }
430}
431
432impl<'a, T: Float> Iterator for NodeIterator<'a, T> {
433 type Item = &'a LinkedListNode<T>;
434 fn next(&mut self) -> Option<Self::Item> {
435 self.cur = self.ll.nodes[self.cur].next_linked_list_node_index;
436 let cur_result = self.pending_result;
437 self.pending_result = if self.cur == self.end {
438 None
440 } else {
441 Some(&self.ll.nodes[self.cur])
442 };
443 cur_result
444 }
445}
446
447struct NodePairIterator<'a, T: Float> {
448 cur: LinkedListNodeIndex,
449 end: LinkedListNodeIndex,
450 ll: &'a LinkedLists<T>,
451 pending_result: Option<(&'a LinkedListNode<T>, &'a LinkedListNode<T>)>,
452}
453
454impl<'a, T: Float> NodePairIterator<'a, T> {
455 fn new(
456 ll: &LinkedLists<T>,
457 start: LinkedListNodeIndex,
458 end: LinkedListNodeIndex,
459 ) -> NodePairIterator<T> {
460 NodePairIterator {
461 pending_result: Some((&ll.nodes[start], nextref!(ll, start))),
462 cur: start,
463 end,
464 ll,
465 }
466 }
467}
468
469impl<'a, T: Float> Iterator for NodePairIterator<'a, T> {
470 type Item = (&'a LinkedListNode<T>, &'a LinkedListNode<T>);
471 fn next(&mut self) -> Option<Self::Item> {
472 self.cur = self.ll.nodes[self.cur].next_linked_list_node_index;
473 let cur_result = self.pending_result;
474 if self.cur == self.end {
475 self.pending_result = None;
477 } else {
478 self.pending_result = Some((&self.ll.nodes[self.cur], nextref!(self.ll, self.cur)))
479 }
480 cur_result
481 }
482}
483
484fn eliminate_holes<T: Float>(
487 ll: &mut LinkedLists<T>,
488 vertices: &Vertices<T>,
489 hole_indices: &[VerticesIndex],
490 inouter_node: LinkedListNodeIndex,
491) -> Result<LinkedListNodeIndex, Error> {
492 let mut outer_node = inouter_node;
493 let mut queue: Vec<LinkedListNode<T>> = Vec::new();
494 for (vertices_hole_start_index, vertices_hole_end_index) in hole_indices
495 .iter()
496 .map(|index| index.checked_mul(DIM).ok_or(Error::Unknown))
497 .chain(iter::once(Ok(vertices.0.len())))
498 .tuple_windows()
499 {
500 let vertices_hole_start_index = vertices_hole_start_index?;
501 let vertices_hole_end_index = vertices_hole_end_index?;
502 let (list, leftmost_idx) = ll.add_contour(
503 vertices,
504 vertices_hole_start_index,
505 vertices_hole_end_index,
506 false,
507 )?;
508 if list == ll.nodes[list].next_linked_list_node_index {
509 ll.nodes[list].is_steiner_point = true;
510 }
511 queue.push(ll.nodes[leftmost_idx]);
512 }
513
514 queue.sort_by(|a, b| {
515 a.coord
516 .x
517 .partial_cmp(&b.coord.x)
518 .unwrap_or(cmp::Ordering::Equal)
519 });
520
521 for node in queue {
523 ll.eliminate_hole(node.idx, outer_node);
524 let nextidx = next!(ll, outer_node).idx;
525 outer_node = filter_points(ll, outer_node, Some(nextidx));
526 }
527 Ok(outer_node)
528} fn calc_invsize<T: Float>(min: Coord<T>, max: Coord<T>) -> T {
533 let invsize = (max.x - min.x).max(max.y - min.y);
534 match invsize.is_zero() {
535 true => T::zero(),
536 false => num_traits::cast::<f64, T>(32767.0).unwrap() / invsize,
537 }
538}
539
540fn earcut_linked_hashed<const PASS: usize, T: Float>(
543 ll: &mut LinkedLists<T>,
544 mut ear_idx: LinkedListNodeIndex,
545 triangle_indices: &mut FinalTriangleIndices,
546) -> Result<(), Error> {
547 if PASS == 0 {
549 ll.index_curve(ear_idx)?;
550 }
551 let mut stop_idx = ear_idx;
553 let mut prev_idx = 0;
554 let mut next_idx = ll.nodes[ear_idx].next_linked_list_node_index;
555 while stop_idx != next_idx {
556 prev_idx = ll.nodes[ear_idx].prev_linked_list_node_index;
557 next_idx = ll.nodes[ear_idx].next_linked_list_node_index;
558 let node_index_triangle = NodeIndexTriangle(prev_idx, ear_idx, next_idx);
559 if node_index_triangle.node_triangle(ll).is_ear_hashed(ll)? {
560 triangle_indices.push(VerticesIndexTriangle(
561 ll.nodes[prev_idx].vertices_index,
562 ll.nodes[ear_idx].vertices_index,
563 ll.nodes[next_idx].vertices_index,
564 ));
565 ll.remove_node(ear_idx);
566 ear_idx = ll.nodes[next_idx].next_linked_list_node_index;
568 stop_idx = ear_idx;
569 } else {
570 ear_idx = next_idx;
571 }
572 }
573
574 if prev_idx == next_idx {
575 return Ok(());
576 };
577 if PASS == 0 {
580 let tmp = filter_points(ll, next_idx, None);
581 earcut_linked_hashed::<1, T>(ll, tmp, triangle_indices)?;
582 } else if PASS == 1 {
583 ear_idx = cure_local_intersections(ll, next_idx, triangle_indices);
584 earcut_linked_hashed::<2, T>(ll, ear_idx, triangle_indices)?;
585 } else if PASS == 2 {
586 split_earcut(ll, next_idx, triangle_indices)?;
587 }
588 Ok(())
589}
590
591fn earcut_linked_unhashed<const PASS: usize, T: Float>(
594 ll: &mut LinkedLists<T>,
595 mut ear_idx: LinkedListNodeIndex,
596 triangles: &mut FinalTriangleIndices,
597) -> Result<(), Error> {
598 let mut stop_idx = ear_idx;
600 let mut prev_idx = 0;
601 let mut next_idx = ll.nodes[ear_idx].next_linked_list_node_index;
602 while stop_idx != next_idx {
603 prev_idx = ll.nodes[ear_idx].prev_linked_list_node_index;
604 next_idx = ll.nodes[ear_idx].next_linked_list_node_index;
605 if NodeIndexTriangle(prev_idx, ear_idx, next_idx).is_ear(ll) {
606 triangles.push(VerticesIndexTriangle(
607 ll.nodes[prev_idx].vertices_index,
608 ll.nodes[ear_idx].vertices_index,
609 ll.nodes[next_idx].vertices_index,
610 ));
611 ll.remove_node(ear_idx);
612 ear_idx = ll.nodes[next_idx].next_linked_list_node_index;
614 stop_idx = ear_idx;
615 } else {
616 ear_idx = next_idx;
617 }
618 }
619
620 if prev_idx == next_idx {
621 return Ok(());
622 };
623 if PASS == 0 {
626 let tmp = filter_points(ll, next_idx, None);
627 earcut_linked_unhashed::<1, T>(ll, tmp, triangles)?;
628 } else if PASS == 1 {
629 ear_idx = cure_local_intersections(ll, next_idx, triangles);
630 earcut_linked_unhashed::<2, T>(ll, ear_idx, triangles)?;
631 } else if PASS == 2 {
632 split_earcut(ll, next_idx, triangles)?;
633 }
634 Ok(())
635}
636
637#[derive(Clone, Copy)]
638struct NodeIndexTriangle(
639 LinkedListNodeIndex,
640 LinkedListNodeIndex,
641 LinkedListNodeIndex,
642);
643
644impl NodeIndexTriangle {
645 fn prev_node<T: Float>(self, ll: &LinkedLists<T>) -> LinkedListNode<T> {
646 ll.nodes[self.0]
647 }
648
649 fn ear_node<T: Float>(self, ll: &LinkedLists<T>) -> LinkedListNode<T> {
650 ll.nodes[self.1]
651 }
652
653 fn next_node<T: Float>(self, ll: &LinkedLists<T>) -> LinkedListNode<T> {
654 ll.nodes[self.2]
655 }
656
657 fn node_triangle<T: Float>(self, ll: &LinkedLists<T>) -> NodeTriangle<T> {
658 NodeTriangle(self.prev_node(ll), self.ear_node(ll), self.next_node(ll))
659 }
660
661 fn area<T: Float>(self, ll: &LinkedLists<T>) -> T {
662 self.node_triangle(ll).area()
663 }
664
665 fn is_ear<T: Float>(self, ll: &LinkedLists<T>) -> bool {
667 let zero = T::zero();
668 match self.area(ll) >= zero {
669 true => false, false => !ll
671 .iter(self.next_node(ll).next_linked_list_node_index..self.prev_node(ll).idx)
672 .any(|p| {
673 self.node_triangle(ll).contains_point(*p)
674 && (NodeTriangle(*prevref!(ll, p.idx), *p, *nextref!(ll, p.idx)).area()
675 >= zero)
676 }),
677 }
678 }
679}
680
681#[derive(Clone, Copy)]
682struct NodeTriangle<T: Float>(LinkedListNode<T>, LinkedListNode<T>, LinkedListNode<T>);
683
684impl<T: Float> NodeTriangle<T> {
685 fn from_ear_node(ear_node: LinkedListNode<T>, ll: &LinkedLists<T>) -> Self {
686 NodeTriangle(
687 ear_node.prev_linked_list_node(ll),
688 ear_node,
689 ear_node.next_linked_list_node(ll),
690 )
691 }
692
693 fn area(&self) -> T {
694 let p = self.0;
695 let q = self.1;
696 let r = self.2;
697 (q.coord.y - p.coord.y) * (r.coord.x - q.coord.x)
699 - (q.coord.x - p.coord.x) * (r.coord.y - q.coord.y)
700 }
701
702 fn contains_point(&self, p: LinkedListNode<T>) -> bool {
704 let zero = T::zero();
705
706 ((self.2.coord.x - p.coord.x) * (self.0.coord.y - p.coord.y)
707 - (self.0.coord.x - p.coord.x) * (self.2.coord.y - p.coord.y)
708 >= zero)
709 && ((self.0.coord.x - p.coord.x) * (self.1.coord.y - p.coord.y)
710 - (self.1.coord.x - p.coord.x) * (self.0.coord.y - p.coord.y)
711 >= zero)
712 && ((self.1.coord.x - p.coord.x) * (self.2.coord.y - p.coord.y)
713 - (self.2.coord.x - p.coord.x) * (self.1.coord.y - p.coord.y)
714 >= zero)
715 }
716
717 #[inline(always)]
718 fn is_ear_hashed(&self, ll: &mut LinkedLists<T>) -> Result<bool, Error> {
719 let zero = T::zero();
720
721 if self.area() >= zero {
722 return Ok(false);
723 };
724 let NodeTriangle(prev, ear, next) = self;
725
726 let bbox_maxx = prev.coord.x.max(ear.coord.x.max(next.coord.x));
727 let bbox_maxy = prev.coord.y.max(ear.coord.y.max(next.coord.y));
728 let bbox_minx = prev.coord.x.min(ear.coord.x.min(next.coord.x));
729 let bbox_miny = prev.coord.y.min(ear.coord.y.min(next.coord.y));
730 let min_z = Coord {
732 x: bbox_minx,
733 y: bbox_miny,
734 }
735 .zorder(ll.invsize)?;
736 let max_z = Coord {
737 x: bbox_maxx,
738 y: bbox_maxy,
739 }
740 .zorder(ll.invsize)?;
741
742 let mut p = ear.prevz_idx;
743 let mut n = ear.nextz_idx;
744 while (p != NULL) && (ll.nodes[p].z >= min_z) && (n != NULL) && (ll.nodes[n].z <= max_z) {
745 if earcheck(
746 prev,
747 ear,
748 next,
749 prevref!(ll, p),
750 &ll.nodes[p],
751 nextref!(ll, p),
752 ) {
753 return Ok(false);
754 }
755 p = ll.nodes[p].prevz_idx;
756
757 if earcheck(
758 prev,
759 ear,
760 next,
761 prevref!(ll, n),
762 &ll.nodes[n],
763 nextref!(ll, n),
764 ) {
765 return Ok(false);
766 }
767 n = ll.nodes[n].nextz_idx;
768 }
769
770 ll.nodes[NULL].z = min_z - 1;
771 while ll.nodes[p].z >= min_z {
772 if earcheck(
773 prev,
774 ear,
775 next,
776 prevref!(ll, p),
777 &ll.nodes[p],
778 nextref!(ll, p),
779 ) {
780 return Ok(false);
781 }
782 p = ll.nodes[p].prevz_idx;
783 }
784
785 ll.nodes[NULL].z = max_z + 1;
786 while ll.nodes[n].z <= max_z {
787 if earcheck(
788 prev,
789 ear,
790 next,
791 prevref!(ll, n),
792 &ll.nodes[n],
793 nextref!(ll, n),
794 ) {
795 return Ok(false);
796 }
797 n = ll.nodes[n].nextz_idx;
798 }
799
800 Ok(true)
801 }
802}
803
804#[inline(always)]
806fn earcheck<T: Float>(
807 a: &LinkedListNode<T>,
808 b: &LinkedListNode<T>,
809 c: &LinkedListNode<T>,
810 prev: &LinkedListNode<T>,
811 p: &LinkedListNode<T>,
812 next: &LinkedListNode<T>,
813) -> bool {
814 let zero = T::zero();
815
816 (p.idx != a.idx)
817 && (p.idx != c.idx)
818 && NodeTriangle(*a, *b, *c).contains_point(*p)
819 && NodeTriangle(*prev, *p, *next).area() >= zero
820}
821
822fn filter_points<T: Float>(
823 ll: &mut LinkedLists<T>,
824 start: LinkedListNodeIndex,
825 end: Option<LinkedListNodeIndex>,
826) -> LinkedListNodeIndex {
827 let mut end = end.unwrap_or(start);
828 if end >= ll.nodes.len() || start >= ll.nodes.len() {
829 return NULL;
830 }
831
832 let mut p = start;
833 let mut again;
834
835 loop {
839 again = false;
840 if !ll.nodes[p].is_steiner_point
841 && (ll.nodes[p].xy_eq(ll.nodes[ll.nodes[p].next_linked_list_node_index])
842 || NodeTriangle::from_ear_node(ll.nodes[p], ll)
843 .area()
844 .is_zero())
845 {
846 ll.remove_node(p);
847 end = ll.nodes[p].prev_linked_list_node_index;
848 p = end;
849 if p == ll.nodes[p].next_linked_list_node_index {
850 break end;
851 }
852 again = true;
853 } else {
854 if p == ll.nodes[p].next_linked_list_node_index {
855 break NULL;
856 }
857 p = ll.nodes[p].next_linked_list_node_index;
858 }
859 if !again && p == end {
860 break end;
861 }
862 }
863}
864
865fn linked_list<T: Float>(
868 vertices: &Vertices<T>,
869 start: usize,
870 end: usize,
871 clockwise: bool,
872) -> Result<(LinkedLists<T>, LinkedListNodeIndex), Error> {
873 let mut ll: LinkedLists<T> = LinkedLists::new(vertices.len() / DIM);
874 if vertices.len() < 80 {
875 ll.usehash = false
876 };
877 let (last_idx, _) = ll.add_contour(vertices, start, end, clockwise)?;
878 Ok((ll, last_idx))
879}
880
881struct VerticesIndexTriangle(usize, usize, usize);
882
883#[derive(Default, Debug)]
884struct FinalTriangleIndices(Vec<usize>);
885
886impl FinalTriangleIndices {
887 fn push(&mut self, vertices_index_triangle: VerticesIndexTriangle) {
888 self.0.push(vertices_index_triangle.0);
889 self.0.push(vertices_index_triangle.1);
890 self.0.push(vertices_index_triangle.2);
891 }
892}
893
894pub fn earcut<T: Float>(
895 vertices: &[T],
896 hole_indices: &[VerticesIndex],
897 dims: usize,
898) -> Result<Vec<usize>, Error> {
899 if vertices.is_empty() && hole_indices.is_empty() {
900 return Ok(vec![]);
901 }
902
903 if vertices.len() % 2 == 1 || dims > vertices.len() {
904 return Err(Error::Unknown);
905 }
906
907 let outer_len = match hole_indices.first() {
908 Some(first_hole_index) => {
909 let outer_len = first_hole_index.checked_mul(DIM).ok_or(Error::Unknown)?;
910 if outer_len > vertices.len() || outer_len == 0 {
911 return Err(Error::Unknown);
912 }
913 if outer_len % 2 == 1 {
914 return Err(Error::Unknown);
915 }
916 outer_len
917 }
918 None => vertices.len(),
919 };
920
921 let vertices = Vertices(vertices);
922 let (mut ll, outer_node) = linked_list(&vertices, 0, outer_len, true)?;
923 let mut triangles = FinalTriangleIndices(Vec::with_capacity(vertices.len() / DIM));
924 if ll.nodes.len() == 1 || DIM != dims {
925 return Ok(triangles.0);
926 }
927
928 let outer_node = eliminate_holes(&mut ll, &vertices, hole_indices, outer_node)?;
929
930 if ll.usehash {
931 ll.invsize = calc_invsize(ll.min, ll.max);
932
933 let (mx, my) = (ll.min.x, ll.min.y);
939 ll.nodes.iter_mut().for_each(|n| {
940 n.coord.x = n.coord.x - mx;
941 n.coord.y = n.coord.y - my;
942 });
943 earcut_linked_hashed::<0, T>(&mut ll, outer_node, &mut triangles)?;
944 } else {
945 earcut_linked_unhashed::<0, T>(&mut ll, outer_node, &mut triangles)?;
946 }
947
948 Ok(triangles.0)
949}
950
951fn cure_local_intersections<T: Float>(
961 ll: &mut LinkedLists<T>,
962 instart: LinkedListNodeIndex,
963 triangles: &mut FinalTriangleIndices,
964) -> LinkedListNodeIndex {
965 let mut p = instart;
966 let mut start = instart;
967
968 loop {
984 let a = ll.nodes[p].prev_linked_list_node_index;
985 let b = next!(ll, p).next_linked_list_node_index;
986
987 if !ll.nodes[a].xy_eq(ll.nodes[b])
988 && pseudo_intersects(
989 ll.nodes[a],
990 ll.nodes[p],
991 *nextref!(ll, p),
992 ll.nodes[b],
993 )
994 && locally_inside(ll, &ll.nodes[a], &ll.nodes[b])
996 && locally_inside(ll, &ll.nodes[b], &ll.nodes[a])
997 {
998 triangles.push(VerticesIndexTriangle(
999 ll.nodes[a].vertices_index,
1000 ll.nodes[p].vertices_index,
1001 ll.nodes[b].vertices_index,
1002 ));
1003
1004 ll.remove_node(p);
1006 let nidx = ll.nodes[p].next_linked_list_node_index;
1007 ll.remove_node(nidx);
1008
1009 start = ll.nodes[b].idx;
1010 p = start;
1011 }
1012 p = ll.nodes[p].next_linked_list_node_index;
1013 if p == start {
1014 break;
1015 }
1016 }
1017
1018 p
1019}
1020
1021fn split_earcut<T: Float>(
1023 ll: &mut LinkedLists<T>,
1024 start_idx: LinkedListNodeIndex,
1025 triangles: &mut FinalTriangleIndices,
1026) -> Result<(), Error> {
1027 let mut a = start_idx;
1029 loop {
1030 let mut b = next!(ll, a).next_linked_list_node_index;
1031 while b != ll.nodes[a].prev_linked_list_node_index {
1032 if ll.nodes[a].vertices_index != ll.nodes[b].vertices_index
1033 && ll.is_valid_diagonal(&ll.nodes[a], &ll.nodes[b])
1034 {
1035 let mut c = split_bridge_polygon(ll, a, b);
1037
1038 let an = ll.nodes[a].next_linked_list_node_index;
1040 let cn = ll.nodes[c].next_linked_list_node_index;
1041 a = filter_points(ll, a, Some(an));
1042 c = filter_points(ll, c, Some(cn));
1043
1044 earcut_linked_hashed::<0, T>(ll, a, triangles)?;
1046 earcut_linked_hashed::<0, T>(ll, c, triangles)?;
1047 return Ok(());
1048 }
1049 b = ll.nodes[b].next_linked_list_node_index;
1050 }
1051 a = ll.nodes[a].next_linked_list_node_index;
1052 if a == start_idx {
1053 break;
1054 }
1055 }
1056 Ok(())
1057}
1058
1059fn find_hole_bridge<T: Float>(
1061 ll: &LinkedLists<T>,
1062 hole: LinkedListNodeIndex,
1063 outer_node: LinkedListNodeIndex,
1064) -> LinkedListNodeIndex {
1065 let mut p = outer_node;
1066 let hx = ll.nodes[hole].coord.x;
1067 let hy = ll.nodes[hole].coord.y;
1068 let mut qx = T::neg_infinity();
1069 let mut m: Option<LinkedListNodeIndex> = None;
1070
1071 let calcx = |p: &LinkedListNode<T>| {
1075 p.coord.x
1076 + (hy - p.coord.y) * (next!(ll, p.idx).coord.x - p.coord.x)
1077 / (next!(ll, p.idx).coord.y - p.coord.y)
1078 };
1079 for (p, n) in ll
1080 .iter_pairs(p..outer_node)
1081 .filter(|(p, n)| hy <= p.coord.y && hy >= n.coord.y)
1082 .filter(|(p, n)| n.coord.y != p.coord.y)
1083 .filter(|(p, _)| calcx(p) <= hx)
1084 {
1085 if qx < calcx(p) {
1086 qx = calcx(p);
1087 if qx == hx && hy == p.coord.y {
1088 return p.idx;
1089 } else if qx == hx && hy == n.coord.y {
1090 return p.next_linked_list_node_index;
1091 }
1092 m = Some(if p.coord.x < n.coord.x { p.idx } else { n.idx });
1093 }
1094 }
1095
1096 let m = match m {
1097 Some(m) => m,
1098 None => return NULL,
1099 };
1100
1101 if hx == qx {
1103 return prev!(ll, m).idx;
1104 }
1105
1106 let mp = LinkedListNode::new(0, ll.nodes[m].coord, 0);
1112 p = next!(ll, m).idx;
1113 let x1 = if hy < mp.coord.y { hx } else { qx };
1114 let x2 = if hy < mp.coord.y { qx } else { hx };
1115 let n1 = LinkedListNode::new(0, Coord { x: x1, y: hy }, 0);
1116 let n2 = LinkedListNode::new(0, Coord { x: x2, y: hy }, 0);
1117 let two = num_traits::cast::<f64, T>(2.).unwrap();
1118
1119 let calctan = |p: &LinkedListNode<T>| (hy - p.coord.y).abs() / (hx - p.coord.x); ll.iter(p..m)
1121 .filter(|p| hx > p.coord.x && p.coord.x >= mp.coord.x)
1122 .filter(|p| NodeTriangle(n1, mp, n2).contains_point(**p))
1123 .fold((m, T::max_value() / two), |(m, tan_min), p| {
1124 if ((calctan(p) < tan_min)
1125 || (calctan(p) == tan_min && p.coord.x > ll.nodes[m].coord.x))
1126 && locally_inside(ll, p, &ll.nodes[hole])
1127 {
1128 (p.idx, calctan(p))
1129 } else {
1130 (m, tan_min)
1131 }
1132 })
1133 .0
1134}
1135
1136fn pseudo_intersects<T: Float>(
1167 p1: LinkedListNode<T>,
1168 q1: LinkedListNode<T>,
1169 p2: LinkedListNode<T>,
1170 q2: LinkedListNode<T>,
1171) -> bool {
1172 if (p1.xy_eq(p2) && q1.xy_eq(q2)) || (p1.xy_eq(q2) && q1.xy_eq(p2)) {
1173 return true;
1174 }
1175 let zero = T::zero();
1176
1177 (NodeTriangle(p1, q1, p2).area() > zero) != (NodeTriangle(p1, q1, q2).area() > zero)
1178 && (NodeTriangle(p2, q2, p1).area() > zero) != (NodeTriangle(p2, q2, q1).area() > zero)
1179}
1180
1181fn intersects_polygon<T: Float>(
1183 ll: &LinkedLists<T>,
1184 a: LinkedListNode<T>,
1185 b: LinkedListNode<T>,
1186) -> bool {
1187 ll.iter_pairs(a.idx..a.idx).any(|(p, n)| {
1188 p.vertices_index != a.vertices_index
1189 && n.vertices_index != a.vertices_index
1190 && p.vertices_index != b.vertices_index
1191 && n.vertices_index != b.vertices_index
1192 && pseudo_intersects(*p, *n, a, b)
1193 })
1194}
1195
1196fn locally_inside<T: Float>(
1198 ll: &LinkedLists<T>,
1199 a: &LinkedListNode<T>,
1200 b: &LinkedListNode<T>,
1201) -> bool {
1202 let zero = T::zero();
1203
1204 match NodeTriangle(*prevref!(ll, a.idx), *a, *nextref!(ll, a.idx)).area() < zero {
1205 true => {
1206 NodeTriangle(*a, *b, *nextref!(ll, a.idx)).area() >= zero
1207 && NodeTriangle(*a, *prevref!(ll, a.idx), *b).area() >= zero
1208 }
1209 false => {
1210 NodeTriangle(*a, *b, *prevref!(ll, a.idx)).area() < zero
1211 || NodeTriangle(*a, *nextref!(ll, a.idx), *b).area() < zero
1212 }
1213 }
1214}
1215
1216fn middle_inside<T: Float>(
1218 ll: &LinkedLists<T>,
1219 a: &LinkedListNode<T>,
1220 b: &LinkedListNode<T>,
1221) -> bool {
1222 let two = T::one() + T::one();
1223
1224 let (mx, my) = ((a.coord.x + b.coord.x) / two, (a.coord.y + b.coord.y) / two);
1225 ll.iter_pairs(a.idx..a.idx)
1226 .filter(|(p, n)| (p.coord.y > my) != (n.coord.y > my))
1227 .filter(|(p, n)| n.coord.y != p.coord.y)
1228 .filter(|(p, n)| {
1229 (mx) < ((n.coord.x - p.coord.x) * (my - p.coord.y) / (n.coord.y - p.coord.y)
1230 + p.coord.x)
1231 })
1232 .fold(false, |inside, _| !inside)
1233}
1234
1235fn split_bridge_polygon<T: Float>(
1308 ll: &mut LinkedLists<T>,
1309 a: LinkedListNodeIndex,
1310 b: LinkedListNodeIndex,
1311) -> LinkedListNodeIndex {
1312 let cidx = ll.nodes.len();
1313 let didx = cidx + 1;
1314 let mut c = LinkedListNode::new(ll.nodes[a].vertices_index, ll.nodes[a].coord, cidx);
1315 let mut d = LinkedListNode::new(ll.nodes[b].vertices_index, ll.nodes[b].coord, didx);
1316
1317 let an = ll.nodes[a].next_linked_list_node_index;
1318 let bp = ll.nodes[b].prev_linked_list_node_index;
1319
1320 ll.nodes[a].next_linked_list_node_index = b;
1321 ll.nodes[b].prev_linked_list_node_index = a;
1322
1323 c.next_linked_list_node_index = an;
1324 ll.nodes[an].prev_linked_list_node_index = cidx;
1325
1326 d.next_linked_list_node_index = cidx;
1327 c.prev_linked_list_node_index = didx;
1328
1329 ll.nodes[bp].next_linked_list_node_index = didx;
1330 d.prev_linked_list_node_index = bp;
1331
1332 ll.nodes.push(c);
1333 ll.nodes.push(d);
1334 didx
1335}