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