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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use super::Contains;
use crate::intersects::Intersects;
use crate::{CoordNum, Coordinate, GeoNum, Line, LineString, MultiLineString, Point};
impl<T> Contains<Coordinate<T>> for LineString<T>
where
T: GeoNum,
{
fn contains(&self, coord: &Coordinate<T>) -> bool {
if self.0.is_empty() {
return false;
}
if self.is_closed() && coord == &self.0[0] {
return true;
}
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<G, T> Contains<G> for MultiLineString<T>
where
T: CoordNum,
LineString<T>: Contains<G>,
{
fn contains(&self, rhs: &G) -> bool {
self.iter().any(|p| p.contains(rhs))
}
}