1use geometry_strategy::intersects::Reversed;
11use geometry_strategy::{CartesianIntersects, IntersectsStrategy};
12
13#[inline]
21#[must_use]
22pub fn intersects<A, B>(a: &A, b: &B) -> bool
23where
24 CartesianIntersects: IntersectsStrategy<A, B>,
25{
26 CartesianIntersects.intersects(a, b)
27}
28
29#[inline]
33#[must_use]
34pub fn intersects_reversed<A, B>(a: &A, b: &B) -> bool
35where
36 Reversed<CartesianIntersects>: IntersectsStrategy<A, B>,
37{
38 Reversed(CartesianIntersects).intersects(a, b)
39}
40
41#[cfg(test)]
42mod tests {
43 use super::intersects;
48 use geometry_cs::Cartesian;
49 use geometry_model::{Linestring, Point2D, Polygon, Segment, linestring, polygon};
50
51 type P = Point2D<f64, Cartesian>;
52 type LS = Linestring<P>;
53
54 fn pt(x: f64, y: f64) -> P {
55 Point2D::new(x, y)
56 }
57
58 #[test]
60 fn ls_crosses_segment() {
61 let ls: LS = linestring![(1.0, 1.0), (3.0, 3.0), (2.0, 5.0)];
62 let s = Segment::new(pt(2.0, 0.0), pt(2.0, 6.0));
63 assert!(intersects(&ls, &s));
64 }
65
66 #[test]
68 fn ls_touches_segment_endpoint() {
69 let ls: LS = linestring![(1.0, 1.0), (3.0, 3.0)];
70 let s = Segment::new(pt(1.0, 0.0), pt(1.0, 1.0));
71 assert!(intersects(&ls, &s));
72 }
73
74 #[test]
76 fn ls_disjoint_from_segment() {
77 let ls: LS = linestring![(1.0, 1.0), (3.0, 3.0)];
78 let s = Segment::new(pt(3.0, 0.0), pt(4.0, 1.0));
79 assert!(!intersects(&ls, &s));
80 }
81
82 #[test]
84 fn ls_crosses_ls() {
85 let a: LS = linestring![(0.0, 0.0), (2.0, 0.0), (3.0, 0.0)];
86 let b: LS = linestring![(0.0, 0.0), (1.0, 1.0), (2.0, 2.0)];
87 assert!(intersects(&a, &b));
88 }
89
90 #[test]
92 fn ls_overlap_collinear() {
93 let a: LS = linestring![(0.0, 0.0), (2.0, 0.0), (3.0, 0.0)];
94 let b: LS = linestring![(1.0, 0.0), (4.0, 0.0), (5.0, 0.0)];
95 assert!(intersects(&a, &b));
96 }
97
98 #[test]
100 fn ls_inside_polygon() {
101 let ls: LS = linestring![(1.0, 1.0), (2.0, 2.0)];
102 let p: Polygon<P> = polygon![[
103 (0.0, 0.0),
104 (10.0, 0.0),
105 (10.0, 10.0),
106 (0.0, 10.0),
107 (0.0, 0.0)
108 ]];
109 assert!(intersects(&ls, &p));
110 }
111
112 #[test]
114 fn ls_outside_polygon() {
115 let ls: LS = linestring![(11.0, 0.0), (12.0, 12.0)];
116 let p: Polygon<P> = polygon![[
117 (0.0, 0.0),
118 (10.0, 0.0),
119 (10.0, 10.0),
120 (0.0, 10.0),
121 (0.0, 0.0)
122 ]];
123 assert!(!intersects(&ls, &p));
124 }
125
126 #[test]
130 fn reversed_pair_agrees() {
131 let ls: LS = linestring![(1.0, 1.0), (2.0, 2.0)];
132 let p: Polygon<P> = polygon![[
133 (0.0, 0.0),
134 (10.0, 0.0),
135 (10.0, 10.0),
136 (0.0, 10.0),
137 (0.0, 0.0)
138 ]];
139 assert_eq!(intersects(&ls, &p), intersects(&p, &ls));
140 }
141
142 fn square(shift: f64) -> Polygon<P> {
143 polygon![[
144 (shift, shift),
145 (shift + 4.0, shift),
146 (shift + 4.0, shift + 4.0),
147 (shift, shift + 4.0),
148 (shift, shift)
149 ]]
150 }
151
152 #[test]
154 fn point_point_intersects_iff_equal() {
155 assert!(intersects(&pt(1.0, 2.0), &pt(1.0, 2.0)));
156 assert!(!intersects(&pt(1.0, 2.0), &pt(1.0, 2.5)));
157 }
158
159 #[test]
162 fn point_segment_membership() {
163 let s = Segment::new(pt(0.0, 0.0), pt(4.0, 4.0));
164 assert!(intersects(&pt(2.0, 2.0), &s)); assert!(intersects(&pt(0.0, 0.0), &s)); assert!(!intersects(&pt(2.0, 3.0), &s)); assert!(!intersects(&pt(5.0, 5.0), &s)); }
169
170 #[test]
173 fn segment_segment_crossing_and_parallel() {
174 let a = Segment::new(pt(0.0, 0.0), pt(4.0, 4.0));
175 let cross = Segment::new(pt(0.0, 4.0), pt(4.0, 0.0));
176 let parallel = Segment::new(pt(0.0, 1.0), pt(4.0, 5.0));
177 assert!(intersects(&a, &cross));
178 assert!(!intersects(&a, ¶llel));
179 }
180
181 #[test]
184 fn empty_linestring_operands_do_not_intersect() {
185 let empty: LS = linestring![];
186 let s = Segment::new(pt(0.0, 0.0), pt(1.0, 1.0));
187 assert!(!intersects(&empty, &s));
188
189 let non_empty: LS = linestring![(0.0, 0.0), (1.0, 1.0)];
190 assert!(!intersects(&empty, &non_empty));
191 assert!(!intersects(&non_empty, &empty));
192 }
193
194 #[test]
197 fn point_polygon_is_covered_by() {
198 let sq = square(0.0);
199 assert!(intersects(&pt(2.0, 2.0), &sq)); assert!(intersects(&pt(0.0, 2.0), &sq)); assert!(!intersects(&pt(9.0, 9.0), &sq)); }
203
204 #[test]
207 fn polygon_polygon_containment_crossing_disjoint() {
208 let a = square(0.0); let contained: Polygon<P> =
210 polygon![[(1.0, 1.0), (2.0, 1.0), (2.0, 2.0), (1.0, 2.0), (1.0, 1.0)]];
211 let overlapping = square(2.0); let disjoint = square(100.0);
213
214 assert!(intersects(&a, &contained)); assert!(intersects(&contained, &a)); assert!(intersects(&a, &overlapping)); assert!(!intersects(&a, &disjoint)); }
219
220 #[test]
223 fn polygon_polygon_hole_edges_are_tested() {
224 let a: Polygon<P> = polygon![
226 [
227 (0.0, 0.0),
228 (10.0, 0.0),
229 (10.0, 10.0),
230 (0.0, 10.0),
231 (0.0, 0.0)
232 ],
233 [(2.0, 2.0), (6.0, 2.0), (6.0, 6.0), (2.0, 6.0), (2.0, 2.0)]
234 ];
235 let b: Polygon<P> = polygon![[(4.0, 4.0), (8.0, 4.0), (8.0, 8.0), (4.0, 8.0), (4.0, 4.0)]];
237 assert!(intersects(&a, &b));
238 }
239
240 #[test]
243 fn reverse_pairs_delegate_to_forward() {
244 let s = Segment::new(pt(0.0, 0.0), pt(4.0, 4.0));
245 let p = pt(2.0, 2.0);
246 assert_eq!(intersects(&s, &p), intersects(&p, &s));
247
248 let ls: LS = linestring![(1.0, 1.0), (3.0, 3.0), (2.0, 5.0)];
249 assert_eq!(intersects(&s, &ls), intersects(&ls, &s));
250
251 let sq = square(0.0);
252 assert_eq!(intersects(&sq, &p), intersects(&p, &sq));
253
254 let ls_in: LS = linestring![(1.0, 1.0), (2.0, 2.0)];
255 assert_eq!(intersects(&sq, &ls_in), intersects(&ls_in, &sq));
256 assert!(intersects(&s, &p));
258 assert!(intersects(&sq, &p));
259 assert!(intersects(&sq, &ls_in));
260 }
261
262 #[test]
265 fn point_point_intersects_in_three_dimensions() {
266 use geometry_model::Point3D;
267 type P3 = Point3D<f64, Cartesian>;
268 let a = P3::new(1.0, 2.0, 3.0);
269 let same = P3::new(1.0, 2.0, 3.0);
270 let diff_z = P3::new(1.0, 2.0, 9.0);
271 assert!(intersects(&a, &same));
272 assert!(!intersects(&a, &diff_z));
273 }
274
275 #[test]
278 fn linestring_polygon_inside_via_vertex_path() {
279 let ls: LS = linestring![(1.0, 1.0), (2.0, 2.0)];
280 assert!(intersects(&ls, &square(0.0)));
281 }
282}