geo/algorithm/intersects/
polygon.rs

1use super::{has_disjoint_bboxes, Intersects};
2use crate::utils::{coord_pos_relative_to_ring, CoordPos};
3use crate::BoundingRect;
4use crate::{
5    Coord, CoordNum, GeoNum, Line, LineString, MultiLineString, MultiPolygon, Point, Polygon, Rect,
6};
7
8impl<T> Intersects<Coord<T>> for Polygon<T>
9where
10    T: GeoNum,
11{
12    fn intersects(&self, p: &Coord<T>) -> bool {
13        coord_pos_relative_to_ring(*p, self.exterior()) != CoordPos::Outside
14            && self
15                .interiors()
16                .iter()
17                .all(|int| coord_pos_relative_to_ring(*p, int) != CoordPos::Inside)
18    }
19}
20symmetric_intersects_impl!(Coord<T>, Polygon<T>);
21symmetric_intersects_impl!(Polygon<T>, Point<T>);
22
23impl<T> Intersects<Line<T>> for Polygon<T>
24where
25    T: GeoNum,
26{
27    fn intersects(&self, line: &Line<T>) -> bool {
28        self.exterior().intersects(line)
29            || self.interiors().iter().any(|inner| inner.intersects(line))
30            || self.intersects(&line.start)
31            || self.intersects(&line.end)
32    }
33}
34symmetric_intersects_impl!(Line<T>, Polygon<T>);
35symmetric_intersects_impl!(Polygon<T>, LineString<T>);
36symmetric_intersects_impl!(Polygon<T>, MultiLineString<T>);
37
38impl<T> Intersects<Rect<T>> for Polygon<T>
39where
40    T: GeoNum,
41{
42    fn intersects(&self, rect: &Rect<T>) -> bool {
43        self.intersects(&rect.to_polygon())
44    }
45}
46symmetric_intersects_impl!(Rect<T>, Polygon<T>);
47
48impl<T> Intersects<Polygon<T>> for Polygon<T>
49where
50    T: GeoNum,
51{
52    fn intersects(&self, polygon: &Polygon<T>) -> bool {
53        if has_disjoint_bboxes(self, polygon) {
54            return false;
55        }
56
57        // self intersects (or contains) any line in polygon
58        self.intersects(polygon.exterior()) ||
59            polygon.interiors().iter().any(|inner_line_string| self.intersects(inner_line_string)) ||
60            // self is contained inside polygon
61            polygon.intersects(self.exterior())
62    }
63}
64
65// Implementations for MultiPolygon
66
67impl<G, T> Intersects<G> for MultiPolygon<T>
68where
69    T: GeoNum,
70    Polygon<T>: Intersects<G>,
71    G: BoundingRect<T>,
72{
73    fn intersects(&self, rhs: &G) -> bool {
74        if has_disjoint_bboxes(self, rhs) {
75            return false;
76        }
77        self.iter().any(|p| p.intersects(rhs))
78    }
79}
80
81symmetric_intersects_impl!(Point<T>, MultiPolygon<T>);
82symmetric_intersects_impl!(Line<T>, MultiPolygon<T>);
83symmetric_intersects_impl!(Rect<T>, MultiPolygon<T>);
84symmetric_intersects_impl!(Polygon<T>, MultiPolygon<T>);
85
86#[cfg(test)]
87mod tests {
88    use crate::*;
89    #[test]
90    fn geom_intersects_geom() {
91        let a = Geometry::<f64>::from(polygon![]);
92        let b = Geometry::from(polygon![]);
93        assert!(!a.intersects(&b));
94    }
95}