1use geometry_coords::CoordinateScalar;
10use geometry_strategy::{CartesianIntersects, IntersectsStrategy};
11use geometry_trait::{Box as BoxTrait, Geometry, Point as PointTrait};
12
13#[inline]
18#[must_use]
19pub fn disjoint<A, B>(a: &A, b: &B) -> bool
20where
21 CartesianIntersects: IntersectsStrategy<A, B>,
22{
23 !CartesianIntersects.intersects(a, b)
24}
25
26#[inline]
54#[must_use]
55pub fn disjoint_box_box<A, B, T>(a: &A, b: &B) -> bool
56where
57 A: BoxTrait,
58 B: BoxTrait,
59 <A as Geometry>::Point: PointTrait<Scalar = T>,
60 <B as Geometry>::Point: PointTrait<Scalar = T>,
61 T: CoordinateScalar,
62{
63 let a_min_x = a.get_indexed::<0, 0>();
65 let a_min_y = a.get_indexed::<0, 1>();
66 let a_max_x = a.get_indexed::<1, 0>();
67 let a_max_y = a.get_indexed::<1, 1>();
68 let b_min_x = b.get_indexed::<0, 0>();
69 let b_min_y = b.get_indexed::<0, 1>();
70 let b_max_x = b.get_indexed::<1, 0>();
71 let b_max_y = b.get_indexed::<1, 1>();
72
73 a_max_x < b_min_x || b_max_x < a_min_x || a_max_y < b_min_y || b_max_y < a_min_y
74}
75
76#[cfg(test)]
77mod tests {
78 use super::disjoint;
79 use crate::intersects::intersects;
80 use geometry_cs::Cartesian;
81 use geometry_model::{Linestring, Point2D, linestring};
82
83 type P = Point2D<f64, Cartesian>;
84 type LS = Linestring<P>;
85
86 #[test]
87 fn disjoint_matches_negated_intersects() {
88 let a: LS = linestring![(0.0, 0.0), (2.0, 0.0)];
89 let b: LS = linestring![(10.0, 10.0), (11.0, 11.0)];
90 assert!(disjoint(&a, &b));
91 assert!(!intersects(&a, &b));
92 }
93
94 #[test]
95 fn disjoint_false_when_intersecting() {
96 let a: LS = linestring![(0.0, 0.0), (2.0, 0.0)];
97 let b: LS = linestring![(1.0, -1.0), (1.0, 1.0)];
98 assert!(!disjoint(&a, &b));
99 assert!(intersects(&a, &b));
100 }
101
102 #[test]
105 fn polygon_pair_disjointness() {
106 use geometry_model::{Polygon, polygon};
107 let a: Polygon<P> = polygon![[(0.0, 0.0), (4.0, 0.0), (4.0, 4.0), (0.0, 4.0), (0.0, 0.0)]];
108 let apart: Polygon<P> = polygon![[
109 (10.0, 10.0),
110 (14.0, 10.0),
111 (14.0, 14.0),
112 (10.0, 14.0),
113 (10.0, 10.0)
114 ]];
115 let overlapping: Polygon<P> =
116 polygon![[(2.0, 2.0), (6.0, 2.0), (6.0, 6.0), (2.0, 6.0), (2.0, 2.0)]];
117 assert!(disjoint(&a, &apart));
118 assert!(!disjoint(&a, &overlapping));
119 }
120
121 #[test]
122 fn box_box_fast_path() {
123 use crate::disjoint::disjoint_box_box;
124 use geometry_model::Box;
125
126 let a = Box::from_corners(P::new(0.0, 0.0), P::new(2.0, 2.0));
127 let right = Box::from_corners(P::new(5.0, 0.0), P::new(6.0, 2.0));
129 assert!(disjoint_box_box(&a, &right));
130 let above = Box::from_corners(P::new(0.0, 5.0), P::new(2.0, 6.0));
132 assert!(disjoint_box_box(&a, &above));
133 let over = Box::from_corners(P::new(1.0, 1.0), P::new(3.0, 3.0));
135 assert!(!disjoint_box_box(&a, &over));
136 let touch = Box::from_corners(P::new(2.0, 0.0), P::new(4.0, 2.0));
138 assert!(!disjoint_box_box(&a, &touch));
139 }
140}