1#![allow(clippy::nonminimal_bool)] use super::{GraphPath, GraphEdge, GraphEdgeRef, GraphPathPoint, GraphPathEdge};
4use crate::bezier::curve::*;
5use crate::bezier::intersection::*;
6use crate::geo::*;
7use crate::consts::*;
8
9use smallvec::*;
10
11use std::mem;
12use std::ops::Range;
13use std::cmp::Ordering;
14
15#[derive(Clone, Copy, Debug)]
19struct Collision {
20 edge_1: GraphEdgeRef,
22
23 edge_2: GraphEdgeRef,
25
26 edge_1_t: f64,
28
29 edge_2_t: f64
31}
32
33impl<Point: Coordinate+Coordinate2D, Label: Copy> GraphPath<Point, Label> {
34 #[inline]
38 fn t_is_zero(t: f64) -> bool { t <= 0.0 }
39
40 #[inline]
44 fn t_is_one(t: f64) -> bool { t >= 1.0 }
45
46 fn get_ordered_edges(&self, points: Range<usize>) -> Vec<GraphEdge<'_, Point, Label>> {
50 let mut ordered_edges = points.into_iter()
51 .flat_map(|point_idx| (0..self.points[point_idx].forward_edges.len()).into_iter().map(move |edge_idx| (point_idx, edge_idx)))
52 .map(|(point_idx, edge_idx)| GraphEdgeRef { start_idx: point_idx, edge_idx: edge_idx, reverse: false })
53 .map(|edge_ref| GraphEdge::new(self, edge_ref))
54 .collect::<Vec<_>>();
55
56 ordered_edges.sort_by(|edge1, edge2| {
57 let bb1 = edge1.get_bounding_box::<Bounds<_>>();
58 let bb2 = edge2.get_bounding_box::<Bounds<_>>();
59
60 bb1.min().x().partial_cmp(&bb2.min().x()).unwrap_or(Ordering::Equal)
61 });
62
63 ordered_edges
64 }
65
66 #[inline]
70 fn snap_points(p1: &Point, p2: &Point) -> Point {
71 Point::from_components(&[(p1.x() + p2.x())/2.0, (p1.y() + p2.y())/2.0])
72 }
73
74 #[inline]
78 fn point_is_near(p1: &Point, p2: &Point, max_distance_squared: f64) -> bool {
79 let offset = *p1 - *p2;
80 let squared_distance = offset.dot(&offset);
81
82 squared_distance <= max_distance_squared
83 }
84
85 fn find_self_collisions(&self, points: Range<usize>, accuracy: f64) -> Vec<Collision> {
89 let ordered_edges = self.get_ordered_edges(points);
91
92 let mut collisions = vec![];
94
95 for (src_curve, tgt_curve) in sweep_self(ordered_edges.iter()) {
96 let mut edge_collisions = curve_intersects_curve_clip(src_curve, tgt_curve, accuracy);
98 if edge_collisions.is_empty() { continue; }
99
100 remove_and_round_close_collisions(&mut edge_collisions, src_curve, tgt_curve);
102
103 let edge_collisions = edge_collisions.into_iter()
106 .filter(|(src_t, tgt_t)| !(Self::t_is_one(*src_t) || Self::t_is_one(*tgt_t) || (Self::t_is_zero(*src_t) && Self::t_is_zero(*tgt_t))))
107 .map(|(src_t, tgt_t)| {
108 Collision {
109 edge_1: src_curve.edge,
110 edge_2: tgt_curve.edge,
111 edge_1_t: src_t,
112 edge_2_t: tgt_t
113 }
114 })
115 .map(|mut collision| {
116 if Self::t_is_one(collision.edge_1_t) {
118 collision.edge_1 = self.following_edge_ref(collision.edge_1);
119 collision.edge_1_t = 0.0;
120 }
121
122 if Self::t_is_one(collision.edge_2_t) {
123 collision.edge_2 = self.following_edge_ref(collision.edge_2);
124 collision.edge_2_t = 0.0;
125 }
126
127 collision
128 });
129
130 collisions.extend(edge_collisions);
132 }
133
134 for edge in ordered_edges {
136 if let Some((t1, t2)) = find_self_intersection_point(&edge, accuracy) {
138 if !(t1 <= 0.0 && t2 >= 1.0) && !(t1 >= 1.0 && t2 <= 0.0) {
139 collisions.push(Collision {
140 edge_1: edge.edge,
141 edge_2: edge.edge,
142 edge_1_t: t1,
143 edge_2_t: t2
144 });
145 }
146 }
147 }
148
149 collisions
150 }
151
152 fn find_collisions(&self, collide_from: Range<usize>, collide_to: Range<usize>, accuracy: f64) -> Vec<Collision> {
156 if collide_from == collide_to {
157 return self.find_self_collisions(collide_from, accuracy);
158 }
159
160 let collide_src = self.get_ordered_edges(collide_from);
162 let collide_tgt = self.get_ordered_edges(collide_to);
163
164 let mut collisions = vec![];
166
167 for (src_curve, tgt_curve) in sweep_against(collide_src.iter(), collide_tgt.iter()) {
168 let mut edge_collisions = curve_intersects_curve_clip(src_curve, tgt_curve, accuracy);
170 if edge_collisions.is_empty() { continue; }
171
172 remove_and_round_close_collisions(&mut edge_collisions, src_curve, tgt_curve);
174
175 let edge_collisions = edge_collisions.into_iter()
178 .filter(|(src_t, tgt_t)| !(Self::t_is_zero(*src_t) && Self::t_is_zero(*tgt_t)))
179 .map(|(src_t, tgt_t)| {
180 Collision {
181 edge_1: src_curve.edge,
182 edge_2: tgt_curve.edge,
183 edge_1_t: src_t,
184 edge_2_t: tgt_t
185 }
186 })
187 .map(|mut collision| {
188 if Self::t_is_one(collision.edge_1_t) {
190 collision.edge_1 = self.following_edge_ref(collision.edge_1);
191 collision.edge_1_t = 0.0;
192 }
193
194 if Self::t_is_one(collision.edge_2_t) {
195 collision.edge_2 = self.following_edge_ref(collision.edge_2);
196 collision.edge_2_t = 0.0;
197 }
198
199 collision
200 });
201
202 collisions.extend(edge_collisions);
204 }
205
206 collisions
207 }
208
209 fn create_collision_points(&mut self, collisions: Vec<Collision>) -> Vec<(Collision, usize)> {
213 let mut collision_points = vec![];
215 collision_points.reserve(collisions.len());
216
217 for collision in collisions.into_iter() {
218 let point_idx = if Self::t_is_zero(collision.edge_1_t) {
220 collision.edge_1.start_idx
222 } else if Self::t_is_zero(collision.edge_2_t) {
223 collision.edge_2.start_idx
225 } else {
226 let edge = self.get_edge(collision.edge_1);
228 let new_point_pos = edge.point_at_pos(collision.edge_1_t);
229 let new_point_idx = self.points.len();
230
231 self.points.push(GraphPathPoint {
232 position: new_point_pos,
233 forward_edges: smallvec![],
234 connected_from: smallvec![]
235 });
236
237 new_point_idx
238 };
239
240 collision_points.push((collision, point_idx));
242 }
243
244 collision_points
245 }
246
247 fn organize_collisions_by_edge(&self, collisions: Vec<(Collision, usize)>) -> Vec<Option<SmallVec<[SmallVec<[(f64, usize); 2]>; 2]>>> {
254 let mut points: Vec<Option<SmallVec<[SmallVec<[(f64, usize); 2]>; 2]>>> = vec![None; self.num_points()];
256
257 for (collision, end_point_idx) in collisions.iter() {
259 let point = points[collision.edge_1.start_idx].get_or_insert_with(|| smallvec![smallvec![]; self.points[collision.edge_1.start_idx].forward_edges.len()]);
261 let edge = &mut point[collision.edge_1.edge_idx];
262
263 edge.push((collision.edge_1_t, *end_point_idx));
264
265 let point = points[collision.edge_2.start_idx].get_or_insert_with(|| smallvec![smallvec![]; self.points[collision.edge_2.start_idx].forward_edges.len()]);
267 let edge = &mut point[collision.edge_2.edge_idx];
268
269 edge.push((collision.edge_2_t, *end_point_idx));
270 }
271
272 points
273 }
274
275 pub (crate) fn detect_collisions(&mut self, collide_from: Range<usize>, collide_to: Range<usize>, accuracy: f64) -> bool {
284 let all_collisions = self.find_collisions(collide_from, collide_to, accuracy);
286 if all_collisions.is_empty() {
287 let collided_at_point = self.combine_overlapping_points(accuracy);
288 self.remove_all_very_short_edges();
289 return collided_at_point;
290 }
291
292 let all_collisions = self.create_collision_points(all_collisions);
294
295 let collisions_by_edge = self.organize_collisions_by_edge(all_collisions);
297
298 let collisions_by_point = collisions_by_edge.into_iter()
300 .enumerate()
301 .filter_map(|(point_idx, collisions)| collisions.map(|collisions| (point_idx, collisions)));
302
303 for (point_idx, edge_collisions) in collisions_by_point {
305 for (edge_idx, mut collisions) in edge_collisions.into_iter().enumerate() {
306 if collisions.is_empty() { continue; }
308
309 self.check_following_edge_consistency();
310
311 let edge = self.get_edge(GraphEdgeRef { start_idx: point_idx, edge_idx: edge_idx, reverse: false });
313 let kind = edge.kind();
314 let label = edge.label();
315 let edge = Curve::from_curve(&edge);
316
317 collisions.sort_by(|(t1, _end_point_idx1), (t2, _end_point_idx2)| {
319 if t1 < t2 {
320 Ordering::Less
321 } else if t1 > t2 {
322 Ordering::Greater
323 } else {
324 Ordering::Equal
325 }
326 });
327
328 let mut remaining_edge = edge;
330 let mut remaining_t = 1.0;
331 let final_point_idx = self.points[point_idx].forward_edges[edge_idx].end_idx;
332 let final_following_edge_idx = self.points[point_idx].forward_edges[edge_idx].following_edge_idx;
333 let mut last_point_idx = point_idx;
334 let mut previous_edge = None;
335 let mut found_collisions = false;
336
337 let mut collisions = collisions.into_iter()
339 .filter(|(t, _)| !Self::t_is_zero(*t));
340
341 if let Some((t, end_point_idx)) = collisions.next() {
343 let (next_edge, new_remaining_edge) = remaining_edge.subdivide::<Curve<_>>(t);
345 let following_edge_idx = self.points[end_point_idx].forward_edges.len();
346 let (cp1, cp2) = next_edge.control_points();
347
348 test_assert!(next_edge.start_point().is_near_to(&self.points[point_idx].position, 0.1));
349 test_assert!(next_edge.end_point().is_near_to(&self.points[end_point_idx].position, 0.1));
350
351 let old_edge = &mut self.points[point_idx].forward_edges[edge_idx];
353
354 old_edge.cp1 = cp1;
355 old_edge.cp2 = cp2;
356 old_edge.end_idx = end_point_idx;
357 old_edge.following_edge_idx = following_edge_idx;
358 old_edge.invalidate_cache();
359
360 previous_edge = Some((point_idx, edge_idx));
362 remaining_t = 1.0-t;
363 remaining_edge = new_remaining_edge;
364 last_point_idx = end_point_idx;
365 found_collisions = true;
366 }
367
368 for (t, end_point_idx) in collisions {
370 let new_edge_idx = self.points[last_point_idx].forward_edges.len();
372 if let Some((point_idx, edge_idx)) = previous_edge {
373 self.points[point_idx].forward_edges[edge_idx].following_edge_idx = new_edge_idx;
374 }
375
376 let t2 = (t - (1.0-remaining_t))/remaining_t;
378 let (next_edge, new_remaining_edge) = remaining_edge.subdivide::<Curve<_>>(t2);
379 let (cp1, cp2) = next_edge.control_points();
380
381 test_assert!(next_edge.start_point().is_near_to(&self.points[last_point_idx].position, 0.1));
382 test_assert!(next_edge.end_point().is_near_to(&self.points[end_point_idx].position, 0.1));
383
384 let new_edge = GraphPathEdge::new(kind, (cp1, cp2), end_point_idx, label, 0);
386 self.points[last_point_idx].forward_edges.push(new_edge);
387
388 previous_edge = Some((last_point_idx, new_edge_idx));
390 remaining_t = 1.0-t;
391 remaining_edge = new_remaining_edge;
392 last_point_idx = end_point_idx;
393 found_collisions = true;
394 }
395
396 if found_collisions {
398 let new_edge_idx = self.points[last_point_idx].forward_edges.len();
400 if let Some((point_idx, edge_idx)) = previous_edge {
401 self.points[point_idx].forward_edges[edge_idx].following_edge_idx = new_edge_idx;
402 }
403
404 let end_point_idx = final_point_idx;
406 let following_edge_idx = final_following_edge_idx;
407 let (cp1, cp2) = remaining_edge.control_points();
408
409 test_assert!(remaining_edge.start_point().is_near_to(&self.points[last_point_idx].position, 0.1));
410 test_assert!(remaining_edge.end_point().is_near_to(&self.points[end_point_idx].position, 0.1));
411
412 let final_edge = GraphPathEdge::new(kind, (cp1, cp2), end_point_idx, label, following_edge_idx);
414 self.points[last_point_idx].forward_edges.push(final_edge);
415 }
416 }
417 }
418
419 self.check_following_edge_consistency();
421
422 self.recalculate_reverse_connections();
423 self.combine_overlapping_points(accuracy);
424 self.remove_all_very_short_edges();
425
426 self.check_following_edge_consistency();
427
428 true
429 }
430
431 fn sweep_for_nearby_points(&mut self, accuracy: f64) -> impl Iterator<Item=(usize, usize)> {
437 struct PointArea<'a, Point, Label>(&'a GraphPath<Point, Label>, usize);
439
440 impl<'a, Point: Coordinate+Coordinate2D, Label> PointArea<'a, Point, Label> {
441 #[inline]
442 fn pos(&self) -> &Point {
443 let PointArea(graph, point_idx) = self;
444
445 &graph.points[*point_idx].position
446 }
447
448 #[inline]
449 fn idx(&self) -> usize {
450 let PointArea(_graph, point_idx) = self;
451
452 *point_idx
453 }
454 }
455
456 impl<'a, Point: Coordinate+Coordinate2D, Label> Geo for PointArea<'a, Point, Label> {
457 type Point = Point;
458 }
459
460 impl<'a, Point: Coordinate+Coordinate2D, Label> HasBoundingBox for PointArea<'a, Point, Label> {
461 fn get_bounding_box<Bounds: BoundingBox<Point=Self::Point>>(&self) -> Bounds {
462 let PointArea(graph, point_idx) = self;
463
464 let point = &graph.points[*point_idx];
465 let lower = Point::from_components(&[point.position.x()-1.0, point.position.y()-1.0]);
466 let upper = Point::from_components(&[point.position.x()+1.0, point.position.y()+1.0]);
467
468 Bounds::from_min_max(lower, upper)
469 }
470 }
471
472 let mut all_points = (0..self.points.len()).into_iter()
474 .map(|idx| PointArea(self, idx))
475 .collect::<Vec<_>>();
476 all_points.sort_by(|point1, point2| {
477 let x1 = point1.pos().x();
478 let x2 = point2.pos().x();
479
480 x1.partial_cmp(&x2).unwrap_or(Ordering::Equal)
481 });
482
483 let min_distance_squared = accuracy * accuracy;
485 let colliding_points = sweep_self(all_points.iter())
486 .filter(|(point1, point2)| {
487 if point1.idx() == point2.idx() {
488 false
490 } else {
491 let p1 = point1.pos();
493 let p2 = point2.pos();
494
495 let (x1, y1) = (p1.x(), p1.y());
496 let (x2, y2) = (p2.x(), p2.y());
497 let (dx, dy) = (x2-x1, y2-y1);
498
499 let distance_squared = dx*dx + dy*dy;
500
501 distance_squared < min_distance_squared
502 }
503 });
504
505 colliding_points
507 .map(|(point1, point2)| {
508 (point1.idx(), point2.idx())
509 })
510 .collect::<Vec<_>>()
511 .into_iter()
512 }
513
514 #[inline(never)]
520 pub fn combine_overlapping_points(&mut self, accuracy: f64) -> bool {
521 for point_idx in 0..self.points.len() {
523 for edge_idx in 0..(self.points[point_idx].forward_edges.len()) {
524 let end_point_idx = self.points[point_idx].forward_edges[edge_idx].end_idx;
525 if end_point_idx == point_idx {
526 continue;
528 }
529
530 let start_point = &self.points[point_idx].position;
531 let end_point = &self.points[end_point_idx].position;
532
533 if start_point.is_near_to(end_point, accuracy) {
534 self.points[end_point_idx].position = self.points[point_idx].position;
535 }
536 }
537 }
538
539 let mut nearby_points = self.sweep_for_nearby_points(accuracy);
541
542 if let Some(nearby_point) = nearby_points.next() {
543 let min_distance_squared = accuracy * accuracy;
545 let mut remapped_points = (0..self.points.len())
546 .into_iter()
547 .map(|idx| (idx, None)) .collect::<Vec<(_, Option<Point>)>>();
549
550 let mut nearby_point = nearby_point;
551 loop {
552 let (p1_orig_idx, p2_orig_idx) = nearby_point;
554 debug_assert!(p1_orig_idx != p2_orig_idx); let (p1_idx, p1_pos) = &remapped_points[p1_orig_idx];
558 let (p2_idx, p2_pos) = &remapped_points[p2_orig_idx];
559
560 let moved = p1_pos.is_some() || p2_pos.is_some();
562
563 let p1_pos = if let Some(pos) = p1_pos { *pos } else { self.points[*p1_idx].position };
564 let p2_pos = if let Some(pos) = p2_pos { *pos } else { self.points[*p2_idx].position };
565
566 if !moved || Self::point_is_near(&p1_pos, &p2_pos, min_distance_squared) {
567 let pos = Self::snap_points(&p1_pos, &p2_pos);
569 let remap_idx = usize::min(*p1_idx, *p2_idx);
570
571 remapped_points[p1_orig_idx] = (remap_idx, Some(pos));
572 remapped_points[p2_orig_idx] = (remap_idx, Some(pos));
573 }
574
575 if let Some(next_point) = nearby_points.next() {
577 nearby_point = next_point;
578 } else {
579 break;
580 }
581 }
582
583 let mut following_edge_idx_offset = vec![0; self.points.len()];
585
586 for original_idx in 0..self.points.len() {
587 if let (new_idx, Some(new_pos)) = &remapped_points[original_idx] {
588 self.points[original_idx].position = *new_pos;
590
591 if *new_idx == original_idx { continue; }
593
594 let mut new_idx = *new_idx;
596 loop {
597 let (next_idx, _) = &remapped_points[new_idx];
598 let next_idx = *next_idx;
599
600 if next_idx == new_idx {
601 break;
602 } else {
603 remapped_points[original_idx].0 = next_idx;
604 new_idx = next_idx;
605 }
606 }
607
608 let forward_edges = mem::take(&mut self.points[original_idx].forward_edges);
610 let connected_from = mem::take(&mut self.points[original_idx].connected_from);
611
612 following_edge_idx_offset[original_idx] = self.points[new_idx].forward_edges.len();
613
614 self.points[new_idx].forward_edges.extend(forward_edges.into_iter());
615 self.points[new_idx].connected_from.extend(connected_from.into_iter());
616 }
617 }
618
619 for point in self.points.iter_mut() {
621 for edge in point.forward_edges.iter_mut() {
623 let new_end_idx = remapped_points[edge.end_idx].0;
624
625 if new_end_idx != edge.end_idx {
626 let following_edge_idx_offset = following_edge_idx_offset[edge.end_idx];
627
628 edge.end_idx = new_end_idx;
629 edge.following_edge_idx += following_edge_idx_offset;
630 }
631 }
632
633 let mut remapped = false;
635 for connected_from_idx in point.connected_from.iter_mut() {
636 let new_connected_from_idx = remapped_points[*connected_from_idx].0;
637
638 if new_connected_from_idx != *connected_from_idx {
639 *connected_from_idx = new_connected_from_idx;
640 remapped = true;
641 }
642 }
643
644 if remapped {
646 point.connected_from.sort_unstable();
647 point.connected_from.dedup();
648 }
649 }
650
651 true
652 } else {
653 false
655 }
656 }
657
658 #[cfg(any(test, feature="extra_checks"))]
662 pub (crate) fn check_following_edge_consistency(&self) {
663 let mut used_edges = vec![vec![]; self.points.len()];
664
665 for point_idx in 0..(self.points.len()) {
666 let point = &self.points[point_idx];
667
668 for edge_idx in 0..(point.forward_edges.len()) {
669 let edge = &point.forward_edges[edge_idx];
670
671 test_assert!(edge.end_idx < self.points.len());
672 test_assert!(edge.following_edge_idx < self.points[edge.end_idx].forward_edges.len());
673 test_assert!(!used_edges[edge.end_idx].contains(&edge.following_edge_idx));
674
675 used_edges[edge.end_idx].push(edge.following_edge_idx);
676 }
677 }
678 }
679
680 #[cfg(not(any(test, feature="extra_checks")))]
681 pub (crate) fn check_following_edge_consistency(&self) {
682
683 }
684}
685
686fn remove_and_round_close_collisions<C: BezierCurve>(collisions: &mut SmallVec<[(f64, f64); 8]>, src: &C, tgt: &C)
695where
696 C::Point: Coordinate+Coordinate2D
697{
698 if collisions.is_empty() {
700 return;
701 }
702
703 let mut positions = collisions.iter().map(|(t1, _t2)| src.point_at_pos(*t1)).collect::<Vec<_>>();
705
706 let mut collision_idx = 0;
708 while collision_idx+1 < collisions.len() {
709 if positions[collision_idx].is_near_to(&positions[collision_idx+1], CLOSE_DISTANCE) {
711 if (collisions[collision_idx].0 - collisions[collision_idx+1].0).abs() < SMALL_T_DISTANCE
712 && (collisions[collision_idx].1 - collisions[collision_idx+1].1).abs() < SMALL_T_DISTANCE {
713 collisions.remove(collision_idx); positions.remove(collision_idx);
714 collisions.remove(collision_idx); positions.remove(collision_idx);
715 } else {
716 collision_idx += 1;
717 }
718 } else {
719 collision_idx += 1;
720 }
721 }
722
723 if !collisions.is_empty() {
725 let src_start = src.start_point();
727 let src_end = src.end_point();
728 let tgt_start = tgt.start_point();
729 let tgt_end = tgt.end_point();
730
731 for collision_idx in 0..collisions.len() {
733 if collisions[collision_idx].0 > 0.0 && collisions[collision_idx].0 < 1.0 {
735 if src_start.is_near_to(&positions[collision_idx], CLOSE_DISTANCE) && collisions[collision_idx].0 < SMALL_T_DISTANCE {
736 collisions[collision_idx].0 = 0.0;
737 }
738
739 if src_end.is_near_to(&positions[collision_idx], CLOSE_DISTANCE) && collisions[collision_idx].0 > 1.0-SMALL_T_DISTANCE {
740 collisions[collision_idx].0 = 1.0;
741 }
742 }
743
744 if collisions[collision_idx].1 > 0.0 && collisions[collision_idx].1 < 1.0 && collisions[collision_idx].1 < SMALL_T_DISTANCE {
746 if tgt_start.is_near_to(&positions[collision_idx], CLOSE_DISTANCE) {
747 collisions[collision_idx].1 = 0.0;
748 }
749
750 if tgt_end.is_near_to(&positions[collision_idx], CLOSE_DISTANCE) && collisions[collision_idx].1 > 1.0-SMALL_T_DISTANCE {
751 collisions[collision_idx].1 = 1.0;
752 }
753 }
754 }
755 }
756}