use super::{impl_contains_from_relate, impl_contains_geometry_for, Contains};
use crate::algorithm::Intersects;
use crate::geometry::*;
use crate::{CoordNum, GeoFloat, GeoNum};
impl<T> Contains<Coord<T>> for LineString<T>
where
T: GeoNum,
{
fn contains(&self, coord: &Coord<T>) -> bool {
if self.0.is_empty() {
return false;
}
if coord == &self.0[0] || coord == self.0.last().unwrap() {
return self.is_closed();
}
self.lines()
.enumerate()
.any(|(i, line)| line.contains(coord) || (i > 0 && coord == &line.start))
}
}
impl<T> Contains<Point<T>> for LineString<T>
where
T: GeoNum,
{
fn contains(&self, p: &Point<T>) -> bool {
self.contains(&p.0)
}
}
impl<T> Contains<Line<T>> for LineString<T>
where
T: GeoNum,
{
fn contains(&self, line: &Line<T>) -> bool {
if line.start == line.end {
return self.contains(&line.start);
}
let mut line = *line;
let mut first_cut = None;
let lines_iter = self.lines();
let num_lines = lines_iter.len();
for (i, segment) in self.lines().chain(lines_iter).enumerate() {
if i >= num_lines {
if let Some(upto_i) = first_cut {
if i >= num_lines + upto_i {
break;
}
} else {
break;
}
}
let other = if segment.intersects(&line.start) {
line.end
} else if segment.intersects(&line.end) {
line.start
} else {
continue;
};
let new_inside = if segment.intersects(&other) {
return true;
}
else if line.contains(&segment.start) {
segment.start
} else if line.contains(&segment.end) {
segment.end
} else {
continue;
};
first_cut = first_cut.or(Some(i));
if other == line.start {
line.end = new_inside;
} else {
line.start = new_inside;
}
}
false
}
}
impl<T> Contains<LineString<T>> for LineString<T>
where
T: GeoNum,
{
fn contains(&self, rhs: &LineString<T>) -> bool {
rhs.lines().all(|l| self.contains(&l))
}
}
impl_contains_from_relate!(LineString<T>, [Polygon<T>, MultiPoint<T>, MultiLineString<T>, MultiPolygon<T>, GeometryCollection<T>, Rect<T>, Triangle<T>]);
impl_contains_geometry_for!(LineString<T>);
impl_contains_from_relate!(MultiLineString<T>, [Line<T>, LineString<T>, Polygon<T>, MultiPoint<T>, MultiLineString<T>, MultiPolygon<T>, GeometryCollection<T>, Rect<T>, Triangle<T>]);
impl_contains_geometry_for!(MultiLineString<T>);
impl<T> Contains<Point<T>> for MultiLineString<T>
where
T: CoordNum,
LineString<T>: Contains<Point<T>>,
{
fn contains(&self, rhs: &Point<T>) -> bool {
self.iter().any(|ls| ls.contains(rhs))
}
}