1use super::{Contains, impl_contains_from_relate, impl_contains_geometry_for};
2use crate::geometry::*;
3use crate::{GeoFloat, GeoNum};
4use crate::{HasDimensions, Relate};
5
6impl<T> Contains<Coord<T>> for Polygon<T>
10where
11 T: GeoNum,
12{
13 fn contains(&self, coord: &Coord<T>) -> bool {
14 use crate::coordinate_position::{CoordPos, CoordinatePosition};
15
16 self.coordinate_position(coord) == CoordPos::Inside
17 }
18}
19
20impl<T> Contains<Point<T>> for Polygon<T>
21where
22 T: GeoNum,
23{
24 fn contains(&self, p: &Point<T>) -> bool {
25 self.contains(&p.0)
26 }
27}
28
29impl<T> Contains<MultiPoint<T>> for Polygon<T>
30where
31 T: GeoNum,
32{
33 fn contains(&self, mp: &MultiPoint<T>) -> bool {
34 use crate::coordinate_position::{CoordPos, CoordinatePosition};
35 mp.iter().any(|p| self.contains(p))
38 && mp
39 .iter()
40 .all(|p| self.coordinate_position(&p.0) != CoordPos::Outside)
41 }
42}
43
44impl_contains_from_relate!(Polygon<T>, [Line<T>, LineString<T>, Polygon<T>, MultiLineString<T>, MultiPolygon<T>, GeometryCollection<T>, Rect<T>, Triangle<T>]);
45impl_contains_geometry_for!(Polygon<T>);
46
47impl<T> Contains<Coord<T>> for MultiPolygon<T>
52where
53 T: GeoNum,
54{
55 fn contains(&self, coord: &Coord<T>) -> bool {
56 self.iter().any(|poly| poly.contains(coord))
57 }
58}
59
60impl<T> Contains<Point<T>> for MultiPolygon<T>
61where
62 T: GeoNum,
63{
64 fn contains(&self, p: &Point<T>) -> bool {
65 self.contains(&p.0)
66 }
67}
68
69impl<T: GeoNum> Contains<MultiPoint<T>> for MultiPolygon<T> {
70 fn contains(&self, rhs: &MultiPoint<T>) -> bool {
71 if self.is_empty() || rhs.is_empty() {
72 return false;
73 }
74 rhs.iter().all(|point| self.contains(point))
75 }
76}
77
78impl<F> Contains<Line<F>> for MultiPolygon<F>
79where
80 F: GeoFloat,
81{
82 fn contains(&self, rhs: &Line<F>) -> bool {
83 rhs.relate(self).is_within()
84 }
85}
86
87impl<F> Contains<LineString<F>> for MultiPolygon<F>
88where
89 F: GeoFloat,
90{
91 fn contains(&self, rhs: &LineString<F>) -> bool {
92 rhs.relate(self).is_within()
93 }
94}
95
96impl<F> Contains<MultiLineString<F>> for MultiPolygon<F>
97where
98 F: GeoFloat,
99{
100 fn contains(&self, rhs: &MultiLineString<F>) -> bool {
101 rhs.relate(self).is_within()
102 }
103}
104
105impl<F> Contains<Polygon<F>> for MultiPolygon<F>
106where
107 F: GeoFloat,
108{
109 fn contains(&self, rhs: &Polygon<F>) -> bool {
110 rhs.relate(self).is_within()
111 }
112}
113
114impl<F> Contains<MultiPolygon<F>> for MultiPolygon<F>
115where
116 F: GeoFloat,
117{
118 fn contains(&self, rhs: &MultiPolygon<F>) -> bool {
119 rhs.relate(self).is_within()
120 }
121}
122
123impl<F> Contains<GeometryCollection<F>> for MultiPolygon<F>
124where
125 F: GeoFloat,
126{
127 fn contains(&self, rhs: &GeometryCollection<F>) -> bool {
128 rhs.relate(self).is_within()
129 }
130}
131
132impl<F> Contains<Rect<F>> for MultiPolygon<F>
133where
134 F: GeoFloat,
135{
136 fn contains(&self, rhs: &Rect<F>) -> bool {
137 rhs.relate(self).is_within()
138 }
139}
140
141impl<F> Contains<Triangle<F>> for MultiPolygon<F>
142where
143 F: GeoFloat,
144{
145 fn contains(&self, rhs: &Triangle<F>) -> bool {
146 rhs.relate(self).is_within()
147 }
148}
149
150#[cfg(test)]
151mod test {
152 use super::*;
153 use crate::{MultiPoint, Relate, coord, polygon};
154
155 fn make_test_pts() -> [Coord<f64>; 7] {
156 let pt_a = coord! {x: 0., y: 0.};
157 let pt_b = coord! {x: 10., y: 0.};
158 let pt_c = coord! {x: 10., y: 10.};
159 let pt_d = coord! {x: 0., y: 10.};
160
161 let pt_edge = coord! {x: 0., y: 5.};
162 let pt_mid = coord! {x: 5., y: 5.};
163 let pt_out = coord! {x: 11., y: 11.};
164 [pt_a, pt_b, pt_c, pt_d, pt_edge, pt_mid, pt_out]
165 }
166
167 #[test]
168 fn test_polygon_should_never_contain_empty_multipoint() {
169 let [pt_a, pt_b, pt_c, pt_d, _pt_edge, _pt_mid, _pt_out] = make_test_pts();
170
171 let poly = polygon![pt_a, pt_b, pt_c, pt_d, pt_a];
172 let empty: MultiPoint<f64> = MultiPoint::new(Vec::new());
173
174 assert!(!poly.contains(&empty));
176 assert!(!poly.relate(&empty).is_contains());
177 }
178
179 #[test]
180 fn test_polygon_should_contains_multipoint() {
181 let [pt_a, pt_b, pt_c, pt_d, pt_edge, pt_mid, _pt_out] = make_test_pts();
182
183 let poly = polygon![pt_a, pt_b, pt_c, pt_d, pt_a];
184
185 let mp_a_mid = MultiPoint::from(vec![pt_a, pt_mid]);
187 let mp_bc_mid = MultiPoint::from(vec![pt_a, pt_b, pt_mid]);
188 let mp_bc_edge_mid = MultiPoint::from(vec![pt_a, pt_b, pt_edge, pt_mid]);
189
190 assert!(poly.contains(&mp_a_mid));
191 assert!(poly.contains(&mp_bc_mid));
192 assert!(poly.contains(&mp_bc_edge_mid));
193 }
194
195 #[test]
196 fn test_polygon_should_not_contains_multipoint_on_edge() {
197 let [pt_a, pt_b, pt_c, pt_d, pt_edge, _pt_mid, _pt_out] = make_test_pts();
198
199 let poly = polygon![pt_a, pt_b, pt_c, pt_d, pt_a];
200
201 let mp_a = MultiPoint::from(vec![pt_a]);
203 let mp_bc = MultiPoint::from(vec![pt_a, pt_b]);
204 let mp_bc_edge = MultiPoint::from(vec![pt_a, pt_b, pt_edge]);
205
206 assert!(!poly.contains(&mp_a));
207 assert!(!poly.contains(&mp_bc));
208 assert!(!poly.contains(&mp_bc_edge));
209 }
210
211 #[test]
212 fn test_polygon_should_not_contains_out_multipoint() {
213 let [pt_a, pt_b, pt_c, pt_d, pt_edge, _pt_mid, pt_out] = make_test_pts();
214
215 let poly = polygon![pt_a, pt_b, pt_c, pt_d, pt_a];
216
217 let mp_a_out = MultiPoint::from(vec![pt_a, pt_out]);
219 let mp_bc_out = MultiPoint::from(vec![pt_a, pt_b, pt_out]);
220 let mp_bc_edge_out = MultiPoint::from(vec![pt_a, pt_b, pt_edge, pt_out]);
221
222 assert!(!poly.contains(&mp_a_out));
223 assert!(!poly.contains(&mp_bc_out));
224 assert!(!poly.contains(&mp_bc_edge_out));
225 }
226}