geo/algorithm/contains/
line_string.rs1use super::{impl_contains_from_relate, impl_contains_geometry_for, Contains};
2use crate::algorithm::Intersects;
3use crate::geometry::*;
4use crate::{CoordNum, GeoFloat, GeoNum};
5
6impl<T> Contains<Coord<T>> for LineString<T>
11where
12 T: GeoNum,
13{
14 fn contains(&self, coord: &Coord<T>) -> bool {
15 if self.0.is_empty() {
16 return false;
17 }
18
19 if coord == &self.0[0] || coord == self.0.last().unwrap() {
20 return self.is_closed();
21 }
22
23 self.lines()
24 .enumerate()
25 .any(|(i, line)| line.contains(coord) || (i > 0 && coord == &line.start))
26 }
27}
28
29impl<T> Contains<Point<T>> for LineString<T>
30where
31 T: GeoNum,
32{
33 fn contains(&self, p: &Point<T>) -> bool {
34 self.contains(&p.0)
35 }
36}
37
38impl<T> Contains<Line<T>> for LineString<T>
39where
40 T: GeoNum,
41{
42 fn contains(&self, line: &Line<T>) -> bool {
43 if line.start == line.end {
44 return self.contains(&line.start);
45 }
46
47 let mut line = *line;
50 let mut first_cut = None;
51
52 let lines_iter = self.lines();
53 let num_lines = lines_iter.len();
54
55 for (i, segment) in self.lines().chain(lines_iter).enumerate() {
58 if i >= num_lines {
59 if let Some(upto_i) = first_cut {
63 if i >= num_lines + upto_i {
64 break;
65 }
66 } else {
67 break;
68 }
69 }
70 let other = if segment.intersects(&line.start) {
73 line.end
74 } else if segment.intersects(&line.end) {
75 line.start
76 } else {
77 continue;
78 };
79
80 let new_inside = if segment.intersects(&other) {
83 return true;
84 }
85 else if line.contains(&segment.start) {
89 segment.start
90 } else if line.contains(&segment.end) {
91 segment.end
92 } else {
93 continue;
94 };
95
96 first_cut = first_cut.or(Some(i));
97 if other == line.start {
98 line.end = new_inside;
99 } else {
100 line.start = new_inside;
101 }
102 }
103
104 false
105 }
106}
107
108impl<T> Contains<LineString<T>> for LineString<T>
109where
110 T: GeoNum,
111{
112 fn contains(&self, rhs: &LineString<T>) -> bool {
113 rhs.lines().all(|l| self.contains(&l))
114 }
115}
116
117impl_contains_from_relate!(LineString<T>, [Polygon<T>, MultiPoint<T>, MultiLineString<T>, MultiPolygon<T>, GeometryCollection<T>, Rect<T>, Triangle<T>]);
118impl_contains_geometry_for!(LineString<T>);
119
120impl_contains_from_relate!(MultiLineString<T>, [Line<T>, LineString<T>, Polygon<T>, MultiPoint<T>, MultiLineString<T>, MultiPolygon<T>, GeometryCollection<T>, Rect<T>, Triangle<T>]);
125impl_contains_geometry_for!(MultiLineString<T>);
126
127impl<T> Contains<Point<T>> for MultiLineString<T>
128where
129 T: CoordNum,
130 LineString<T>: Contains<Point<T>>,
131{
132 fn contains(&self, rhs: &Point<T>) -> bool {
133 self.iter().any(|ls| ls.contains(rhs))
134 }
135}