1use crate::delaunay_core::math;
2use crate::handles::{DirectedEdgeHandle, FixedVertexHandle, VertexHandle};
3use crate::{HasPosition, Point2, Triangulation, TriangulationExt};
4
5#[doc = include_str!("../images/line_intersection_iterator_scenario.svg")]
23pub struct LineIntersectionIterator<'a, V, DE, UE, F>
60where
61 V: HasPosition,
62 DE: Default,
63 UE: Default,
64 F: Default,
65{
66 cur_intersection: Option<Intersection<'a, V, DE, UE, F>>,
67 line_from: Point2<V::Scalar>,
68 line_to: Point2<V::Scalar>,
69}
70
71#[allow(clippy::enum_variant_names)]
75pub enum Intersection<'a, V, DE, UE, F>
76where
77 V: HasPosition,
78{
79 EdgeIntersection(DirectedEdgeHandle<'a, V, DE, UE, F>),
82 VertexIntersection(VertexHandle<'a, V, DE, UE, F>),
86 EdgeOverlap(DirectedEdgeHandle<'a, V, DE, UE, F>),
90}
91
92impl<V, DE, UE, F> core::fmt::Debug for Intersection<'_, V, DE, UE, F>
93where
94 V: HasPosition,
95{
96 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
97 use self::Intersection::*;
98 match self {
99 EdgeIntersection(handle) => write!(f, "EdgeIntersection({:?})", handle),
100 VertexIntersection(handle) => write!(f, "VertexIntersection({:?})", handle),
101 EdgeOverlap(handle) => write!(f, "EdgeOverlap({:?})", handle),
102 }
103 }
104}
105
106impl<V, DE, UE, F> PartialEq for Intersection<'_, V, DE, UE, F>
107where
108 V: HasPosition,
109{
110 fn eq(&self, other: &Self) -> bool {
111 use self::Intersection::*;
112 match (self, other) {
113 (&EdgeIntersection(h0), &EdgeIntersection(h1)) => h0 == h1,
114 (&VertexIntersection(h0), &VertexIntersection(h1)) => h0 == h1,
115 (&EdgeOverlap(h0), &EdgeOverlap(h1)) => h0 == h1,
116 _ => false,
117 }
118 }
119}
120
121impl<V, DE, UE, F> Copy for Intersection<'_, V, DE, UE, F> where V: HasPosition {}
122
123impl<V, DE, UE, F> Clone for Intersection<'_, V, DE, UE, F>
124where
125 V: HasPosition,
126{
127 fn clone(&self) -> Self {
128 *self
129 }
130}
131
132impl<'a, V, DE, UE, F> Intersection<'a, V, DE, UE, F>
133where
134 V: HasPosition,
135{
136 pub fn as_edge_intersection(&self) -> Option<DirectedEdgeHandle<'a, V, DE, UE, F>> {
138 match self {
139 Intersection::EdgeIntersection(ref edge) => Some(*edge),
140 _ => None,
141 }
142 }
143}
144
145impl<'a, V, DE, UE, F> LineIntersectionIterator<'a, V, DE, UE, F>
146where
147 V: HasPosition,
148 DE: Default,
149 UE: Default,
150 F: Default,
151{
152 pub fn new<T>(
155 delaunay: &'a T,
156 line_from: Point2<V::Scalar>,
157 line_to: Point2<V::Scalar>,
158 ) -> LineIntersectionIterator<'a, V, DE, UE, F>
159 where
160 T: Triangulation<Vertex = V, DirectedEdge = DE, UndirectedEdge = UE, Face = F>,
161 {
162 let first_intersection = Self::get_first_intersection(delaunay, line_from, line_to);
163 LineIntersectionIterator {
164 cur_intersection: first_intersection,
165 line_from,
166 line_to,
167 }
168 }
169
170 pub fn new_from_handles<T>(
197 delaunay: &T,
198 from: FixedVertexHandle,
199 to: FixedVertexHandle,
200 ) -> LineIntersectionIterator<'_, V, DE, UE, F>
201 where
202 T: Triangulation<Vertex = V, DirectedEdge = DE, UndirectedEdge = UE, Face = F>,
203 {
204 let from = delaunay.vertex(from);
205 let line_from = from.position();
206 let to = delaunay.vertex(to);
207 let line_to = to.position();
208
209 LineIntersectionIterator {
210 cur_intersection: Some(Intersection::VertexIntersection(from)),
211 line_from,
212 line_to,
213 }
214 }
215
216 fn get_first_intersection<T>(
217 delaunay: &'a T,
218 line_from: Point2<V::Scalar>,
219 line_to: Point2<V::Scalar>,
220 ) -> Option<Intersection<'a, V, DE, UE, F>>
221 where
222 T: Triangulation<Vertex = V, DirectedEdge = DE, UndirectedEdge = UE, Face = F>,
223 {
224 use crate::PositionInTriangulation::*;
225
226 match delaunay.locate_with_hint_option_core(line_from, None) {
227 OutsideOfConvexHull(edge_handle) => {
228 let mut edge = delaunay.directed_edge(edge_handle);
229 let line_from_query = edge.side_query(line_from);
230
231 loop {
232 if line_from_query.is_on_line() {
233 let dist_from = edge.from().position().distance_2(line_from);
234 let dist_to = edge.to().position().distance_2(line_from);
235 let vertex = if dist_to < dist_from {
236 edge.to()
237 } else {
238 edge.from()
239 };
240 return Some(Intersection::VertexIntersection(vertex));
241 }
242 let line_to_query = edge.side_query(line_to);
243
244 if line_to_query.is_on_left_side() {
245 return None;
246 }
247
248 let edge_from = edge.from().position();
249 let edge_to = edge.to().position();
250 let edge_from_query = math::side_query(line_from, line_to, edge_from);
251 let edge_to_query = math::side_query(line_from, line_to, edge_to);
252
253 match (
254 edge_from_query.is_on_left_side(),
255 edge_to_query.is_on_left_side_or_on_line(),
256 ) {
257 (true, true) => edge = edge.prev(),
258 (false, false) => edge = edge.next(),
259 (false, true) => {
260 if edge_to_query.is_on_line() {
261 return Some(Intersection::VertexIntersection(edge.to()));
262 }
263 if edge_from_query.is_on_line() {
264 return Some(Intersection::VertexIntersection(edge.from()));
265 }
266 return Some(Intersection::EdgeIntersection(edge.rev()));
267 }
268 (true, false) => panic!("Unexpected edge topology. This is a bug."),
269 }
270 }
271 }
272 OnFace(face_handle) => get_first_edge_from_edge_ring(
273 delaunay.face(face_handle).adjacent_edges().iter().copied(),
274 line_from,
275 line_to,
276 ),
277 OnVertex(vertex_handle) => Some(Intersection::VertexIntersection(
278 delaunay.vertex(vertex_handle),
279 )),
280 OnEdge(edge) => {
281 let edge = delaunay.directed_edge(edge);
282 let edge_from = edge.from().position();
283 let edge_to = edge.to().position();
284 let from_query = math::side_query(line_from, line_to, edge_from);
285 let to_query = math::side_query(line_from, line_to, edge_to);
286 if from_query.is_on_line() && to_query.is_on_line() {
287 let dist_to = edge_to.sub(line_to).length2();
288 let dist_from = edge_from.sub(line_to).length2();
289 if dist_to < dist_from {
290 Some(Intersection::EdgeOverlap(edge))
291 } else {
292 Some(Intersection::EdgeOverlap(edge.rev()))
293 }
294 } else {
295 let edge_query = edge.side_query(line_to);
296 if edge_query.is_on_left_side() {
297 Some(Intersection::EdgeIntersection(edge))
298 } else {
299 Some(Intersection::EdgeIntersection(edge.rev()))
300 }
301 }
302 }
303 NoTriangulation => {
304 if let Some(next_vertex) = delaunay.vertices().next() {
305 let single_vertex = next_vertex.position();
306 let projection = math::project_point(line_from, line_to, single_vertex);
307 if projection.is_on_edge() {
308 let query = math::side_query(line_from, line_to, single_vertex);
309 if query.is_on_line() {
310 return Some(Intersection::VertexIntersection(next_vertex));
311 }
312 }
313 }
314 None
315 }
316 }
317 }
318
319 fn get_next(&mut self) -> Option<Intersection<'a, V, DE, UE, F>> {
320 use self::Intersection::*;
321 match self.cur_intersection {
322 Some(EdgeIntersection(cur_edge)) => {
323 match trace_direction_out_of_edge(cur_edge, self.line_from, self.line_to) {
324 EdgeOutDirection::ConvexHull => None,
325 EdgeOutDirection::VertexIntersection(vertex) => {
326 Some(VertexIntersection(vertex))
327 }
328 EdgeOutDirection::EdgeIntersection(edge) => Some(EdgeIntersection(edge)),
329 EdgeOutDirection::NoIntersection => None,
330 }
331 }
332 Some(VertexIntersection(vertex)) => {
333 if vertex.position() == self.line_to {
334 None
336 } else {
337 match trace_direction_out_of_vertex(vertex, self.line_to) {
338 VertexOutDirection::ConvexHull => None,
339 VertexOutDirection::EdgeOverlap(edge) => Some(EdgeOverlap(edge)),
340 VertexOutDirection::EdgeIntersection(edge) => {
341 if edge.side_query(self.line_to).is_on_right_side() {
342 None
344 } else {
345 Some(EdgeIntersection(edge))
346 }
347 }
348 }
349 }
350 }
351 Some(EdgeOverlap(edge)) => {
352 if self.line_from == self.line_to {
353 None
354 } else if math::project_point(self.line_from, self.line_to, edge.to().position())
355 .is_on_edge()
356 {
357 Some(VertexIntersection(edge.to()))
358 } else {
359 None
360 }
361 }
362 None => None,
363 }
364 }
365}
366
367impl<'a, V, DE, UE, F> Iterator for LineIntersectionIterator<'a, V, DE, UE, F>
368where
369 V: HasPosition,
370 DE: Default,
371 UE: Default,
372 F: Default,
373{
374 type Item = Intersection<'a, V, DE, UE, F>;
375
376 fn next(&mut self) -> Option<Self::Item> {
377 let cur = self.cur_intersection;
378 self.cur_intersection = self.get_next();
379 cur
380 }
381}
382
383fn get_first_edge_from_edge_ring<'a, I, V, DE, UE, F>(
384 ring: I,
385 line_from: Point2<V::Scalar>,
386 line_to: Point2<V::Scalar>,
387) -> Option<Intersection<'a, V, DE, UE, F>>
388where
389 I: IntoIterator<Item = DirectedEdgeHandle<'a, V, DE, UE, F>>,
390 V: HasPosition,
391{
392 use self::Intersection::*;
393 for edge in ring {
394 let cur_from = edge.from().position();
395 let cur_to = edge.to().position();
396
397 debug_assert!(math::side_query(cur_from, cur_to, line_from).is_on_left_side_or_on_line());
398 if math::intersects_edge_non_collinear(line_from, line_to, cur_from, cur_to) {
399 if math::side_query(line_from, line_to, cur_from).is_on_line() {
400 return Some(VertexIntersection(edge.from()));
401 } else if math::side_query(line_from, line_to, cur_to).is_on_line() {
402 return Some(VertexIntersection(edge.to()));
403 }
404 return Some(EdgeIntersection(edge.rev()));
405 }
406 }
407 None
408}
409
410pub(super) enum VertexOutDirection<'a, V, DE, UE, F> {
411 ConvexHull,
412 EdgeOverlap(DirectedEdgeHandle<'a, V, DE, UE, F>),
413 EdgeIntersection(DirectedEdgeHandle<'a, V, DE, UE, F>),
414}
415
416pub(super) fn trace_direction_out_of_vertex<V, DE, UE, F>(
417 vertex: VertexHandle<V, DE, UE, F>,
418 line_to: Point2<V::Scalar>,
419) -> VertexOutDirection<V, DE, UE, F>
420where
421 V: HasPosition,
422{
423 let mut current_edge = match vertex.out_edge() {
424 Some(edge) => edge,
425 None => return VertexOutDirection::ConvexHull,
426 };
427
428 let mut current_query = current_edge.side_query(line_to);
429
430 let iterate_ccw = current_query.is_on_left_side();
431
432 loop {
433 if current_query.is_on_line() && !current_edge.project_point(line_to).is_before_edge() {
434 return VertexOutDirection::EdgeOverlap(current_edge);
435 }
436
437 let next = if iterate_ccw {
438 current_edge.ccw()
439 } else {
440 current_edge.cw()
441 };
442
443 let next_query = next.side_query(line_to);
444 if next_query.is_on_line() && !next.project_point(line_to).is_before_edge() {
445 return VertexOutDirection::EdgeOverlap(next);
446 }
447
448 let face_between_current_and_next = if iterate_ccw {
449 current_edge.face()
450 } else {
451 next.face()
452 };
453 if face_between_current_and_next.is_outer() {
454 return VertexOutDirection::ConvexHull;
455 }
456
457 if iterate_ccw == next_query.is_on_right_side() {
458 let segment_edge = if iterate_ccw {
459 current_edge.next()
460 } else {
461 current_edge.rev().prev()
462 };
463 return VertexOutDirection::EdgeIntersection(segment_edge.rev());
464 }
465
466 current_query = next_query;
467 current_edge = next;
468 }
469}
470
471pub(super) enum EdgeOutDirection<'a, V, DE, UE, F> {
472 ConvexHull,
473 VertexIntersection(VertexHandle<'a, V, DE, UE, F>),
474 EdgeIntersection(DirectedEdgeHandle<'a, V, DE, UE, F>),
475 NoIntersection,
476}
477
478pub(super) fn trace_direction_out_of_edge<V, DE, UE, F>(
479 edge: DirectedEdgeHandle<V, DE, UE, F>,
480 line_from: Point2<V::Scalar>,
481 line_to: Point2<V::Scalar>,
482) -> EdgeOutDirection<V, DE, UE, F>
483where
484 V: HasPosition,
485{
486 debug_assert!(
487 edge.side_query(line_to).is_on_left_side_or_on_line(),
488 "The target must be on the left side of the current edge"
489 );
490
491 let e_prev = if edge.is_outer_edge() {
492 return EdgeOutDirection::ConvexHull;
494 } else {
495 edge.prev()
496 };
497
498 let o_next = edge.next();
499
500 let e_prev_inter = e_prev.intersects_edge_non_collinear(line_from, line_to);
502 let o_next_inter = o_next.intersects_edge_non_collinear(line_from, line_to);
503
504 match (e_prev_inter, o_next_inter) {
505 (true, false) => EdgeOutDirection::EdgeIntersection(e_prev.rev()),
506 (false, true) => EdgeOutDirection::EdgeIntersection(o_next.rev()),
507 (true, true) => {
508 EdgeOutDirection::VertexIntersection(e_prev.from())
510 }
511 (false, false) => EdgeOutDirection::NoIntersection,
512 }
513}
514
515#[cfg(test)]
516mod test {
517 use self::Intersection::*;
518 use super::*;
519 use crate::{InsertionError, Point2, Triangulation as _};
520
521 use alloc::{vec, vec::Vec};
522
523 type Triangulation = crate::DelaunayTriangulation<Point2<f64>>;
524
525 fn reverse<'a, V, DE, UE, F>(
526 intersection: &Intersection<'a, V, DE, UE, F>,
527 ) -> Intersection<'a, V, DE, UE, F>
528 where
529 V: HasPosition,
530 {
531 match intersection {
532 EdgeIntersection(edge) => EdgeIntersection(edge.rev()),
533 VertexIntersection(vertex) => VertexIntersection(*vertex),
534 EdgeOverlap(edge) => EdgeOverlap(edge.rev()),
535 }
536 }
537
538 fn check(
539 delaunay: &Triangulation,
540 from: Point2<f64>,
541 to: Point2<f64>,
542 mut expected: Vec<Intersection<Point2<f64>, (), (), ()>>,
543 ) {
544 let collected: Vec<_> = LineIntersectionIterator::new(delaunay, from, to).collect();
545 assert_eq!(collected, expected);
546 let mut reversed = Vec::new();
547 let rev_collected: Vec<_> = LineIntersectionIterator::new(delaunay, to, from).collect();
548 for intersection in rev_collected.iter() {
549 reversed.push(reverse(intersection));
550 }
551 expected.reverse();
552 assert_eq!(reversed, expected);
553 }
554
555 fn create_test_triangulation() -> Result<
556 (
557 Triangulation,
558 FixedVertexHandle,
559 FixedVertexHandle,
560 FixedVertexHandle,
561 FixedVertexHandle,
562 ),
563 InsertionError,
564 > {
565 let v0 = Point2::new(-2.0, -2.0);
566 let v1 = Point2::new(2.0, 2.0);
567 let v2 = Point2::new(1.0, -1.0);
568 let v3 = Point2::new(-1.0, 1.0);
569
570 let mut delaunay = Triangulation::new();
571 let v0 = delaunay.insert(v0)?;
572 let v1 = delaunay.insert(v1)?;
573 let v2 = delaunay.insert(v2)?;
574 let v3 = delaunay.insert(v3)?;
575
576 Ok((delaunay, v0, v1, v2, v3))
577 }
578
579 #[test]
580 fn test_single_line_intersection() -> Result<(), InsertionError> {
581 let (delaunay, _, _, v2, v3) = create_test_triangulation()?;
582 let from = Point2::new(-0.5, -0.5);
583 let to = Point2::new(0.5, 0.5);
584 let edge = delaunay.get_edge_from_neighbors(v3, v2).unwrap();
585 check(&delaunay, from, to, vec![EdgeIntersection(edge)]);
586 Ok(())
587 }
588
589 #[test]
590 fn test_empty_inner_intersection() -> Result<(), InsertionError> {
591 let (delaunay, _, _, _, _) = create_test_triangulation()?;
592 let from = Point2::new(-0.5, -0.5);
593 let to = Point2::new(-0.25, -0.25);
594 assert!(LineIntersectionIterator::new(&delaunay, from, to)
595 .next()
596 .is_none());
597
598 assert!(LineIntersectionIterator::new(&delaunay, from, from)
599 .next()
600 .is_none());
601 Ok(())
602 }
603
604 #[test]
605 fn test_between_vertices_intersection() -> Result<(), InsertionError> {
606 let (delaunay, v0, v1, v2, v3) = create_test_triangulation()?;
607 let from = Point2::new(-2.0, -2.0);
608 let to = Point2::new(2.0, 2.0);
609 let edge = delaunay.get_edge_from_neighbors(v3, v2).unwrap();
610 let first = VertexIntersection(delaunay.vertex(v0));
611 let last = VertexIntersection(delaunay.vertex(v1));
612 let edges: Vec<_> = LineIntersectionIterator::new(&delaunay, from, to).collect();
613 assert_eq!(edges, vec![first, EdgeIntersection(edge), last]);
614 Ok(())
615 }
616
617 #[test]
618 fn test_mixed_intersections() -> Result<(), InsertionError> {
619 let (mut delaunay, _, v1, v2, v3) = create_test_triangulation()?;
620 let v4 = delaunay.insert(Point2::new(1.0, 1.0))?;
621 let from = Point2::new(-1.0, -1.0);
622 let to = Point2::new(2.0, 2.0);
623 let intersection_edge = delaunay.get_edge_from_neighbors(v3, v2).unwrap();
624 let overlap_edge = delaunay.get_edge_from_neighbors(v4, v1).unwrap();
625 check(
626 &delaunay,
627 from,
628 to,
629 vec![
630 EdgeIntersection(intersection_edge),
631 VertexIntersection(delaunay.vertex(v4)),
632 EdgeOverlap(overlap_edge),
633 VertexIntersection(delaunay.vertex(v1)),
634 ],
635 );
636 Ok(())
637 }
638
639 #[test]
640 fn test_out_of_hull_intersections() -> Result<(), InsertionError> {
641 let (ref d, v0, v1, v2, v3) = create_test_triangulation()?;
642
643 let edge20 = d.get_edge_from_neighbors(v2, v0).unwrap();
644 let edge20 = EdgeIntersection(edge20);
645 let edge30 = d.get_edge_from_neighbors(v3, v0).unwrap();
646 let edge30 = EdgeIntersection(edge30);
647 let edge12 = d.get_edge_from_neighbors(v1, v2).unwrap();
648 let edge12 = EdgeIntersection(edge12);
649 let edge32 = d.get_edge_from_neighbors(v3, v2).unwrap();
650 let o32 = EdgeOverlap(edge32);
651 let edge32 = EdgeIntersection(edge32);
652
653 let v0 = VertexIntersection(d.vertex(v0));
654 let v2 = VertexIntersection(d.vertex(v2));
655 let v3 = VertexIntersection(d.vertex(v3));
656
657 let from = Point2::new(-2.0, 1.0);
659 let to = Point2::new(-2.0, 0.0);
660 check(d, from, to, vec![]);
661 let from = Point2::new(-2., 0.);
663 let to = Point2::new(-2., -4.0);
664 check(d, from, to, vec![v0]);
665 let from = Point2::new(-0.5, -0.5);
666 check(d, from, to, vec![edge20]);
667 let from = Point2::new(-2.0, 0.0);
669 let to = Point2::new(0., -2.);
670 check(d, from, to, vec![edge30, edge20]);
671 let from = Point2::new(-3.0, 3.0);
672 let to = Point2::new(3.0, -3.0);
673 check(d, from, to, vec![v3, o32, v2]);
674 let from = Point2::new(-2.0, 0.0);
676 let to = Point2::new(2., -1.);
677 check(d, from, to, vec![edge30, edge32, edge12]);
678 Ok(())
679 }
680
681 #[test]
682 fn test_on_line_intersection() -> Result<(), InsertionError> {
683 let (d, _, v1, v2, v3) = create_test_triangulation()?;
684
685 let edge = d.get_edge_from_neighbors(v2, v3).unwrap();
686 let e32 = EdgeIntersection(edge.rev());
687 let o23 = EdgeOverlap(edge);
688 let o32 = EdgeOverlap(edge.rev());
689
690 let v1 = VertexIntersection(d.vertex(v1));
691 let v2 = VertexIntersection(d.vertex(v2));
692 let v3 = VertexIntersection(d.vertex(v3));
693
694 let from = Point2::new(0.0, 0.0);
695 let to = Point2::new(0.0, 0.0);
696 let collected: Vec<_> = LineIntersectionIterator::new(&d, from, to).collect();
697 assert!(collected == vec![o23] || collected == vec![o32]);
698 let to = Point2::new(0.2, 0.2);
699 check(&d, from, to, vec![e32]);
700 let to = Point2::new(2.0, 2.0);
701 check(&d, from, to, vec![e32, v1]);
702 let to = Point2::new(-30.0, 30.0);
703 check(&d, from, to, vec![o23, v3]);
704 let to = Point2::new(30.0, -30.0);
705 check(&d, from, to, vec![o32, v2]);
706 let from = Point2::new(-30.0, 30.0);
707 check(&d, from, to, vec![v3, o32, v2]);
708 Ok(())
709 }
710
711 #[test]
712 fn test_intersecting_zero_vertices() {
713 let delaunay = Triangulation::new();
714 let mut iterator = LineIntersectionIterator::new(
715 &delaunay,
716 Point2::new(0.5, 1.234),
717 Point2::new(3.223, 42.0),
718 );
719 assert!(iterator.next().is_none());
720 }
721
722 #[test]
723 fn test_intersection_when_passing_equal_line_from_and_line_to() -> Result<(), InsertionError> {
724 let (delaunay, v1, _, v3, v4) = create_test_triangulation()?;
725 let v1_position = delaunay.s().vertex(v1).position();
726 let edge = delaunay.get_edge_from_neighbors(v3, v4).unwrap();
727 let v1 = delaunay.s().vertex(v1);
728
729 check(
730 &delaunay,
731 v1_position,
732 v1_position,
733 vec![VertexIntersection(v1)],
734 );
735 let origin = Point2::new(0.0, 0.0);
736 let intersections: Vec<_> =
737 LineIntersectionIterator::new(&delaunay, origin, origin).collect();
738
739 assert_eq![intersections.len(), 1];
740 assert!(
741 intersections[0] == EdgeOverlap(edge) || intersections[0] == EdgeOverlap(edge.rev())
742 );
743 Ok(())
744 }
745
746 #[test]
747 fn test_intersecting_single_vertex() -> Result<(), InsertionError> {
748 let mut delaunay = Triangulation::new();
749 let pos = Point2::new(0.5, 0.5);
750 let v0 = delaunay.insert(pos)?;
751 let v0 = delaunay.vertex(v0);
752 let from = Point2::new(1.0, 0.0);
753 let to = Point2::new(0.0, 1.0);
754 check(&delaunay, from, to, vec![VertexIntersection(v0)]);
755 check(&delaunay, pos, pos, vec![VertexIntersection(v0)]);
756 let to = Point2::new(1.234, 42.0);
757 check(&delaunay, from, to, vec![]);
758 Ok(())
759 }
760
761 #[test]
762 fn test_intersecting_degenerate_triangulation() -> Result<(), InsertionError> {
763 let mut d = Triangulation::new();
764
765 let v2 = d.insert(Point2::new(0.0, 0.0))?;
766 let v3 = d.insert(Point2::new(1.0, 1.0))?;
767 let v1 = d.insert(Point2::new(-2.0, -2.0))?;
768 let v0 = d.insert(Point2::new(-3.0, -3.0))?;
769
770 let e01 = d.get_edge_from_neighbors(v0, v1).unwrap();
771 let e12 = d.get_edge_from_neighbors(v1, v2).unwrap();
772 let e23 = d.get_edge_from_neighbors(v2, v3).unwrap();
773
774 let v0 = VertexIntersection(d.vertex(v0));
775 let v1 = VertexIntersection(d.vertex(v1));
776 let v2 = VertexIntersection(d.vertex(v2));
777 let v3 = VertexIntersection(d.vertex(v3));
778
779 let intersection_23 = EdgeIntersection(e23);
780 let e01 = EdgeOverlap(e01);
781 let e12 = EdgeOverlap(e12);
782 let e23 = EdgeOverlap(e23);
783
784 let from = Point2::new(-4.0, -4.0);
785 let to = Point2::new(5.0, 5.0);
786 check(&d, from, to, vec![v0, e01, v1, e12, v2, e23, v3]);
787 let to = Point2::new(-2.0, -2.0);
788 check(&d, from, to, vec![v0, e01, v1]);
789 let to = Point2::new(-0.5, -0.5);
790 check(&d, from, to, vec![v0, e01, v1, e12]);
791
792 let from = Point2::new(1.0, -0.0);
793 let to = Point2::new(0.0, 1.0);
794 check(&d, from, to, vec![intersection_23]);
795 let to = Point2::new(0.5, 0.5);
796 check(&d, from, to, vec![intersection_23]);
797
798 let from = Point2::new(0.5, -0.5);
799 let to = Point2::new(-0.5, 0.5);
800 check(&d, from, to, vec![v2]);
801
802 let single_vertex = Point2::new(-2.0, -2.0);
803 check(&d, single_vertex, single_vertex, vec![v1]);
804
805 Ok(())
806 }
807
808 #[test]
809 fn test_intersecting_through_point_ending_on_face() -> Result<(), InsertionError> {
810 let mut d = Triangulation::new();
811
812 let v0 = d.insert(Point2::new(0.0, 0.0))?;
813 let v1 = d.insert(Point2::new(1.0, 1.0))?;
814 let v2 = d.insert(Point2::new(-1.0, 1.0))?;
815 let v3 = d.insert(Point2::new(0.0, 2.0))?;
816 d.insert(Point2::new(-1.0, 3.0))?;
817 d.insert(Point2::new(1.0, 3.0))?;
818
819 let e = d.get_edge_from_neighbors(v2, v1).unwrap();
820
821 let v0 = VertexIntersection(d.vertex(v0));
822 let e = EdgeIntersection(e);
823 let v3 = VertexIntersection(d.vertex(v3));
824
825 let from = Point2::new(0.0, 0.0);
826 let to = Point2::new(0.0, 2.5);
827 check(&d, from, to, vec![v0, e, v3]);
828 Ok(())
829 }
830}