1use crate::advancing_front::{AdvancingFront, NodeId, NodeRef};
2use crate::points::{Points, PointsBuilder};
3use crate::triangles::TriangleId;
4use crate::triangles::TriangleStore;
5use crate::utils::{in_circle, in_scan_area, orient_2d, Angle, Orientation};
6use crate::{shape::*, Context, PointId, Triangle};
7
8#[allow(unused_variables)]
11pub trait Observer {
12 fn enter_point_event(&mut self, point_id: PointId, context: &Context) {}
14 fn exit_point_event(&mut self, point_id: PointId, context: &Context) {}
15
16 fn edge_event(&mut self, edge: Edge, context: &Context) {}
18
19 fn sweep_done(&mut self, context: &Context) {}
21
22 fn finalized(&mut self, context: &Context) {}
24
25 #[inline]
27 fn will_legalize(&mut self, triangle_id: TriangleId, context: &Context) {}
28
29 #[inline]
31 fn legalize_step(&mut self, triangle_id: TriangleId, context: &Context) {}
32
33 #[inline]
35 fn triangle_rotated(
36 &mut self,
37 triangle_id: TriangleId,
38 opposite_triangle_id: TriangleId,
39 context: &Context,
40 ) {
41 }
42
43 #[inline]
45 fn legalized(&mut self, triangel_id: TriangleId, context: &Context) {}
46}
47
48impl Observer for () {}
50
51#[derive(Clone)]
74pub struct SweeperBuilder {
75 points_builder: PointsBuilder,
76}
77
78impl SweeperBuilder {
79 pub fn new(polyline: Vec<Point>) -> Self {
82 let mut points_builder = PointsBuilder::with_capacity(polyline.len());
83 parse_polyline(polyline, &mut points_builder);
84
85 Self { points_builder }
86 }
87
88 pub fn add_steiner_point(mut self, point: Point) -> Self {
92 self.points_builder.add_steiner_point(point);
93 self
94 }
95
96 pub fn add_steiner_points(mut self, points: impl IntoIterator<Item = Point>) -> Self {
98 let _ = self.points_builder.add_steiner_points(points);
99 self
100 }
101
102 pub fn add_hole(mut self, polyline: Vec<Point>) -> Self {
104 parse_polyline(polyline, &mut self.points_builder);
105 self
106 }
107
108 pub fn add_holes(mut self, holes: impl IntoIterator<Item = Vec<Point>>) -> Self {
110 for polyline in holes.into_iter() {
111 self = self.add_hole(polyline);
112 }
113 self
114 }
115
116 pub fn build(self) -> Sweeper {
118 let points = self.points_builder.build();
119 Sweeper { points }
120 }
121}
122
123#[derive(Clone)]
125pub struct Sweeper {
126 points: Points,
127}
128
129pub struct Triangles {
131 points: Points,
133 triangles: TriangleStore,
135 result: Vec<TriangleId>,
137
138 next: usize,
140}
141
142impl Iterator for Triangles {
143 type Item = Triangle;
144
145 fn next(&mut self) -> Option<Self::Item> {
146 if self.next < self.result.len() {
147 let index = self.next;
148 self.next += 1;
149
150 let tri_id = unsafe { self.result.get_unchecked(index) };
152 let triangle = tri_id.get(&self.triangles);
153
154 return Some(Triangle {
155 points: [
156 triangle.points[0].get(&self.points),
157 triangle.points[1].get(&self.points),
158 triangle.points[2].get(&self.points),
159 ],
160 });
161 } else {
162 None
163 }
164 }
165}
166
167impl Sweeper {
168 pub fn triangulate(self) -> Triangles {
170 self.triangulate_with_observer(&mut ())
171 }
172
173 pub fn triangulate_with_observer(self, observer: &mut impl Observer) -> Triangles {
175 let mut triangles = TriangleStore::with_capacity(self.points.len() * 3);
176
177 let initial_triangle = triangles.insert(InnerTriangle::new(
178 self.points.get_id_by_y(0).unwrap(),
179 self.points.head,
180 self.points.tail,
181 ));
182
183 let mut advancing_front = AdvancingFront::new(
185 triangles.get(initial_triangle).unwrap(),
186 initial_triangle,
187 &self.points,
188 );
189
190 let mut context = Context::new(&self.points, &mut triangles, &mut advancing_front);
191
192 Self::sweep_points(&mut context, observer);
193 observer.sweep_done(&context);
194
195 Self::finalize_polygon(&mut context);
196 observer.finalized(&context);
197
198 let result = context.result;
200
201 Triangles {
202 points: self.points,
203 triangles,
204 result,
205
206 next: 0,
207 }
208 }
209}
210
211impl Sweeper {
212 fn sweep_points(context: &mut Context, observer: &mut impl Observer) {
213 for (point_id, point, edges) in context.points.iter_point_by_y(1) {
214 observer.enter_point_event(point_id, context);
215 Self::point_event(point_id, point, context, observer);
216 observer.exit_point_event(point_id, context);
217
218 for p in edges {
219 let edge = Edge { p, q: point_id };
220 Self::edge_event(edge, point, context, observer);
221
222 observer.edge_event(edge, context);
223 }
224
225 debug_assert!(Self::verify_triangles(context));
226 }
227 }
228
229 fn finalize_polygon(context: &mut Context) -> Option<()> {
230 let node = context.advancing_front.nth(1)?;
233
234 let mut t = node.triangle?;
235
236 loop {
237 if let Some(tri) = context.triangles.get(t) {
238 if !tri.constrained_edge_cw(node.point_id()) {
239 t = tri.neighbor_ccw(node.point_id());
240 } else {
241 break;
242 }
243 } else {
244 break;
246 }
247 }
248
249 if !t.invalid() {
250 Self::clean_mesh(t, context);
251 }
252
253 Some(())
254 }
255
256 fn clean_mesh(triangle_id: TriangleId, context: &mut Context) -> Option<()> {
257 let mut triangles = Vec::<(TriangleId, TriangleId)>::with_capacity(context.points.len());
259 triangles.push((triangle_id, TriangleId::INVALID));
260
261 while let Some((t, from)) = triangles.pop() {
262 if t.invalid() {
263 continue;
264 }
265
266 let tri = context.triangles.get_mut(t).unwrap();
267
268 if !tri.interior {
269 tri.interior = true;
270 context.result.push(t);
271
272 for i in 0..3 {
273 if !tri.is_constrained(i) {
274 let new_t = tri.neighbors[i];
275 if new_t != from {
276 triangles.push((new_t, t));
277 }
278 }
279 }
280 }
281 }
282
283 Some(())
284 }
285}
286
287impl Sweeper {
292 fn point_event(
293 point_id: PointId,
294 point: Point,
295 context: &mut Context,
296 observer: &mut impl Observer,
297 ) {
298 let node = context.advancing_front.locate_node(point).unwrap();
299 let node_id = node.get_node_id();
300 let next_node = node.next().unwrap();
301 let node_point = node.point();
302
303 let triangle = context.triangles.insert(InnerTriangle::new(
304 point_id,
305 node.point_id(),
306 next_node.point_id(),
307 ));
308 let node_triangle = node.triangle.unwrap();
309 context.triangles.mark_neighbor(node_triangle, triangle);
310 context.advancing_front.insert(point_id, point, triangle);
311
312 Self::legalize(triangle, context, observer);
313
314 if point.x <= node_point.x + f64::EPSILON {
317 Self::fill_one(node_id, context, observer);
318 }
319
320 Self::fill_advancing_front(point, context, observer);
321 }
322
323 fn is_legalize(triangle_id: TriangleId, context: &Context) -> [TriangleId; 3] {
325 let mut result = [TriangleId::INVALID; 3];
326 for point_idx in 0..3 {
327 let triangle = context.triangles.get_unchecked(triangle_id);
328 let opposite_triangle_id = triangle.neighbors[point_idx];
329 let Some(opposite_triangle) = context.triangles.get(opposite_triangle_id) else {
330 continue;
331 };
332
333 let p = triangle.points[point_idx];
334 let op = opposite_triangle.opposite_point(&triangle, p);
335 let oi = opposite_triangle.point_index(op).unwrap();
336
337 if opposite_triangle.is_constrained(oi) {
338 continue;
339 }
340
341 let inside = unsafe {
342 in_circle(
343 context.points.get_point_uncheck(p),
344 context.points.get_point_uncheck(triangle.point_ccw(p)),
345 context.points.get_point_uncheck(triangle.point_cw(p)),
346 context.points.get_point_uncheck(op),
347 )
348 };
349
350 if inside {
351 result[point_idx] = opposite_triangle_id;
352 }
353 }
354
355 result
356 }
357
358 fn legalize(triangle_id: TriangleId, context: &mut Context, observer: &mut impl Observer) {
360 observer.will_legalize(triangle_id, context);
361
362 let mut legalized_triangles = std::mem::take(&mut context.legalize_remap_tids);
365
366 let mut task_queue = std::mem::take(&mut context.legalize_task_queue);
368 task_queue.push(triangle_id);
369 legalized_triangles.push(triangle_id);
370
371 while let Some(triangle_id) = task_queue.pop() {
372 for point_idx in 0..3 {
373 let triangle = triangle_id.get(&context.triangles);
374 if triangle.is_constrained(point_idx) || triangle.is_delaunay(point_idx) {
376 continue;
377 }
378
379 let opposite_triangle_id = triangle.neighbors[point_idx];
380 if opposite_triangle_id.invalid() {
381 continue;
382 };
383 let opposite_triangle = opposite_triangle_id.get(&context.triangles);
384
385 let p = triangle.points[point_idx];
386 let op = opposite_triangle.opposite_point(&triangle, p);
387
388 let illegal = in_circle(
389 p.get(&context.points),
390 triangle.point_ccw(p).get(&context.points),
391 triangle.point_cw(p).get(&context.points),
392 op.get(&context.points),
393 );
394 if illegal {
395 observer.triangle_rotated(triangle_id, opposite_triangle_id, context);
396 let need_remap = Self::rotate_triangle_pair(
398 triangle_id,
399 p,
400 opposite_triangle_id,
401 op,
402 context.triangles,
403 );
404
405 {
407 let (t, ot) = unsafe {
408 context
409 .triangles
410 .get_mut_two(triangle_id, opposite_triangle_id)
411 };
412
413 let (t_idx, ot_idx) = t.common_edge_index(ot).unwrap();
414 t.set_delaunay(t_idx, true);
415 ot.set_delaunay(ot_idx, true);
416 }
417
418 task_queue.push(triangle_id);
419 task_queue.push(opposite_triangle_id);
420
421 if need_remap {
422 legalized_triangles.push(triangle_id);
423 legalized_triangles.push(opposite_triangle_id);
424 }
425 break;
426 } else {
427 }
430 }
431
432 observer.legalize_step(triangle_id, context);
433 }
434
435 for triangle_id in legalized_triangles.drain(..) {
436 Self::map_triangle_to_nodes(triangle_id, context);
437 }
438
439 {
440 context.legalize_task_queue = task_queue;
442 context.legalize_remap_tids = legalized_triangles;
443 }
444
445 observer.legalized(triangle_id, context);
446 }
447
448 fn rotate_triangle_pair(
450 t_id: TriangleId,
451 p: PointId,
452 ot_id: TriangleId,
453 op: PointId,
454 triangles: &mut TriangleStore,
455 ) -> bool {
456 let (t, ot) = unsafe { triangles.get_mut_two(t_id, ot_id) };
457
458 let n1 = t.neighbor_ccw(p);
459 let n2 = t.neighbor_cw(p);
460 let n3 = ot.neighbor_ccw(op);
461 let n4 = ot.neighbor_cw(op);
462
463 let ea1 = t.edge_attr_ccw(p);
464 let ea2 = t.edge_attr_cw(p);
465 let ea3 = ot.edge_attr_ccw(op);
466 let ea4 = ot.edge_attr_cw(op);
467
468 t.rotate_cw(p, op);
470 ot.rotate_cw(op, p);
471
472 t.set_edge_attr_cw(p, ea2);
473 t.set_edge_attr_ccw(op, ea3);
474 ot.set_edge_attr_ccw(p, ea1);
475 ot.set_edge_attr_cw(op, ea4);
476
477 t.clear_neighbors();
478 ot.clear_neighbors();
479
480 TriangleStore::mark_neighbor_for_two_mut(t_id, ot_id, t, ot);
481
482 let (t, ot, t_n1, t_n2, t_n3, t_n4) =
483 unsafe { triangles.get_mut_six(t_id, ot_id, n1, n2, n3, n4) };
484
485 if let Some(t_n2) = t_n2 {
486 TriangleStore::mark_neighbor_for_two_mut(t_id, n2, t, t_n2);
487 }
488 if let Some(t_n3) = t_n3 {
489 TriangleStore::mark_neighbor_for_two_mut(t_id, n3, t, t_n3);
490 }
491 if let Some(t_n1) = t_n1 {
492 TriangleStore::mark_neighbor_for_two_mut(ot_id, n1, ot, t_n1);
493 }
494 if let Some(t_n4) = t_n4 {
495 TriangleStore::mark_neighbor_for_two_mut(ot_id, n4, ot, t_n4);
496 }
497
498 n1.invalid() || n2.invalid() || n3.invalid() || n4.invalid()
499 }
500
501 fn map_triangle_to_nodes(triangle_id: TriangleId, context: &mut Context) {
503 let triangle = triangle_id.get(&context.triangles);
504 for i in 0..3 {
505 if triangle.neighbors[i].invalid() {
506 let point = unsafe {
507 context
508 .points
509 .get_point_uncheck(triangle.point_cw(triangle.points[i]))
510 };
511 context.advancing_front.update_triangle(point, triangle_id);
512 }
513 }
514 }
515
516 fn fill_one(
522 node: NodeId,
523 context: &mut Context,
524 observer: &mut impl Observer,
525 ) -> Option<FillOne> {
526 let node = context.advancing_front.get_node_with_id(node).unwrap();
527 let prev_node = node.prev()?;
528 let next_node = node.next()?;
529
530 let fill_one_result = FillOne {
535 prev: prev_node.get_node_id(),
536 next: next_node.get_node_id(),
537 };
538
539 let new_triangle = context.triangles.insert(InnerTriangle::new(
540 prev_node.point_id(),
541 node.point_id(),
542 next_node.point_id(),
543 ));
544
545 context
546 .triangles
547 .mark_neighbor(new_triangle, prev_node.triangle.unwrap());
548 context
549 .triangles
550 .mark_neighbor(new_triangle, node.triangle.unwrap());
551
552 unsafe {
557 context.advancing_front.update_and_delete_by_index(
558 prev_node.index(),
559 prev_node.point_id(),
560 new_triangle,
561 node.index(),
562 )
563 };
564
565 Self::legalize(new_triangle, context, observer);
568
569 Some(fill_one_result)
570 }
571
572 fn fill_advancing_front(
573 node_point: Point,
574 context: &mut Context,
575 observer: &mut impl Observer,
576 ) {
577 let node_id = context
578 .advancing_front
579 .get_node(node_point)
580 .unwrap()
581 .get_node_id();
582
583 {
584 let mut node_id = node_id.clone();
586 while let Some(next_node) = context.advancing_front.locate_next_node(node_id) {
587 if next_node.next().is_some() {
588 if Self::should_fill(&next_node) {
590 break;
591 }
592 let next_node_id = next_node.get_node_id();
593
594 node_id = match Self::fill_one(next_node_id, context, observer) {
595 Some(fill_one) => fill_one.next,
596 None => next_node_id,
597 };
598 } else {
599 break;
600 }
601 }
602 }
603
604 {
605 let mut node_id = node_id.clone();
607
608 while let Some(prev_node) = context.advancing_front.locate_prev_node(node_id) {
609 if prev_node.prev().is_some() {
610 if Self::should_fill(&prev_node) {
612 break;
613 }
614
615 node_id = prev_node.get_node_id();
616 Self::fill_one(node_id, context, observer);
617 } else {
618 break;
619 }
620 }
621 }
622
623 if Self::basin_angle_satisfy(node_id, context) {
625 Self::fill_basin(node_id, context, observer);
626 }
627 }
628
629 fn should_fill(node: &NodeRef) -> bool {
630 let next = node.next().unwrap();
631 let prev_node = node.prev().unwrap();
632
633 let angle = crate::utils::Angle::new(node.point(), next.point(), prev_node.point());
634
635 if angle.is_negative() {
636 return true;
638 } else if !angle.exceeds_90_degree() {
639 return false;
643 }
644
645 if let Some(next_next) = next.next() {
646 if Angle::new(node.point(), next_next.point(), prev_node.point())
647 .between_0_to_90_degree()
648 {
649 return false;
650 }
651 }
652
653 if let Some(prev_prev) = prev_node.prev() {
654 if Angle::new(node.point(), next.point(), prev_prev.point()).between_0_to_90_degree() {
655 return false;
656 }
657 }
658
659 true
660 }
661}
662
663struct FillOne {
664 prev: NodeId,
665 next: NodeId,
666}
667
668#[derive(Debug)]
669struct ConstrainedEdge {
670 constrained_edge: Edge,
671 p: Point,
672 q: Point,
673 right: bool,
675}
676
677impl ConstrainedEdge {
678 fn p_id(&self) -> PointId {
679 self.constrained_edge.p
680 }
681
682 fn q_id(&self) -> PointId {
683 self.constrained_edge.q
684 }
685
686 fn with_q(&self, q: PointId, context: &Context) -> Self {
687 let q_point = q.get(&context.points);
688 Self {
689 constrained_edge: Edge {
690 p: self.constrained_edge.p,
691 q,
692 },
693 p: self.p,
694 q: q_point,
695 right: self.p.x > q_point.x,
696 }
697 }
698}
699
700impl Sweeper {
702 fn edge_event(edge: Edge, q: Point, context: &mut Context, observer: &mut impl Observer) {
703 let p = edge.p.get(&context.points);
704
705 let constrain_edge = ConstrainedEdge {
706 constrained_edge: edge,
707 p,
708 q,
709 right: p.x > q.x,
710 };
711
712 {
713 let node = context.advancing_front.get_node_with_cache(q).unwrap();
715
716 let triangle_id = node.triangle.unwrap();
717 let node_id = node.get_node_id();
718 if Self::try_mark_edge_for_triangle(edge.p, edge.q, triangle_id, context) {
719 return;
721 }
722
723 Self::fill_edge_event(&constrain_edge, node_id, context, observer);
725 }
726
727 let triangle = context
729 .advancing_front
730 .get_node_with_cache(q)
731 .unwrap()
732 .triangle
733 .unwrap();
734
735 let mut triangle_ids = std::mem::take(&mut context.triangle_id_queue);
737 Self::edge_event_process(
738 edge.p,
739 edge.q,
740 &constrain_edge,
741 triangle,
742 edge.q,
743 &mut triangle_ids,
744 context,
745 );
746
747 for triangle_id in triangle_ids.drain(..) {
748 Self::legalize(triangle_id, context, observer);
749 }
750 context.triangle_id_queue = triangle_ids;
751 }
752
753 fn try_mark_edge_for_triangle(
756 p: PointId,
757 q: PointId,
758 t_id: TriangleId,
759 context: &mut Context,
760 ) -> bool {
761 let triangle = context.triangles.get_mut_unchecked(t_id);
762 let Some(index) = triangle.edge_index(p, q) else { return false; };
763
764 triangle.set_constrained(index, true);
765 let neighbor_t_id = triangle.neighbors[index];
766 if !neighbor_t_id.invalid() {
767 let ot = context.triangles.get_mut_unchecked(neighbor_t_id);
768 let index = ot.neighbor_index(t_id);
769 ot.set_constrained(index, true);
770 }
771
772 true
773 }
774
775 fn fill_edge_event(
776 edge: &ConstrainedEdge,
777 node_id: NodeId,
778 context: &mut Context,
779 observer: &mut impl Observer,
780 ) {
781 if edge.right {
782 Self::fill_right_above_edge_event(edge, node_id, context, observer);
783 } else {
784 Self::fill_left_above_edge_event(edge, node_id, context, observer);
785 }
786 }
787
788 fn fill_right_above_edge_event(
789 edge: &ConstrainedEdge,
790 node_id: NodeId,
791 context: &mut Context,
792 observer: &mut impl Observer,
793 ) {
794 let mut node_id = node_id.clone();
795 while let Some(next_node) = context.advancing_front.locate_next_node(node_id) {
796 if next_node.point().x >= edge.p.x {
797 break;
798 }
799
800 if orient_2d(edge.q, next_node.point(), edge.p).is_ccw() {
802 Self::fill_right_below_edge_event(edge, node_id, context, observer);
803 } else {
804 node_id = next_node.get_node_id();
806 }
807 }
808 }
809
810 fn fill_right_below_edge_event(
811 edge: &ConstrainedEdge,
812 node_id: NodeId,
813 context: &mut Context,
814 observer: &mut impl Observer,
815 ) -> Option<()> {
816 if node_id.point().x >= edge.p.x {
817 return None;
818 }
819
820 let node = context.advancing_front.get_node_with_id(node_id).unwrap();
821
822 let next_node = node.next().unwrap();
823 let next_next_node = next_node.next().unwrap();
824
825 if orient_2d(node.point(), next_node.point(), next_next_node.point()).is_ccw() {
826 Self::fill_right_concave_edge_event(edge, node_id, context, observer);
828 } else {
829 Self::fill_right_convex_edge_event(edge, node_id, context, observer)?;
831
832 Self::fill_right_below_edge_event(edge, node_id, context, observer);
834 }
835
836 Some(())
837 }
838
839 fn fill_right_concave_edge_event(
841 edge: &ConstrainedEdge,
842 node_id: NodeId,
843 context: &mut Context,
844 observer: &mut impl Observer,
845 ) {
846 let next_id = {
847 let next_node = context.advancing_front.locate_next_node(node_id).unwrap();
848 let next_id = next_node.get_node_id();
849 match Self::fill_one(next_id, context, observer) {
850 None => {
851 next_id
853 }
854 Some(fill_one) => fill_one.next,
855 }
856 };
857
858 if next_id.point_id() != edge.p_id() {
859 if orient_2d(edge.q, next_id.point(), edge.p).is_ccw() {
861 let next_next_node = context.advancing_front.locate_next_node(next_id).unwrap();
862
863 if orient_2d(node_id.point(), next_id.point(), next_next_node.point()).is_ccw() {
865 Self::fill_right_concave_edge_event(edge, node_id, context, observer);
867 } else {
868 }
870 }
871 }
872 }
873
874 #[must_use]
876 fn fill_right_convex_edge_event(
877 edge: &ConstrainedEdge,
878 node_id: NodeId,
879 context: &mut Context,
880 observer: &mut impl Observer,
881 ) -> Option<()> {
882 let next_node = context.advancing_front.locate_next_node(node_id).unwrap();
883 let next_next_node = next_node.next().unwrap();
884 let next_next_next_node = next_next_node.next()?;
885 if orient_2d(
887 next_node.point(),
888 next_next_node.point(),
889 next_next_next_node.point(),
890 )
891 .is_ccw()
892 {
893 Self::fill_right_concave_edge_event(edge, node_id, context, observer);
895 } else {
896 if orient_2d(edge.q, next_next_node.point(), edge.p).is_ccw() {
899 Self::fill_right_convex_edge_event(
901 edge,
902 next_node.get_node_id(),
903 context,
904 observer,
905 )?;
906 } else {
907 }
909 }
910
911 Some(())
912 }
913
914 fn fill_left_above_edge_event(
915 edge: &ConstrainedEdge,
916 node_id: NodeId,
917 context: &mut Context,
918 observer: &mut impl Observer,
919 ) {
920 let mut node_id = node_id.clone();
921 while let Some(prev_node) = context.advancing_front.locate_prev_node(node_id) {
922 if prev_node.point().x <= edge.p.x {
924 break;
925 }
926
927 if orient_2d(edge.q, prev_node.point(), edge.p).is_cw() {
928 Self::fill_left_below_edge_event(edge, node_id, context, observer);
929 } else {
930 node_id = prev_node.get_node_id();
931 }
932 }
933 }
934
935 fn fill_left_below_edge_event(
936 edge: &ConstrainedEdge,
937 node_id: NodeId,
938 context: &mut Context,
939 observer: &mut impl Observer,
940 ) -> Option<()> {
941 if node_id.point().x > edge.p.x {
942 let prev_node = context.advancing_front.locate_prev_node(node_id).unwrap();
943 let prev_prev_node = prev_node.prev().unwrap();
944 if orient_2d(node_id.point(), prev_node.point(), prev_prev_node.point()).is_cw() {
945 Self::fill_left_concave_edge_event(edge, node_id, context, observer);
946 } else {
947 Self::fill_left_convex_edge_event(edge, node_id, context, observer)?;
949
950 Self::fill_left_below_edge_event(edge, node_id, context, observer);
952 }
953 Some(())
954 } else {
955 None
956 }
957 }
958
959 #[must_use]
961 fn fill_left_convex_edge_event(
962 edge: &ConstrainedEdge,
963 node_id: NodeId,
964 context: &mut Context,
965 observer: &mut impl Observer,
966 ) -> Option<()> {
967 let prev_node = context.advancing_front.locate_prev_node(node_id).unwrap();
969 let prev_prev_node = prev_node.prev().unwrap();
970 let prev_prev_prev_node = prev_prev_node.prev()?;
971
972 if orient_2d(
973 prev_node.point(),
974 prev_prev_node.point(),
975 prev_prev_prev_node.point(),
976 )
977 .is_cw()
978 {
979 Self::fill_left_concave_edge_event(edge, prev_node.get_node_id(), context, observer);
981 } else {
982 if orient_2d(edge.q, prev_prev_node.point(), edge.p).is_cw() {
985 Self::fill_left_convex_edge_event(
987 edge,
988 prev_node.get_node_id(),
989 context,
990 observer,
991 )?;
992 } else {
993 }
995 }
996 Some(())
997 }
998
999 fn fill_left_concave_edge_event(
1000 edge: &ConstrainedEdge,
1001 node_id: NodeId,
1002 context: &mut Context,
1003 observer: &mut impl Observer,
1004 ) {
1005 let prev_node = context.advancing_front.locate_prev_node(node_id).unwrap();
1006
1007 let prev_node_id = prev_node.get_node_id();
1008
1009 let prev_node_id = match Self::fill_one(prev_node_id, context, observer) {
1010 Some(fill_one) => fill_one.prev,
1011 None => prev_node_id,
1012 };
1013
1014 if prev_node_id.point_id() != edge.p_id() {
1015 if orient_2d(edge.q, prev_node_id.point(), edge.p).is_cw() {
1017 let prev_node = context
1018 .advancing_front
1019 .get_node_with_id(prev_node_id)
1020 .unwrap();
1021 let prev_prev_node = prev_node.prev().unwrap();
1023 if orient_2d(node_id.point(), prev_node.point(), prev_prev_node.point()).is_cw() {
1024 Self::fill_left_concave_edge_event(edge, node_id, context, observer);
1026 } else {
1027 }
1029 }
1030 }
1031 }
1032
1033 fn edge_event_process(
1034 ep: PointId,
1035 eq: PointId,
1036 constrain_edge: &ConstrainedEdge,
1037 triangle_id: TriangleId,
1038 p: PointId,
1039 triangle_ids: &mut Vec<TriangleId>,
1040 context: &mut Context,
1041 ) {
1042 assert!(!triangle_id.invalid());
1043
1044 if Self::try_mark_edge_for_triangle(ep, eq, triangle_id, context) {
1045 return;
1046 }
1047
1048 let triangle = context.triangles.get_mut_unchecked(triangle_id);
1049 let p1 = triangle.point_ccw(p);
1050 let o1 = orient_2d(
1051 eq.get(&context.points),
1052 p1.get(&context.points),
1053 ep.get(&context.points),
1054 );
1055
1056 if o1.is_collinear() {
1057 if let Some(edge_index) = triangle.edge_index(eq, p1) {
1058 triangle.set_constrained(edge_index, true);
1059
1060 let neighbor_across_t = triangle.neighbor_across(p);
1061 Self::edge_event_process(
1062 ep,
1063 p1,
1064 &constrain_edge.with_q(p1, context),
1065 neighbor_across_t,
1066 p1,
1067 triangle_ids,
1068 context,
1069 );
1070 return;
1071 } else {
1072 panic!("EdgeEvent - collinear points not supported")
1073 }
1074 }
1075
1076 let p2 = triangle.point_cw(p);
1077 let o2 = orient_2d(
1078 eq.get(&context.points),
1079 p2.get(&context.points),
1080 ep.get(&context.points),
1081 );
1082 if o2.is_collinear() {
1083 if let Some(edge_index) = triangle.edge_index(eq, p2) {
1084 triangle.set_constrained(edge_index, true);
1085
1086 let neighbor_across_t = triangle.neighbor_across(p);
1087 Self::edge_event_process(
1088 ep,
1089 p2,
1090 &constrain_edge.with_q(p2, context),
1091 neighbor_across_t,
1092 p2,
1093 triangle_ids,
1094 context,
1095 );
1096
1097 return;
1098 } else {
1099 panic!("collinear points not supported");
1100 }
1101 }
1102
1103 if o1 == o2 {
1104 let triangle_id = if o1.is_cw() {
1107 triangle.neighbor_ccw(p)
1108 } else {
1109 triangle.neighbor_cw(p)
1110 };
1111
1112 Self::edge_event_process(
1113 ep,
1114 eq,
1115 constrain_edge,
1116 triangle_id,
1117 p,
1118 triangle_ids,
1119 context,
1120 );
1121 } else {
1122 Self::flip_edge_event(
1123 ep,
1124 eq,
1125 constrain_edge,
1126 triangle_id,
1127 p,
1128 triangle_ids,
1129 context,
1130 );
1131 }
1132 }
1133}
1134
1135impl Sweeper {
1137 fn flip_edge_event(
1138 ep: PointId,
1139 eq: PointId,
1140 edge: &ConstrainedEdge,
1141 triangle_id: TriangleId,
1142 p: PointId,
1143 legalize_queue: &mut Vec<TriangleId>,
1144 context: &mut Context,
1145 ) {
1146 let t = triangle_id.get(&context.triangles);
1147 let ot_id = t.neighbor_across(p);
1148 let ot = ot_id.get(&context.triangles);
1149 let op = ot.opposite_point(t, p);
1150
1151 if in_scan_area(
1152 p.get(&context.points),
1153 t.point_ccw(p).get(&context.points),
1154 t.point_cw(p).get(&context.points),
1155 op.get(&context.points),
1156 ) {
1157 if Self::rotate_triangle_pair(triangle_id, p, ot_id, op, &mut context.triangles) {
1159 Self::map_triangle_to_nodes(triangle_id, context);
1160 Self::map_triangle_to_nodes(ot_id, context);
1161 }
1162 legalize_queue.extend([triangle_id, ot_id]);
1164
1165 if p == eq && op == ep {
1166 if eq == edge.q_id() && ep == edge.p_id() {
1167 context
1168 .triangles
1169 .get_mut_unchecked(triangle_id)
1170 .set_constrained_for_edge(ep, eq);
1171
1172 context
1173 .triangles
1174 .get_mut_unchecked(ot_id)
1175 .set_constrained_for_edge(ep, eq);
1176 }
1177 } else {
1178 let o = orient_2d(
1179 eq.get(&context.points),
1180 op.get(&context.points),
1181 ep.get(&context.points),
1182 );
1183
1184 let t = Self::next_flip_triangle(o, triangle_id, ot_id, legalize_queue);
1185 Self::flip_edge_event(ep, eq, edge, t, p, legalize_queue, context);
1186 }
1187 } else {
1188 let new_p = Self::next_flip_point(ep, eq, ot_id, op, context);
1189 Self::flip_scan_edge_event(
1190 ep,
1191 eq,
1192 edge,
1193 triangle_id,
1194 ot_id,
1195 new_p,
1196 legalize_queue,
1197 context,
1198 );
1199 Self::edge_event_process(ep, eq, edge, triangle_id, p, legalize_queue, context);
1200 }
1201 }
1202
1203 fn next_flip_triangle(
1204 o: Orientation,
1205 t: TriangleId,
1206 ot: TriangleId,
1207 triangle_ids: &mut Vec<TriangleId>,
1208 ) -> TriangleId {
1209 if o.is_ccw() {
1210 triangle_ids.push(ot);
1212 t
1213 } else {
1214 triangle_ids.push(t);
1216 ot
1217 }
1218 }
1219
1220 fn next_flip_point(
1221 ep: PointId,
1222 eq: PointId,
1223 ot: TriangleId,
1224 op: PointId,
1225 context: &mut Context,
1226 ) -> PointId {
1227 let o2d = orient_2d(
1228 eq.get(&context.points),
1229 op.get(&context.points),
1230 ep.get(&context.points),
1231 );
1232
1233 let ot = context.triangles.get_unchecked(ot);
1234 match o2d {
1235 Orientation::CW => {
1236 ot.point_ccw(op)
1238 }
1239 Orientation::CCW => {
1240 ot.point_cw(op)
1242 }
1243 Orientation::Collinear => {
1244 panic!("Opposing point on constrained edge");
1245 }
1246 }
1247 }
1248
1249 fn flip_scan_edge_event(
1250 ep: PointId,
1251 eq: PointId,
1252 edge: &ConstrainedEdge,
1253 flip_triangle_id: TriangleId,
1254 t_id: TriangleId,
1255 p: PointId,
1256 triangle_ids: &mut Vec<TriangleId>,
1257 context: &mut Context,
1258 ) {
1259 let t = t_id.get(&context.triangles);
1260 let ot = t.neighbor_across(p);
1261 if ot.invalid() {
1262 panic!("flip_scan_edge_event - null neighbor across");
1263 }
1264
1265 let op = ot.get(&context.triangles).opposite_point(t, p);
1266 let flip_triangle = flip_triangle_id.get(&context.triangles);
1267 let p1 = flip_triangle.point_ccw(eq);
1268 let p2 = flip_triangle.point_cw(eq);
1269
1270 if in_scan_area(
1271 eq.get(&context.points),
1272 p1.get(&context.points),
1273 p2.get(&context.points),
1274 op.get(&context.points),
1275 ) {
1276 Self::flip_edge_event(eq, op, edge, ot, op, triangle_ids, context);
1278
1279 } else {
1288 let new_p = Self::next_flip_point(ep, eq, ot, op, context);
1289 Self::flip_scan_edge_event(
1290 ep,
1291 eq,
1292 edge,
1293 flip_triangle_id,
1294 ot,
1295 new_p,
1296 triangle_ids,
1297 context,
1298 );
1299 }
1300 }
1301}
1302
1303#[derive(Debug)]
1304struct Basin {
1305 left: Point,
1306 right: Point,
1307 width: f64,
1308 left_higher: bool,
1309}
1310
1311impl Basin {
1312 pub fn is_shallow(&self, point: Point) -> bool {
1313 let height = if self.left_higher {
1314 self.left.y - point.y
1315 } else {
1316 self.right.y - point.y
1317 };
1318
1319 self.width > height
1320 }
1321
1322 pub fn completed(&self, point: Point) -> bool {
1323 if point.x >= self.right.x || point.x <= self.left.x {
1324 return true;
1325 }
1326
1327 self.is_shallow(point)
1328 }
1329}
1330
1331impl Sweeper {
1333 fn basin_angle_satisfy(node_id: NodeId, context: &Context) -> bool {
1334 const TAN_3_4_PI: f64 = -1.;
1335 let Some(next) = context.advancing_front.locate_next_node(node_id) else { return false };
1336 let Some(next_next) = next.next() else { return false };
1337
1338 let ax = node_id.point().x - next_next.point().x;
1339 let ay = node_id.point().y - next_next.point().y;
1340 if ax > 0. {
1344 ay < TAN_3_4_PI * ax
1345 } else {
1346 ay > TAN_3_4_PI * ax
1347 }
1348 }
1349
1350 fn fill_basin(
1353 node_point: NodeId,
1354 context: &mut Context,
1355 observer: &mut impl Observer,
1356 ) -> Option<()> {
1357 let next_node = context.advancing_front.locate_next_node(node_point)?;
1358 let next_next_node = next_node.next()?;
1359
1360 let left: NodeRef<'_>;
1362 if orient_2d(
1363 node_point.point(),
1364 next_node.point(),
1365 next_next_node.point(),
1366 )
1367 .is_ccw()
1368 {
1369 left = next_next_node;
1370 } else {
1371 left = next_node;
1372 }
1373
1374 let mut bottom = left.clone();
1376 while let Some(next_node) = bottom.next() {
1377 if bottom.point().y >= next_node.point().y {
1378 bottom = next_node;
1379 } else {
1380 break;
1381 }
1382 }
1383
1384 if bottom.point_id().eq(&left.point_id()) {
1386 return None;
1387 }
1388
1389 let mut right: NodeRef = bottom.clone();
1391 while let Some(next_node) = right.next() {
1392 if right.point().y < next_node.point().y {
1393 right = next_node;
1394 } else {
1395 break;
1396 }
1397 }
1398 if right.point_id() == bottom.point_id() {
1399 return None;
1401 }
1402
1403 let width = right.point().x - left.point().x;
1404 let left_higher: bool = left.point().y > right.point().y;
1405
1406 Self::fill_basin_req(
1407 bottom.get_node_id(),
1408 &Basin {
1409 left: left.point(),
1410 right: right.point(),
1411 width,
1412 left_higher,
1413 },
1414 context,
1415 observer,
1416 );
1417
1418 Some(())
1419 }
1420
1421 fn fill_basin_req(
1422 node: NodeId,
1423 basin: &Basin,
1424 context: &mut Context,
1425 observer: &mut impl Observer,
1426 ) -> Option<()> {
1427 if basin.completed(node.point()) {
1428 return None;
1429 }
1430
1431 let fill_one = Self::fill_one(node, context, observer).expect("already in basin");
1432 let prev = fill_one.prev;
1433 let next = fill_one.next;
1434
1435 if prev.point().eq(&basin.left) && next.point().eq(&basin.right) {
1436 return Some(());
1437 }
1438
1439 let new_node = if prev.point().eq(&basin.left) {
1440 let next = context.advancing_front.get_node_with_id(next).unwrap();
1441 let next_next = next.next().unwrap();
1442 if orient_2d(node.point(), next.point(), next_next.point()).is_cw() {
1443 return None;
1444 }
1445
1446 next.get_node_id()
1447 } else if next.point().eq(&basin.right) {
1448 let prev = context.advancing_front.get_node_with_id(prev).unwrap();
1449 let prev_prev = prev.prev()?;
1450 if orient_2d(node.point(), prev.point(), prev_prev.point()).is_ccw() {
1451 return None;
1452 }
1453
1454 prev.get_node_id()
1455 } else {
1456 if prev.point().y < next.point().y {
1458 prev
1459 } else {
1460 next
1461 }
1462 };
1463
1464 Self::fill_basin_req(new_node, basin, context, observer)
1465 }
1466}
1467
1468impl Sweeper {
1469 pub fn verify_triangles(context: &Context) -> bool {
1470 Self::illegal_triangles(context).is_empty()
1471 }
1472
1473 #[allow(unused)]
1475 pub fn illegal_triangles(context: &Context) -> Vec<(TriangleId, TriangleId)> {
1476 let triangle_ids = context
1477 .triangles
1478 .iter()
1479 .map(|(t_id, _)| t_id)
1480 .collect::<Vec<_>>();
1481
1482 let mut result = Vec::<(TriangleId, TriangleId)>::new();
1483
1484 for t_id in triangle_ids {
1485 for illegal_neighbor in &Self::is_legalize(t_id, context) {
1486 if !illegal_neighbor.invalid() {
1487 result.push((t_id, *illegal_neighbor));
1488 }
1489 }
1490 }
1491
1492 result
1493 }
1494}
1495
1496fn parse_polyline(polyline: Vec<Point>, points: &mut PointsBuilder) {
1497 let mut point_iter = polyline
1499 .iter()
1500 .map(|p| (points.add_steiner_point(*p), p))
1501 .collect::<Vec<_>>()
1502 .into_iter();
1503
1504 if let Some(first_point) = point_iter.next() {
1505 let mut last_point = first_point;
1506 loop {
1507 match point_iter.next() {
1508 Some(p2) => {
1509 let edge = Edge::new(last_point, p2);
1510 points.get_point_mut(edge.q).unwrap().edges.push(edge.p);
1511 last_point = p2;
1512 }
1513 None => {
1514 let edge = Edge::new(last_point, first_point);
1515 points.get_point_mut(edge.q).unwrap().edges.push(edge.p);
1516 break;
1517 }
1518 }
1519 }
1520 }
1521}
1522
1523#[cfg(test)]
1524mod tests {
1525 use std::io::{Read, Write};
1526
1527 use rand::Rng;
1528
1529 use super::*;
1530
1531 #[derive(Default)]
1532 struct CacheHitOb {
1533 hit_count: u64,
1534 mis_count: u64,
1535 rotate_count: u64,
1536 legalize_step_count: u64,
1537 legalize_count: u64,
1538 }
1539
1540 impl CacheHitOb {
1541 pub fn hit_rate(&self) -> f64 {
1542 self.hit_count as f64 / (self.hit_count + self.mis_count) as f64
1543 }
1544 }
1545
1546 impl Observer for CacheHitOb {
1547 fn legalized(&mut self, _triangel_id: TriangleId, _context: &Context) {
1548 self.legalize_count += 1;
1549 }
1550
1551 fn legalize_step(&mut self, _triangle_id: TriangleId, _context: &Context) {
1552 self.legalize_step_count += 1;
1553 }
1554
1555 fn triangle_rotated(
1556 &mut self,
1557 _triangle_id: TriangleId,
1558 _opposite_triangle_id: TriangleId,
1559 _context: &Context,
1560 ) {
1561 self.rotate_count += 1;
1562 }
1563
1564 fn finalized(&mut self, context: &Context) {
1565 let hit = context
1566 .advancing_front
1567 .hit_count
1568 .load(std::sync::atomic::Ordering::Relaxed);
1569 let miss = context
1570 .advancing_front
1571 .miss_count
1572 .load(std::sync::atomic::Ordering::Relaxed);
1573 println!(
1574 "af cache hit: {}/{} rate: {:.2}%",
1575 hit,
1576 hit + miss,
1577 hit as f64 / (hit + miss) as f64 * 100.
1578 );
1579
1580 println!(
1581 "points: {} triangle: {}",
1582 context.points.len(),
1583 context.triangles.len()
1584 );
1585 println!(
1586 "legalize: {} steps: {} rotate: {}",
1587 self.legalize_count, self.legalize_step_count, self.rotate_count
1588 );
1589 self.hit_count = hit;
1590 self.mis_count = miss;
1591 }
1592 }
1593
1594 #[test]
1595 fn test_bird() {
1596 let file_path = "test_data/bird.dat";
1597 let points = try_load_from_file(file_path).unwrap();
1598
1599 let mut cache_hit = CacheHitOb::default();
1600 let sweeper = SweeperBuilder::new(points).build();
1601 let triangles = sweeper
1602 .triangulate_with_observer(&mut cache_hit)
1603 .collect::<Vec<_>>();
1604 assert_eq!(triangles.len(), 273);
1605 assert!(cache_hit.hit_rate() > 0.63);
1606 assert!(cache_hit.rotate_count == 272);
1607 }
1608
1609 #[test]
1610 fn test_nazca_heron() {
1611 let file_path = "test_data/nazca_heron.dat";
1612 let points = try_load_from_file(file_path).unwrap();
1613
1614 let sweeper = SweeperBuilder::new(points).build();
1615 let mut cache_hit = CacheHitOb::default();
1616 let triangles = sweeper
1617 .triangulate_with_observer(&mut cache_hit)
1618 .collect::<Vec<_>>();
1619 assert_eq!(triangles.len(), 1034);
1620 assert!(cache_hit.hit_rate() > 0.71);
1621 assert!(cache_hit.rotate_count == 671);
1622 }
1623
1624 #[test]
1625 fn test_rand() {
1626 let test_path = "test_data/latest_test_data";
1627 let points = match try_load_from_file(test_path) {
1628 None => {
1629 let mut points = Vec::<Point>::new();
1630 for _ in 0..100 {
1631 let x: f64 = rand::thread_rng().gen_range(0.0..800.);
1632 let y: f64 = rand::thread_rng().gen_range(0.0..800.);
1633 points.push(Point::new(x, y));
1634 }
1635 save_to_file(&points, test_path);
1636 points
1637 }
1638 Some(points) => points,
1639 };
1640
1641 let sweeper = SweeperBuilder::new(vec![
1642 Point::new(-10., -10.),
1643 Point::new(810., -10.),
1644 Point::new(810., 810.),
1645 Point::new(-10., 810.),
1646 ])
1647 .add_steiner_points(points)
1648 .add_hole(vec![
1649 Point::new(400., 400.),
1650 Point::new(600., 400.),
1651 Point::new(600., 600.),
1652 Point::new(400., 600.),
1653 ])
1654 .build();
1655 let _ = sweeper.triangulate();
1656
1657 delete_file(test_path);
1658 }
1659
1660 fn try_load_from_file(path: &str) -> Option<Vec<Point>> {
1661 let mut f = std::fs::File::options().read(true).open(path).ok()?;
1662 let mut value = "".to_string();
1663 f.read_to_string(&mut value).unwrap();
1664 let mut points = vec![];
1665 for line in value.lines() {
1666 let mut iter = line.split_whitespace();
1667 let x = iter.next().unwrap();
1668 let y = iter.next().unwrap();
1669
1670 let x = x.parse::<f64>().unwrap();
1671 let y = y.parse::<f64>().unwrap();
1672 points.push(Point::new(x, y));
1673 }
1674
1675 Some(points)
1676 }
1677
1678 fn save_to_file(points: &[Point], path: &str) {
1679 use std::fmt::Write;
1680
1681 let mut f = std::fs::File::options()
1682 .write(true)
1683 .create_new(true)
1684 .open(path)
1685 .unwrap();
1686
1687 let mut value = "".to_string();
1688 for p in points {
1689 writeln!(value, "{} {}", p.x, p.y).unwrap();
1690 }
1691
1692 f.write_all(value.as_bytes()).unwrap();
1693 }
1694
1695 fn delete_file(path: &str) {
1696 std::fs::remove_file(path).unwrap();
1697 }
1698}