geo/algorithm/contains/
line.rs

1use super::{impl_contains_from_relate, impl_contains_geometry_for, Contains};
2use crate::algorithm::Intersects;
3use crate::geometry::*;
4use crate::{GeoFloat, GeoNum};
5
6// ┌──────────────────────────┐
7// │ Implementations for Line │
8// └──────────────────────────┘
9
10impl<T> Contains<Coord<T>> for Line<T>
11where
12    T: GeoNum,
13{
14    fn contains(&self, coord: &Coord<T>) -> bool {
15        if self.start == self.end {
16            &self.start == coord
17        } else {
18            coord != &self.start && coord != &self.end && self.intersects(coord)
19        }
20    }
21}
22
23impl<T> Contains<Point<T>> for Line<T>
24where
25    T: GeoNum,
26{
27    fn contains(&self, p: &Point<T>) -> bool {
28        self.contains(&p.0)
29    }
30}
31
32impl<T> Contains<Line<T>> for Line<T>
33where
34    T: GeoNum,
35{
36    fn contains(&self, line: &Line<T>) -> bool {
37        if line.start == line.end {
38            self.contains(&line.start)
39        } else {
40            self.intersects(&line.start) && self.intersects(&line.end)
41        }
42    }
43}
44
45impl<T> Contains<LineString<T>> for Line<T>
46where
47    T: GeoNum,
48{
49    fn contains(&self, linestring: &LineString<T>) -> bool {
50        // Empty linestring has no interior, and not
51        // contained in anything.
52        if linestring.0.is_empty() {
53            return false;
54        }
55
56        // The interior of the linestring should have some
57        // intersection with the interior of self. Two cases
58        // arise:
59        //
60        // 1. There are at least two distinct points in the
61        // linestring. Then, if both intersect, the interior
62        // between these two must have non-empty intersection.
63        //
64        // 2. Otherwise, all the points on the linestring
65        // are the same. In this case, the interior is this
66        // specific point, and it should be contained in the
67        // line.
68        let first = linestring.0.first().unwrap();
69        let mut all_equal = true;
70
71        // If all the vertices of the linestring intersect
72        // self, then the interior or boundary of the
73        // linestring cannot have non-empty intersection
74        // with the exterior.
75        let all_intersects = linestring.0.iter().all(|c| {
76            if c != first {
77                all_equal = false;
78            }
79            self.intersects(c)
80        });
81
82        all_intersects && (!all_equal || self.contains(first))
83    }
84}
85
86impl_contains_from_relate!(Line<T>, [Polygon<T>, MultiPoint<T>, MultiLineString<T>, MultiPolygon<T>, GeometryCollection<T>, Rect<T>, Triangle<T>]);
87impl_contains_geometry_for!(Line<T>);