1use crate::BoundingRect;
2use crate::*;
3
4pub trait Intersects<Rhs = Self> {
40 fn intersects(&self, rhs: &Rhs) -> bool;
41}
42
43macro_rules! symmetric_intersects_impl {
54 ($t:ty, $k:ty) => {
55 impl<T> $crate::Intersects<$k> for $t
56 where
57 $k: $crate::Intersects<$t>,
58 T: CoordNum,
59 {
60 fn intersects(&self, rhs: &$k) -> bool {
61 rhs.intersects(self)
62 }
63 }
64 };
65}
66
67mod collections;
68mod coordinate;
69mod line;
70mod line_string;
71mod point;
72mod polygon;
73mod rect;
74mod triangle;
75
76#[inline]
79fn value_in_range<T>(value: T, min: T, max: T) -> bool
80where
81 T: std::cmp::PartialOrd,
82{
83 value >= min && value <= max
84}
85
86#[inline]
89fn value_in_between<T>(value: T, bound_1: T, bound_2: T) -> bool
90where
91 T: std::cmp::PartialOrd,
92{
93 if bound_1 < bound_2 {
94 value_in_range(value, bound_1, bound_2)
95 } else {
96 value_in_range(value, bound_2, bound_1)
97 }
98}
99
100#[inline]
103pub(crate) fn point_in_rect<T>(value: Coord<T>, bound_1: Coord<T>, bound_2: Coord<T>) -> bool
104where
105 T: CoordNum,
106{
107 value_in_between(value.x, bound_1.x, bound_2.x)
108 && value_in_between(value.y, bound_1.y, bound_2.y)
109}
110
111fn has_disjoint_bboxes<T, A, B>(a: &A, b: &B) -> bool
113where
114 T: CoordNum,
115 A: BoundingRect<T>,
116 B: BoundingRect<T>,
117{
118 let mut disjoint_bbox = false;
119 if let Some(a_bbox) = a.bounding_rect().into() {
120 if let Some(b_bbox) = b.bounding_rect().into() {
121 if !a_bbox.intersects(&b_bbox) {
122 disjoint_bbox = true;
123 }
124 }
125 }
126 disjoint_bbox
127}
128
129#[cfg(test)]
130mod test {
131 use crate::Intersects;
132 use crate::{
133 coord, line_string, polygon, Geometry, Line, LineString, MultiLineString, MultiPoint,
134 MultiPolygon, Point, Polygon, Rect,
135 };
136
137 #[test]
139 fn empty_linestring1_test() {
140 let linestring = line_string![(x: 3., y: 2.), (x: 7., y: 6.)];
141 assert!(!line_string![].intersects(&linestring));
142 }
143 #[test]
144 fn empty_linestring2_test() {
145 let linestring = line_string![(x: 3., y: 2.), (x: 7., y: 6.)];
146 assert!(!linestring.intersects(&LineString::new(Vec::new())));
147 }
148 #[test]
149 fn empty_all_linestring_test() {
150 let empty: LineString = line_string![];
151 assert!(!empty.intersects(&empty));
152 }
153 #[test]
154 fn intersect_linestring_test() {
155 let ls1 = line_string![(x: 3., y: 2.), (x: 7., y: 6.)];
156 let ls2 = line_string![(x: 3., y: 4.), (x: 8., y: 4.)];
157 assert!(ls1.intersects(&ls2));
158 }
159 #[test]
160 fn parallel_linestrings_test() {
161 let ls1 = line_string![(x: 3., y: 2.), (x: 7., y: 6.)];
162 let ls2 = line_string![(x: 3., y: 1.), (x: 7., y: 5.)];
163 assert!(!ls1.intersects(&ls2));
164 }
165 #[test]
167 fn linestring_in_polygon_test() {
168 let poly = polygon![
169 (x: 0., y: 0.),
170 (x: 5., y: 0.),
171 (x: 5., y: 6.),
172 (x: 0., y: 6.),
173 (x: 0., y: 0.),
174 ];
175 let ls = line_string![(x: 2., y: 2.), (x: 3., y: 3.)];
176 assert!(poly.intersects(&ls));
177 }
178 #[test]
179 fn linestring_on_boundary_polygon_test() {
180 let poly = Polygon::new(
181 LineString::from(vec![(0., 0.), (5., 0.), (5., 6.), (0., 6.), (0., 0.)]),
182 Vec::new(),
183 );
184 assert!(poly.intersects(&LineString::from(vec![(0., 0.), (5., 0.)])));
185 assert!(poly.intersects(&LineString::from(vec![(5., 0.), (5., 6.)])));
186 assert!(poly.intersects(&LineString::from(vec![(5., 6.), (0., 6.)])));
187 assert!(poly.intersects(&LineString::from(vec![(0., 6.), (0., 0.)])));
188 }
189 #[test]
190 fn intersect_linestring_polygon_test() {
191 let poly = Polygon::new(
192 LineString::from(vec![(0., 0.), (5., 0.), (5., 6.), (0., 6.), (0., 0.)]),
193 Vec::new(),
194 );
195 assert!(poly.intersects(&LineString::from(vec![(2., 2.), (6., 6.)])));
196 }
197 #[test]
198 fn linestring_outside_polygon_test() {
199 let poly = Polygon::new(
200 LineString::from(vec![(0., 0.), (5., 0.), (5., 6.), (0., 6.), (0., 0.)]),
201 Vec::new(),
202 );
203 assert!(!poly.intersects(&LineString::from(vec![(7., 2.), (9., 4.)])));
204 }
205 #[test]
206 fn linestring_in_inner_polygon_test() {
207 let e = LineString::from(vec![(0., 0.), (5., 0.), (5., 6.), (0., 6.), (0., 0.)]);
208 let v = vec![LineString::from(vec![
209 (1., 1.),
210 (4., 1.),
211 (4., 4.),
212 (1., 4.),
213 (1., 1.),
214 ])];
215 let poly = Polygon::new(e, v);
216 assert!(!poly.intersects(&LineString::from(vec![(2., 2.), (3., 3.)])));
217 assert!(poly.intersects(&LineString::from(vec![(2., 2.), (4., 4.)])));
218 }
219 #[test]
220 fn linestring_traverse_polygon_test() {
221 let e = LineString::from(vec![(0., 0.), (5., 0.), (5., 6.), (0., 6.), (0., 0.)]);
222 let v = vec![LineString::from(vec![
223 (1., 1.),
224 (4., 1.),
225 (4., 4.),
226 (1., 4.),
227 (1., 1.),
228 ])];
229 let poly = Polygon::new(e, v);
230 assert!(poly.intersects(&LineString::from(vec![(2., 0.5), (2., 5.)])));
231 }
232 #[test]
233 fn linestring_in_inner_with_2_inner_polygon_test() {
234 let e = LineString::from(vec![(2., 2.), (14., 2.), (14., 8.), (2., 8.), (2., 2.)]);
258 let v = vec![
259 LineString::from(vec![(4., 3.), (7., 3.), (7., 6.), (4., 6.), (4., 3.)]),
260 LineString::from(vec![(9., 3.), (12., 3.), (12., 6.), (9., 6.), (9., 3.)]),
261 ];
262 let poly = Polygon::new(e, v);
263 assert!(!poly.intersects(&LineString::from(vec![(5., 4.), (6., 5.)])));
264 assert!(poly.intersects(&LineString::from(vec![(11., 2.5), (11., 7.)])));
265 assert!(poly.intersects(&LineString::from(vec![(4., 7.), (6., 7.)])));
266 assert!(poly.intersects(&LineString::from(vec![(8., 1.), (8., 9.)])));
267 }
268 #[test]
269 fn polygons_do_not_intersect() {
270 let p1 = Polygon::new(
271 LineString::from(vec![(1., 3.), (3., 3.), (3., 5.), (1., 5.), (1., 3.)]),
272 Vec::new(),
273 );
274 let p2 = Polygon::new(
275 LineString::from(vec![
276 (10., 30.),
277 (30., 30.),
278 (30., 50.),
279 (10., 50.),
280 (10., 30.),
281 ]),
282 Vec::new(),
283 );
284
285 assert!(!p1.intersects(&p2));
286 assert!(!p2.intersects(&p1));
287 }
288 #[test]
289 fn polygons_overlap() {
290 let p1 = Polygon::new(
291 LineString::from(vec![(1., 3.), (3., 3.), (3., 5.), (1., 5.), (1., 3.)]),
292 Vec::new(),
293 );
294 let p2 = Polygon::new(
295 LineString::from(vec![(2., 3.), (4., 3.), (4., 7.), (2., 7.), (2., 3.)]),
296 Vec::new(),
297 );
298
299 assert!(p1.intersects(&p2));
300 assert!(p2.intersects(&p1));
301 }
302 #[test]
303 fn polygon_contained() {
304 let p1 = Polygon::new(
305 LineString::from(vec![(1., 3.), (4., 3.), (4., 6.), (1., 6.), (1., 3.)]),
306 Vec::new(),
307 );
308 let p2 = Polygon::new(
309 LineString::from(vec![(2., 4.), (3., 4.), (3., 5.), (2., 5.), (2., 4.)]),
310 Vec::new(),
311 );
312
313 assert!(p1.intersects(&p2));
314 assert!(p2.intersects(&p1));
315 }
316 #[test]
317 fn polygons_conincident() {
318 let p1 = Polygon::new(
319 LineString::from(vec![(1., 3.), (4., 3.), (4., 6.), (1., 6.), (1., 3.)]),
320 Vec::new(),
321 );
322 let p2 = Polygon::new(
323 LineString::from(vec![(1., 3.), (4., 3.), (4., 6.), (1., 6.), (1., 3.)]),
324 Vec::new(),
325 );
326
327 assert!(p1.intersects(&p2));
328 assert!(p2.intersects(&p1));
329 }
330 #[test]
331 fn polygon_intersects_bounding_rect_test() {
332 let poly = Polygon::new(
352 LineString::from(vec![(0., 0.), (12., 0.), (12., 8.), (0., 8.), (0., 0.)]),
353 vec![LineString::from(vec![
354 (7., 4.),
355 (11., 4.),
356 (11., 7.),
357 (7., 7.),
358 (7., 4.),
359 ])],
360 );
361 let b1 = Rect::new(coord! { x: 11., y: 1. }, coord! { x: 13., y: 2. });
362 let b2 = Rect::new(coord! { x: 2., y: 2. }, coord! { x: 8., y: 5. });
363 let b3 = Rect::new(coord! { x: 8., y: 5. }, coord! { x: 10., y: 6. });
364 let b4 = Rect::new(coord! { x: 1., y: 1. }, coord! { x: 3., y: 3. });
365 assert!(poly.intersects(&b1));
367 assert!(poly.intersects(&b2));
369 assert!(!poly.intersects(&b3));
371 assert!(poly.intersects(&b4));
373 assert!(b1.intersects(&poly));
375 assert!(b2.intersects(&poly));
376 assert!(!b3.intersects(&poly));
377 assert!(b4.intersects(&poly));
378 }
379 #[test]
380 fn bounding_rect_test() {
381 let bounding_rect_xl =
382 Rect::new(coord! { x: -100., y: -200. }, coord! { x: 100., y: 200. });
383 let bounding_rect_sm = Rect::new(coord! { x: -10., y: -20. }, coord! { x: 10., y: 20. });
384 let bounding_rect_s2 = Rect::new(coord! { x: 0., y: 0. }, coord! { x: 20., y: 30. });
385 assert!(bounding_rect_xl.intersects(&bounding_rect_sm));
387 assert!(bounding_rect_sm.intersects(&bounding_rect_xl));
388 assert!(bounding_rect_sm.intersects(&bounding_rect_s2));
389 assert!(bounding_rect_s2.intersects(&bounding_rect_sm));
390 }
391 #[test]
392 fn rect_intersection_consistent_with_poly_intersection_test() {
393 let bounding_rect_xl =
394 Rect::new(coord! { x: -100., y: -200. }, coord! { x: 100., y: 200. });
395 let bounding_rect_sm = Rect::new(coord! { x: -10., y: -20. }, coord! { x: 10., y: 20. });
396 let bounding_rect_s2 = Rect::new(coord! { x: 0., y: 0. }, coord! { x: 20., y: 30. });
397
398 assert!(bounding_rect_xl.to_polygon().intersects(&bounding_rect_sm));
399 assert!(bounding_rect_xl.intersects(&bounding_rect_sm.to_polygon()));
400 assert!(bounding_rect_xl
401 .to_polygon()
402 .intersects(&bounding_rect_sm.to_polygon()));
403
404 assert!(bounding_rect_sm.to_polygon().intersects(&bounding_rect_xl));
405 assert!(bounding_rect_sm.intersects(&bounding_rect_xl.to_polygon()));
406 assert!(bounding_rect_sm
407 .to_polygon()
408 .intersects(&bounding_rect_xl.to_polygon()));
409
410 assert!(bounding_rect_sm.to_polygon().intersects(&bounding_rect_s2));
411 assert!(bounding_rect_sm.intersects(&bounding_rect_s2.to_polygon()));
412 assert!(bounding_rect_sm
413 .to_polygon()
414 .intersects(&bounding_rect_s2.to_polygon()));
415
416 assert!(bounding_rect_s2.to_polygon().intersects(&bounding_rect_sm));
417 assert!(bounding_rect_s2.intersects(&bounding_rect_sm.to_polygon()));
418 assert!(bounding_rect_s2
419 .to_polygon()
420 .intersects(&bounding_rect_sm.to_polygon()));
421 }
422 #[test]
423 fn point_intersects_line_test() {
424 let p0 = Point::new(2., 4.);
425 let line1 = Line::from([(2., 0.), (2., 5.)]);
427 let line2 = Line::from([(0., 6.), (1.5, 4.5)]);
429 let line3 = Line::from([(0., 6.), (3., 3.)]);
431 let line4 = Line::from([(1., 2.), (5., 3.)]);
433 let line5 = Line::from([(1., 5.), (5., 6.)]);
435 let line6 = Line::from([(1., 2.), (5., -3.)]);
437 let line7 = Line::from([(1., 6.), (5., 5.)]);
439 assert!(line1.intersects(&p0));
440 assert!(p0.intersects(&line1));
441 assert!(!line2.intersects(&p0));
442 assert!(!p0.intersects(&line2));
443 assert!(line3.intersects(&p0));
444 assert!(p0.intersects(&line3));
445 assert!(!line4.intersects(&p0));
446 assert!(!p0.intersects(&line4));
447 assert!(!line5.intersects(&p0));
448 assert!(!p0.intersects(&line5));
449 assert!(!line6.intersects(&p0));
450 assert!(!p0.intersects(&line6));
451 assert!(!line7.intersects(&p0));
452 assert!(!p0.intersects(&line7));
453 }
454 #[test]
455 fn line_intersects_line_test() {
456 let line0 = Line::from([(0., 0.), (3., 4.)]);
457 let line1 = Line::from([(2., 0.), (2., 5.)]);
458 let line2 = Line::from([(0., 7.), (5., 4.)]);
459 let line3 = Line::from([(0., 0.), (-3., -4.)]);
460 assert!(line0.intersects(&line0));
461 assert!(line0.intersects(&line1));
462 assert!(!line0.intersects(&line2));
463 assert!(line0.intersects(&line3));
464
465 assert!(line1.intersects(&line0));
466 assert!(line1.intersects(&line1));
467 assert!(!line1.intersects(&line2));
468 assert!(!line1.intersects(&line3));
469
470 assert!(!line2.intersects(&line0));
471 assert!(!line2.intersects(&line1));
472 assert!(line2.intersects(&line2));
473 assert!(!line1.intersects(&line3));
474 }
475 #[test]
476 fn line_intersects_linestring_test() {
477 let line0 = Line::from([(0., 0.), (3., 4.)]);
478 let linestring0 = LineString::from(vec![(0., 1.), (1., 0.), (2., 0.)]);
479 let linestring1 = LineString::from(vec![(0.5, 0.2), (1., 0.), (2., 0.)]);
480 assert!(line0.intersects(&linestring0));
481 assert!(!line0.intersects(&linestring1));
482 assert!(linestring0.intersects(&line0));
483 assert!(!linestring1.intersects(&line0));
484 }
485 #[test]
486 fn line_intersects_polygon_test() {
487 let line0 = Line::from([(0.5, 0.5), (2., 1.)]);
488 let poly0 = Polygon::new(
489 LineString::from(vec![(0., 0.), (1., 2.), (1., 0.), (0., 0.)]),
490 vec![],
491 );
492 let poly1 = Polygon::new(
493 LineString::from(vec![(1., -1.), (2., -1.), (2., -2.), (1., -1.)]),
494 vec![],
495 );
496 let poly2 = Polygon::new(
498 LineString::from(vec![(-1., -1.), (-1., 10.), (10., -1.), (-1., -1.)]),
499 vec![LineString::from(vec![
500 (0., 0.),
501 (3., 4.),
502 (3., 0.),
503 (0., 0.),
504 ])],
505 );
506 assert!(line0.intersects(&poly0));
507 assert!(poly0.intersects(&line0));
508
509 assert!(!line0.intersects(&poly1));
510 assert!(!poly1.intersects(&line0));
511
512 assert!(!line0.intersects(&poly2));
513 assert!(!poly2.intersects(&line0));
514 }
515 #[test]
516 fn rect_test_419() {
518 let a = Rect::new(
519 coord! {
520 x: 9.228515625,
521 y: 46.83013364044739,
522 },
523 coord! {
524 x: 9.2724609375,
525 y: 46.86019101567026,
526 },
527 );
528 let b = Rect::new(
529 coord! {
530 x: 9.17953,
531 y: 46.82018,
532 },
533 coord! {
534 x: 9.26309,
535 y: 46.88099,
536 },
537 );
538 assert!(a.intersects(&b));
539 assert!(b.intersects(&a));
540 }
541
542 #[test]
543 fn compile_test_geom_geom() {
544 let geom: Geometry<_> = Line::from([(0.5, 0.5), (2., 1.)]).into();
547 assert!(geom.intersects(&geom));
548 }
549
550 #[test]
551 fn exhaustive_compile_test() {
552 use geo_types::{GeometryCollection, Triangle};
553 let pt: Point = Point::new(0., 0.);
554 let ln: Line = Line::new((0., 0.), (1., 1.));
555 let ls = line_string![(0., 0.).into(), (1., 1.).into()];
556 let poly = Polygon::new(LineString::from(vec![(0., 0.), (1., 1.), (1., 0.)]), vec![]);
557 let rect = Rect::new(coord! { x: 10., y: 20. }, coord! { x: 30., y: 10. });
558 let tri = Triangle::new(
559 coord! { x: 0., y: 0. },
560 coord! { x: 10., y: 20. },
561 coord! { x: 20., y: -10. },
562 );
563 let geom = Geometry::Point(pt);
564 let gc = GeometryCollection::new_from(vec![geom.clone()]);
565 let multi_point = MultiPoint::new(vec![pt]);
566 let multi_ls = MultiLineString::new(vec![ls.clone()]);
567 let multi_poly = MultiPolygon::new(vec![poly.clone()]);
568
569 let _ = pt.intersects(&pt);
570 let _ = pt.intersects(&ln);
571 let _ = pt.intersects(&ls);
572 let _ = pt.intersects(&poly);
573 let _ = pt.intersects(&rect);
574 let _ = pt.intersects(&tri);
575 let _ = pt.intersects(&geom);
576 let _ = pt.intersects(&gc);
577 let _ = pt.intersects(&multi_point);
578 let _ = pt.intersects(&multi_ls);
579 let _ = pt.intersects(&multi_poly);
580 let _ = ln.intersects(&pt);
581 let _ = ln.intersects(&ln);
582 let _ = ln.intersects(&ls);
583 let _ = ln.intersects(&poly);
584 let _ = ln.intersects(&rect);
585 let _ = ln.intersects(&tri);
586 let _ = ln.intersects(&geom);
587 let _ = ln.intersects(&gc);
588 let _ = ln.intersects(&multi_point);
589 let _ = ln.intersects(&multi_ls);
590 let _ = ln.intersects(&multi_poly);
591 let _ = ls.intersects(&pt);
592 let _ = ls.intersects(&ln);
593 let _ = ls.intersects(&ls);
594 let _ = ls.intersects(&poly);
595 let _ = ls.intersects(&rect);
596 let _ = ls.intersects(&tri);
597 let _ = ls.intersects(&geom);
598 let _ = ls.intersects(&gc);
599 let _ = ls.intersects(&multi_point);
600 let _ = ls.intersects(&multi_ls);
601 let _ = ls.intersects(&multi_poly);
602 let _ = poly.intersects(&pt);
603 let _ = poly.intersects(&ln);
604 let _ = poly.intersects(&ls);
605 let _ = poly.intersects(&poly);
606 let _ = poly.intersects(&rect);
607 let _ = poly.intersects(&tri);
608 let _ = poly.intersects(&geom);
609 let _ = poly.intersects(&gc);
610 let _ = poly.intersects(&multi_point);
611 let _ = poly.intersects(&multi_ls);
612 let _ = poly.intersects(&multi_poly);
613 let _ = rect.intersects(&pt);
614 let _ = rect.intersects(&ln);
615 let _ = rect.intersects(&ls);
616 let _ = rect.intersects(&poly);
617 let _ = rect.intersects(&rect);
618 let _ = rect.intersects(&tri);
619 let _ = rect.intersects(&geom);
620 let _ = rect.intersects(&gc);
621 let _ = rect.intersects(&multi_point);
622 let _ = rect.intersects(&multi_ls);
623 let _ = rect.intersects(&multi_poly);
624 let _ = tri.intersects(&pt);
625 let _ = tri.intersects(&ln);
626 let _ = tri.intersects(&ls);
627 let _ = tri.intersects(&poly);
628 let _ = tri.intersects(&rect);
629 let _ = tri.intersects(&tri);
630 let _ = tri.intersects(&geom);
631 let _ = tri.intersects(&gc);
632 let _ = tri.intersects(&multi_point);
633 let _ = tri.intersects(&multi_ls);
634 let _ = tri.intersects(&multi_poly);
635 let _ = geom.intersects(&pt);
636 let _ = geom.intersects(&ln);
637 let _ = geom.intersects(&ls);
638 let _ = geom.intersects(&poly);
639 let _ = geom.intersects(&rect);
640 let _ = geom.intersects(&tri);
641 let _ = geom.intersects(&geom);
642 let _ = geom.intersects(&gc);
643 let _ = geom.intersects(&multi_point);
644 let _ = geom.intersects(&multi_ls);
645 let _ = geom.intersects(&multi_poly);
646 let _ = gc.intersects(&pt);
647 let _ = gc.intersects(&ln);
648 let _ = gc.intersects(&ls);
649 let _ = gc.intersects(&poly);
650 let _ = gc.intersects(&rect);
651 let _ = gc.intersects(&tri);
652 let _ = gc.intersects(&geom);
653 let _ = gc.intersects(&gc);
654 let _ = gc.intersects(&multi_point);
655 let _ = gc.intersects(&multi_ls);
656 let _ = gc.intersects(&multi_poly);
657 let _ = multi_point.intersects(&pt);
658 let _ = multi_point.intersects(&ln);
659 let _ = multi_point.intersects(&ls);
660 let _ = multi_point.intersects(&poly);
661 let _ = multi_point.intersects(&rect);
662 let _ = multi_point.intersects(&tri);
663 let _ = multi_point.intersects(&geom);
664 let _ = multi_point.intersects(&gc);
665 let _ = multi_point.intersects(&multi_point);
666 let _ = multi_point.intersects(&multi_ls);
667 let _ = multi_point.intersects(&multi_poly);
668 let _ = multi_ls.intersects(&pt);
669 let _ = multi_ls.intersects(&ln);
670 let _ = multi_ls.intersects(&ls);
671 let _ = multi_ls.intersects(&poly);
672 let _ = multi_ls.intersects(&rect);
673 let _ = multi_ls.intersects(&tri);
674 let _ = multi_ls.intersects(&geom);
675 let _ = multi_ls.intersects(&gc);
676 let _ = multi_ls.intersects(&multi_point);
677 let _ = multi_ls.intersects(&multi_ls);
678 let _ = multi_ls.intersects(&multi_poly);
679 let _ = multi_poly.intersects(&pt);
680 let _ = multi_poly.intersects(&ln);
681 let _ = multi_poly.intersects(&ls);
682 let _ = multi_poly.intersects(&poly);
683 let _ = multi_poly.intersects(&rect);
684 let _ = multi_poly.intersects(&tri);
685 let _ = multi_poly.intersects(&geom);
686 let _ = multi_poly.intersects(&gc);
687 let _ = multi_poly.intersects(&multi_point);
688 let _ = multi_poly.intersects(&multi_ls);
689 let _ = multi_poly.intersects(&multi_poly);
690 }
691}