1use alloc::{collections::VecDeque, vec::Vec};
2
3#[cfg(not(feature = "std"))]
4use hashbrown::HashSet;
5#[cfg(feature = "std")]
6use std::collections::HashSet;
7
8use num_traits::{one, zero, Float};
9use smallvec::smallvec;
10use smallvec::SmallVec;
11
12use crate::delaunay_core::math;
13use crate::handles::VertexHandle;
14use crate::{
15 handles::{
16 DirectedEdgeHandle, FixedDirectedEdgeHandle, FixedVertexHandle, UndirectedEdgeHandle,
17 },
18 HasPosition, Point2, SpadeNum, Triangulation,
19};
20
21pub trait DistanceMetric<S>
22where
23 S: SpadeNum,
24{
25 fn is_edge_inside(&self, points: [Point2<S>; 2]) -> bool;
26
27 fn is_handle_inside<V, DE, UE, F>(&self, handle: UndirectedEdgeHandle<V, DE, UE, F>) -> bool
28 where
29 V: HasPosition<Scalar = S>,
30 {
31 self.is_edge_inside(handle.positions())
32 }
33
34 fn distance_to_point(&self, point: Point2<S>) -> S;
35
36 fn is_point_inside(&self, point: Point2<S>) -> bool {
37 self.distance_to_point(point) <= zero()
38 }
39}
40
41#[derive(Debug, PartialOrd, PartialEq, Clone, Copy, Hash)]
46pub struct CircleMetric<S: SpadeNum> {
47 center: Point2<S>,
48 radius_2: S,
49}
50
51impl<S: SpadeNum> CircleMetric<S> {
52 pub(crate) fn new(center: Point2<S>, radius_2: S) -> Self {
53 assert!(radius_2 >= zero());
54
55 Self { center, radius_2 }
56 }
57}
58
59impl<S> DistanceMetric<S> for CircleMetric<S>
60where
61 S: SpadeNum + Float,
62{
63 fn is_edge_inside(&self, points: [Point2<S>; 2]) -> bool {
64 let [p0, p1] = points;
65 math::distance_2(p0, p1, self.center) <= self.radius_2
66 }
67
68 fn distance_to_point(&self, point: Point2<S>) -> S {
69 self.center.distance_2(point) - self.radius_2
70 }
71}
72
73#[derive(Debug, PartialOrd, PartialEq, Clone, Copy, Hash)]
78pub struct RectangleMetric<S>
79where
80 S: SpadeNum,
81{
82 lower: Point2<S>,
83 upper: Point2<S>,
84}
85
86impl<S> RectangleMetric<S>
87where
88 S: SpadeNum,
89{
90 pub(crate) fn new(lower: Point2<S>, upper: Point2<S>) -> Self {
91 Self { lower, upper }
92 }
93}
94
95impl<S> DistanceMetric<S> for RectangleMetric<S>
96where
97 S: SpadeNum,
98 S: Float,
99{
100 fn is_edge_inside(&self, points: [Point2<S>; 2]) -> bool {
101 let [from, to] = points;
102 if self.is_point_inside(from) || self.is_point_inside(to) {
103 return true;
104 }
105
106 if self.lower == self.upper {
107 return math::side_query(from, to, self.lower).is_on_line();
108 }
109
110 for [v0, v1] in self.edges() {
111 let [s0, s1] = get_edge_intersections(v0, v1, from, to);
112 if s0.is_infinite() {
113 if !math::side_query(from, to, v0).is_on_line() {
115 continue;
117 }
118
119 let p1 = math::project_point(from, to, v0);
120 let p2 = math::project_point(from, to, v1);
121
122 if p1.is_on_edge() || p2.is_on_edge() {
123 return true;
124 }
125 } else if (zero()..=one()).contains(&s0) && (zero()..=one()).contains(&s1) {
126 return true;
127 }
128 }
129 false
130 }
131
132 fn distance_to_point(&self, point: Point2<S>) -> S {
133 if self.lower == self.upper {
134 return point.distance_2(self.lower);
135 }
136
137 if self.is_point_inside(point) {
138 zero()
139 } else {
140 let [d0, d1, d2, d3] = self.edges().map(|[p0, p1]| math::distance_2(p0, p1, point));
141
142 d0.min(d1).min(d2).min(d3)
143 }
144 }
145}
146
147impl<S> RectangleMetric<S>
148where
149 S: SpadeNum,
150{
151 fn is_point_inside(&self, point: Point2<S>) -> bool {
152 point.all_component_wise(self.lower, |a, b| a >= b)
153 && point.all_component_wise(self.upper, |a, b| a <= b)
154 }
155
156 fn edges(&self) -> [[Point2<S>; 2]; 4] {
157 let lower = self.lower;
158 let upper = self.upper;
159 let v0 = lower;
160 let v1 = Point2::new(lower.x, upper.y);
161 let v2 = upper;
162 let v3 = Point2::new(upper.x, lower.y);
163
164 [[v0, v1], [v1, v2], [v2, v3], [v3, v0]]
165 }
166}
167
168fn get_edge_intersections<S: Float>(
169 v0: Point2<S>,
170 v1: Point2<S>,
171 e0: Point2<S>,
172 e1: Point2<S>,
173) -> [S; 2] {
174 let x4 = v1.x;
175 let x3 = v0.x;
176 let x2 = e1.x;
177 let x1 = e0.x;
178 let y4 = v1.y;
179 let y3 = v0.y;
180 let y2 = e1.y;
181 let y1 = e0.y;
182 let divisor = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
183 let (s0, s1);
184 if divisor == zero() {
185 s0 = S::infinity();
186 s1 = S::infinity();
187 } else {
188 s0 = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / divisor;
189 s1 = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / divisor;
190 }
191 [s0, s1]
192}
193
194#[derive(Clone, Debug, PartialEq, Eq)]
203pub(crate) struct FloodFillIterator<'a, T, M>
204where
205 T: Triangulation,
206 M: DistanceMetric<<T::Vertex as HasPosition>::Scalar>,
207{
208 t: &'a T,
209 edge_loop: VecDeque<FixedDirectedEdgeHandle>,
210 pending: Option<FixedDirectedEdgeHandle>,
211 already_visited: HashSet<FixedVertexHandle>,
212 metric: M,
213}
214
215#[derive(Clone, Debug, PartialEq, Eq)]
222pub struct VerticesInShapeIterator<'a, T, M>
223where
224 T: Triangulation,
225 M: DistanceMetric<<T::Vertex as HasPosition>::Scalar>,
226{
227 initial_elements: SmallVec<[FixedVertexHandle; 3]>,
228 inner_iter: FloodFillIterator<'a, T, M>,
229}
230
231impl<'a, T, M> VerticesInShapeIterator<'a, T, M>
232where
233 T: Triangulation,
234 M: DistanceMetric<<T::Vertex as HasPosition>::Scalar>,
235{
236 pub(crate) fn new(inner_iter: FloodFillIterator<'a, T, M>) -> Self {
237 let initial_elements = if inner_iter.t.num_vertices() == 1 {
238 smallvec![FixedVertexHandle::new(0)]
241 } else {
242 inner_iter.already_visited.iter().copied().collect()
243 };
244
245 Self {
246 initial_elements,
247 inner_iter,
248 }
249 }
250}
251
252impl<'a, T, M> Iterator for VerticesInShapeIterator<'a, T, M>
253where
254 T: Triangulation,
255 M: DistanceMetric<<T::Vertex as HasPosition>::Scalar>,
256{
257 type Item = VertexHandle<'a, T::Vertex, T::DirectedEdge, T::UndirectedEdge, T::Face>;
258
259 fn next(&mut self) -> Option<Self::Item> {
260 while let Some(next) = self.initial_elements.pop() {
261 let vertex = self.inner_iter.t.vertex(next);
262 if self.inner_iter.metric.is_point_inside(vertex.position()) {
263 return Some(vertex);
264 }
265 }
266
267 while let Some((_, vertex)) = self.inner_iter.next() {
268 if let Some(vertex) = vertex {
269 if self.inner_iter.metric.is_point_inside(vertex.position()) {
270 return Some(vertex);
271 }
272 }
273 }
274 None
275 }
276}
277
278#[derive(Clone, Debug, PartialEq, Eq)]
285pub struct EdgesInShapeIterator<'a, T, M>
286where
287 T: Triangulation,
288 M: DistanceMetric<<T::Vertex as HasPosition>::Scalar>,
289{
290 pub(crate) inner_iter: FloodFillIterator<'a, T, M>,
291}
292
293impl<'a, T, M> Iterator for EdgesInShapeIterator<'a, T, M>
294where
295 T: Triangulation,
296 M: DistanceMetric<<T::Vertex as HasPosition>::Scalar>,
297{
298 type Item = UndirectedEdgeHandle<'a, T::Vertex, T::DirectedEdge, T::UndirectedEdge, T::Face>;
299
300 fn next(&mut self) -> Option<Self::Item> {
301 self.inner_iter
302 .next()
303 .map(|(handle, _)| handle.as_undirected())
304 }
305}
306
307impl<'a, T, M> FloodFillIterator<'a, T, M>
308where
309 T: Triangulation,
310 M: DistanceMetric<<T::Vertex as HasPosition>::Scalar>,
311{
312 pub fn new(
313 t: &'a T,
314 metric: M,
315 start_point: Point2<<T::Vertex as HasPosition>::Scalar>,
316 ) -> Self {
317 let start_edges = Self::get_start_edges(t, &metric, start_point);
318 let already_visited = start_edges
319 .iter()
320 .map(|edge| t.directed_edge(*edge).from().fix())
321 .collect();
322
323 Self {
324 t,
325 edge_loop: start_edges.into(),
326 pending: None,
327 already_visited,
328 metric,
329 }
330 }
331
332 #[allow(clippy::type_complexity)]
333 fn get_start_edges(
334 t: &'a T,
335 metric: &M,
336 start_point: Point2<<T::Vertex as HasPosition>::Scalar>,
337 ) -> Vec<FixedDirectedEdgeHandle> {
338 use crate::PositionInTriangulation::*;
339 if !metric.is_point_inside(start_point) {
340 return Vec::new();
342 }
343
344 if t.all_vertices_on_line() {
345 return t
346 .undirected_edges()
347 .filter(|edge| metric.is_handle_inside(*edge))
348 .flat_map(|edge| [edge.as_directed().fix(), edge.as_directed().rev().fix()])
349 .collect();
350 }
351
352 let start_face = match t.locate(start_point) {
353 OnVertex(point) => t
354 .vertex(point)
355 .out_edges()
356 .flat_map(|edge| edge.face().as_inner())
357 .next(),
358 OnEdge(edge) => {
359 let edge = t.directed_edge(edge);
360 edge.face()
361 .as_inner()
362 .or_else(|| edge.rev().face().as_inner())
363 }
364 OnFace(face) => Some(t.face(face)),
365 OutsideOfConvexHull(edge) => {
366 let mut current_edge = t.directed_edge(edge);
370 let [from_distance, to_distance] = current_edge
371 .positions()
372 .map(|p| metric.distance_to_point(p));
373 let walk_forward;
374 let mut min_distance;
375 if from_distance > to_distance {
376 walk_forward = true;
377 min_distance = to_distance;
378 } else {
379 walk_forward = false;
380 min_distance = from_distance;
381 }
382
383 loop {
384 if metric.is_handle_inside(current_edge.as_undirected()) {
385 break current_edge.rev().face().as_inner();
386 }
387
388 let next_distance = if walk_forward {
389 current_edge = current_edge.next();
390 metric.distance_to_point(current_edge.to().position())
391 } else {
392 current_edge = current_edge.prev();
393 metric.distance_to_point(current_edge.from().position())
394 };
395
396 if next_distance > min_distance {
397 break None;
400 }
401
402 min_distance = next_distance;
403 }
404 }
405 NoTriangulation => None,
406 };
407
408 start_face
409 .into_iter()
410 .flat_map(|face| face.adjacent_edges().into_iter().rev())
411 .map(|edge| edge.fix().rev())
412 .collect()
413 }
414}
415
416impl<'a, T, M> FloodFillIterator<'a, T, M>
417where
418 T: Triangulation,
419 M: DistanceMetric<<T::Vertex as HasPosition>::Scalar>,
420{
421 #[allow(clippy::type_complexity)]
463 fn next(
464 &mut self,
465 ) -> Option<(
466 DirectedEdgeHandle<'a, T::Vertex, T::DirectedEdge, T::UndirectedEdge, T::Face>,
467 Option<VertexHandle<'a, T::Vertex, T::DirectedEdge, T::UndirectedEdge, T::Face>>,
468 )> {
469 if let Some(pending) = self.pending.take() {
470 let pending = self.t.directed_edge(pending);
471 if self.metric.is_handle_inside(pending.as_undirected()) {
472 return Some((pending, None));
473 }
474 }
475
476 while let Some(next) = self.edge_loop.pop_front() {
477 let next = self.t.directed_edge(next);
478
479 if !self.metric.is_handle_inside(next.as_undirected()) {
480 continue;
481 }
482
483 if self.edge_loop.front() == Some(&next.rev().fix()) {
493 self.edge_loop.pop_front();
494 return Some((next, None));
495 }
496
497 if self.edge_loop.back() == Some(&next.rev().fix()) {
499 self.edge_loop.pop_back();
500 return Some((next, None));
501 }
502
503 if next.is_outer_edge() {
504 return Some((next, None));
505 }
506
507 let new_edge_1 = next.prev().rev();
509 let new_edge_2 = next.next().rev();
510
511 let first = self.edge_loop.front().copied();
512 if first == Some(next.next().fix()) {
513 self.already_visited.remove(&next.to().fix());
518 self.pending = self.edge_loop.pop_front();
519 self.edge_loop.push_front(new_edge_1.fix());
520 return Some((next, None));
521 }
522
523 let last = self.edge_loop.back().copied();
524 if last == Some(next.prev().fix()) {
525 self.already_visited.remove(&next.from().fix());
527 self.pending = self.edge_loop.pop_back();
528 self.edge_loop.push_back(next.next().rev().fix());
529 return Some((next, None));
530 }
531
532 let new_vertex = new_edge_1.to();
535 if !self.already_visited.insert(new_vertex.fix()) {
536 let is_e1_inside = self.metric.is_handle_inside(new_edge_1.as_undirected());
537 let is_e2_inside = self.metric.is_handle_inside(new_edge_2.as_undirected());
538
539 match (is_e1_inside, is_e2_inside) {
540 (true, true) => {
541 self.edge_loop.push_back(next.fix());
542 continue;
543 }
544 (true, false) => self.edge_loop.push_back(new_edge_1.fix()),
545 (false, true) => self.edge_loop.push_back(new_edge_2.fix()),
546 (false, false) => {}
547 }
548 } else {
549 self.edge_loop.push_back(new_edge_1.fix());
550 self.edge_loop.push_back(new_edge_2.fix());
551 return Some((next, Some(new_vertex)));
552 }
553
554 return Some((next, None));
555 }
556 None
557 }
558}
559
560#[cfg(test)]
561mod test {
562
563 use alloc::{vec, vec::Vec};
564
565 use crate::{
566 flood_fill_iterator::{CircleMetric, DistanceMetric, RectangleMetric},
567 test_utilities::random_points_with_seed,
568 ConstrainedDelaunayTriangulation, DelaunayTriangulation, FloatTriangulation,
569 InsertionError, Point2, Triangulation,
570 };
571
572 use super::get_edge_intersections;
573
574 #[test]
575 fn test_empty() {
576 let d = DelaunayTriangulation::<Point2<_>>::default();
577 let edges = d.get_edges_in_rectangle(Point2::new(-1.0, -2.0), Point2::new(2.0, 2.0));
578 assert_eq!(edges.count(), 0);
579 }
580
581 #[test]
582 fn test_single_vertex() -> Result<(), InsertionError> {
583 let mut d = DelaunayTriangulation::<Point2<f64>>::default();
584 d.insert(Point2::new(0.2, 1.0))?;
585 test_rectangle_iterator(&d);
586 Ok(())
587 }
588
589 #[test]
590 fn test_single_face() -> Result<(), InsertionError> {
591 let vertices = vec![
592 Point2::new(3.0, 2.0),
593 Point2::new(-2.0, 1.0),
594 Point2::new(-3.0, -4.0),
595 ];
596 let d = DelaunayTriangulation::<_>::bulk_load(vertices)?;
597 test_rectangle_iterator(&d);
598 Ok(())
599 }
600
601 #[test]
602 fn test_rectangle_center_on_vertex() -> Result<(), InsertionError> {
603 let vertices = vec![
604 Point2::new(3.0, 2.0),
605 Point2::new(0.0, 0.0),
606 Point2::new(-2.0, 1.0),
607 Point2::new(-3.0, -4.0),
608 ];
609 let d = DelaunayTriangulation::<_>::bulk_load(vertices)?;
610 test_rectangle_iterator(&d);
611 Ok(())
612 }
613
614 #[test]
615 fn test_small() -> Result<(), InsertionError> {
616 let vertices = vec![
617 Point2::new(3.0, 2.0),
618 Point2::new(-2.0, 1.0),
619 Point2::new(2.0, 1.0),
620 Point2::new(1.0, -4.0),
621 ];
622 let d = DelaunayTriangulation::<_>::bulk_load(vertices)?;
623 let edges = d.get_edges_in_rectangle(Point2::new(-10.0, -10.0), Point2::new(10.0, 10.0));
624 assert_eq!(edges.count(), d.num_undirected_edges());
625
626 Ok(())
627 }
628
629 #[test]
630 fn test_random() -> Result<(), InsertionError> {
631 for size in [4, 52, 122] {
632 let vertices = random_points_with_seed(size, crate::test_utilities::SEED);
633 let d = DelaunayTriangulation::<_>::bulk_load(vertices.clone())?;
634 test_rectangle_iterator(&d);
635 let mut c = ConstrainedDelaunayTriangulation::<_>::bulk_load(vertices)?;
636 let constraints = random_points_with_seed(size, crate::test_utilities::SEED2);
637
638 for points in constraints.as_slice().chunks_exact(2) {
639 let from = c.insert(points[0])?;
640 let to = c.insert(points[1])?;
641 if c.can_add_constraint(from, to) {
642 c.add_constraint(from, to);
643 }
644 }
645 test_rectangle_iterator(&c);
646 }
647 Ok(())
648 }
649
650 fn test_rectangle_iterator(d: &impl Triangulation<Vertex = Point2<f64>>) {
651 let areas = [
652 (Point2::new(-10.0, -10.0), Point2::new(10.0, 10.0)),
653 (Point2::new(-2.0, -2.0), Point2::new(-0.1, -0.1)),
654 (Point2::new(-0.5, -0.5), Point2::new(0.5, 0.5)),
655 (Point2::new(-0.1, -10.), Point2::new(0.1, 10.)),
656 (Point2::new(-5.0, -0.1), Point2::new(5.0, 0.1)),
657 (Point2::new(-0.9, -0.9), Point2::new(0.9, 0.9)),
658 (Point2::new(0.0, 0.0), Point2::new(0.0, 0.0)),
659 (Point2::new(20.1, 20.1), Point2::new(10.0, 10.0)),
660 (Point2::new(-2.0, -2.0), Point2::new(0.0, 0.0)),
661 (Point2::new(-2.0, 0.0), Point2::new(0.0, 2.0)),
662 (Point2::new(0.0, 0.0), Point2::new(2.0, 2.0)),
663 (Point2::new(-2.0, -2.0), Point2::new(-1.0, -1.0)),
664 (Point2::new(-2.0, -2.0), Point2::new(-1.0, -0.5)),
665 (Point2::new(-2.0, -2.0), Point2::new(-1.0, 0.0)),
666 ];
667
668 for (lower, upper) in areas {
669 let rectangle_metric = RectangleMetric::new(lower, upper);
670
671 let edges = d.get_edges_in_rectangle(lower, upper);
673 let expected_count = d
674 .undirected_edges()
675 .filter(|edge| rectangle_metric.is_handle_inside(*edge))
676 .count();
677
678 assert_eq!(edges.count(), expected_count);
679
680 let center = lower.add(upper).mul(0.5);
681 let radius = (upper.x - lower.x).max(upper.y - lower.y);
682 let radius_2 = radius * radius;
683 let circle_metric = CircleMetric::new(center, radius_2);
684
685 let edges = d.get_edges_in_circle(center, radius_2);
686 let expected_count = d
687 .undirected_edges()
688 .filter(|edge| circle_metric.is_handle_inside(*edge))
689 .count();
690
691 assert_eq!(edges.count(), expected_count);
692
693 let vertices = d.get_vertices_in_rectangle(lower, upper);
695 let expected = d
696 .vertices()
697 .filter(|vertex| rectangle_metric.is_point_inside(vertex.position()))
698 .count();
699 assert_eq!(vertices.count(), expected);
700
701 let vertices = d.get_vertices_in_circle(center, radius_2);
702 let expected = d
703 .vertices()
704 .filter(|vertex| vertex.position().distance_2(center) <= radius_2)
705 .count();
706
707 assert_eq!(vertices.count(), expected);
708 }
709 }
710
711 #[test]
712 fn test_medium_triangulation() -> Result<(), InsertionError> {
713 let vertices = vec![
714 Point2::new(-7., -5.5),
715 Point2::new(-4., -6.5),
716 Point2::new(-5., -9.),
717 Point2::new(-6., 6.),
718 Point2::new(-8., -6.),
719 Point2::new(3., 3.),
720 ];
721 let d = DelaunayTriangulation::<_>::bulk_load(vertices)?;
722 test_rectangle_iterator(&d);
723 Ok(())
724 }
725
726 #[test]
727 fn test_convex_hull_edge_cases() -> Result<(), InsertionError> {
728 let coords = [-1.0f64, 0.1, 1.0];
729 let mut vertices = Vec::new();
730 for x in &coords {
731 for y in &coords {
732 vertices.push(Point2::new(*x, *y));
733 }
734 }
735 let d = DelaunayTriangulation::<_>::bulk_load(vertices)?;
736 test_rectangle_iterator(&d);
737 Ok(())
738 }
739
740 #[test]
741 fn test_degenerate() -> Result<(), InsertionError> {
742 let vertices = vec![Point2::new(0.0, 0.0), Point2::new(1.0, 0.5)];
743 let d = DelaunayTriangulation::<_>::bulk_load(vertices)?;
744 test_rectangle_iterator(&d);
745
746 let vertices = vec![
747 Point2::new(0.0, 0.0),
748 Point2::new(1.0, 0.5),
749 Point2::new(2.0, 1.0),
750 Point2::new(4.0, 2.0),
751 ];
752 let d = DelaunayTriangulation::<_>::bulk_load(vertices)?;
753 test_rectangle_iterator(&d);
754
755 Ok(())
756 }
757
758 #[test]
759 fn test_edge_intersections() {
760 let sut = get_edge_intersections;
761 let v0 = Point2::new(0.0, 0.0);
762 let v1 = Point2::new(2.0, 0.0);
763
764 let [s0, s1] = sut(v0, v1, Point2::new(1.0f64, 1.0), Point2::new(1.0, -1.0));
765 assert_eq!(s0, 0.5);
766 assert_eq!(s1, 0.5);
767
768 let [s0, s1] = sut(v0, v1, Point2::new(0.5, 1.0), Point2::new(0.5, -1.0));
769 assert_eq!(s0, 0.25);
770 assert_eq!(s1, 0.5);
771
772 let [s0, s1] = sut(v0, v1, v0, v1);
773 assert!(s0.is_infinite());
774 assert!(s1.is_infinite());
775
776 let [s0, s1] = sut(v0, v1, Point2::new(1.0, 0.0), Point2::new(20.0, 0.0));
777 assert!(s0.is_infinite());
778 assert!(s1.is_infinite());
779
780 let [s0, s1] = sut(v0, v1, Point2::new(1.0, 3.0), Point2::new(20.0, 3.0));
781 assert!(s0.is_infinite());
782 assert!(s1.is_infinite());
783 }
784
785 #[test]
786 fn test_is_edge_inside() {
787 fn check(from: Point2<f64>, to: Point2<f64>, expected: bool) {
788 let metric = RectangleMetric::new(Point2::new(-1.0, -1.0), Point2::new(1.0, 1.0));
789 assert_eq!(metric.is_edge_inside([from, to]), expected);
790 assert_eq!(metric.is_edge_inside([to, from]), expected);
791 }
792
793 check(Point2::new(0.0, 0.0), Point2::new(2.0, 3.0), true);
794 check(Point2::new(-2.0, -3.0), Point2::new(2.0, 4.0), true);
795 check(Point2::new(-2.0, 0.5), Point2::new(2.0, 0.5), true);
796
797 check(Point2::new(-0.25, -0.25), Point2::new(0.1, 0.1), true);
798
799 check(Point2::new(-0.25, -0.25), Point2::new(1.0, 1.0), true);
800 check(Point2::new(-1.0, -1.0), Point2::new(0.5, 1.0), true);
801
802 check(Point2::new(-1.0, -1.0), Point2::new(1.0, 1.0), true);
803 check(Point2::new(-1.0, -1.0), Point2::new(2.0, 2.0), true);
804
805 check(Point2::new(1.0, 1.0), Point2::new(3.0, 4.0), true);
806
807 check(Point2::new(-1.0, -1.0), Point2::new(-2.0, 0.0), true);
808
809 check(Point2::new(-1.0, -1.0), Point2::new(-1.0, 1.0), true);
810 check(Point2::new(-1.0, -1.0), Point2::new(-1.0, 2.0), true);
811 check(Point2::new(-1.0, -2.0), Point2::new(-1.0, 2.0), true);
812 check(Point2::new(-2.0, -1.0), Point2::new(-0.5, -1.0), true);
813
814 check(Point2::new(-2.0, 2.0), Point2::new(3.0, -3.0), true);
815 check(Point2::new(-0.25, 0.25), Point2::new(-20.0, 20.0), true);
816
817 check(Point2::new(-2.0, 0.0), Point2::new(0.0, -2.0), true);
818
819 check(Point2::new(-2.0, -2.0), Point2::new(-1.0, -3.0), false);
820 check(Point2::new(-2.0, 0.0), Point2::new(0.0, -2.1), false);
821 check(Point2::new(-1.0, -2.0), Point2::new(1.0, -2.0), false);
822
823 check(Point2::new(-2.0, -1.0), Point2::new(-1.5, -1.0), false);
824 check(Point2::new(1.5, -1.0), Point2::new(2.0, -1.0), false);
825 }
826}