1pub trait Contains<Rhs = Self> {
36 fn contains(&self, rhs: &Rhs) -> bool;
37}
38
39mod geometry;
40mod geometry_collection;
41mod line;
42mod line_string;
43mod point;
44mod polygon;
45mod rect;
46mod triangle;
47
48macro_rules! impl_contains_from_relate {
49 ($for:ty, [$($target:ty),*]) => {
50 $(
51 impl<T> Contains<$target> for $for
52 where
53 T: GeoFloat
54 {
55 fn contains(&self, target: &$target) -> bool {
56 use $crate::algorithm::Relate;
57 self.relate(target).is_contains()
58 }
59 }
60 )*
61 };
62}
63pub(crate) use impl_contains_from_relate;
64
65macro_rules! impl_contains_geometry_for {
66 ($geom_type: ty) => {
67 impl<T> Contains<Geometry<T>> for $geom_type
68 where
69 T: GeoFloat,
70 {
71 fn contains(&self, geometry: &Geometry<T>) -> bool {
72 match geometry {
73 Geometry::Point(g) => self.contains(g),
74 Geometry::Line(g) => self.contains(g),
75 Geometry::LineString(g) => self.contains(g),
76 Geometry::Polygon(g) => self.contains(g),
77 Geometry::MultiPoint(g) => self.contains(g),
78 Geometry::MultiLineString(g) => self.contains(g),
79 Geometry::MultiPolygon(g) => self.contains(g),
80 Geometry::GeometryCollection(g) => self.contains(g),
81 Geometry::Rect(g) => self.contains(g),
82 Geometry::Triangle(g) => self.contains(g),
83 }
84 }
85 }
86 };
87}
88pub(crate) use impl_contains_geometry_for;
89
90#[cfg(test)]
95mod test {
96 use crate::line_string;
97 use crate::Contains;
98 use crate::{coord, Coord, Line, LineString, MultiPolygon, Point, Polygon, Rect, Triangle};
99
100 #[test]
101 fn linestring_contains_point() {
103 let line_string = LineString::from(vec![(0., 0.), (3., 3.)]);
104 let point_on_line = Point::new(1., 1.);
105 assert!(line_string.contains(&point_on_line));
106 }
107 #[test]
108 fn polygon_does_not_contain_polygon() {
110 let v = Polygon::new(
111 vec![
112 (150., 350.),
113 (100., 350.),
114 (210., 160.),
115 (290., 350.),
116 (250., 350.),
117 (200., 250.),
118 (150., 350.),
119 ]
120 .into(),
121 vec![],
122 );
123 let rect = Polygon::new(
124 vec![
125 (250., 310.),
126 (150., 310.),
127 (150., 280.),
128 (250., 280.),
129 (250., 310.),
130 ]
131 .into(),
132 vec![],
133 );
134 assert!(!v.contains(&rect));
135 }
136 #[test]
137 fn polygon_contains_polygon() {
139 let v = Polygon::new(
140 vec![
141 (150., 350.),
142 (100., 350.),
143 (210., 160.),
144 (290., 350.),
145 (250., 350.),
146 (200., 250.),
147 (150., 350.),
148 ]
149 .into(),
150 vec![],
151 );
152 let rect = Polygon::new(
153 vec![
154 (185., 237.),
155 (220., 237.),
156 (220., 220.),
157 (185., 220.),
158 (185., 237.),
159 ]
160 .into(),
161 vec![],
162 );
163 assert!(v.contains(&rect));
164 }
165 #[test]
166 fn linestring_fully_contained_in_polygon() {
168 let poly = Polygon::new(
169 LineString::from(vec![(0., 0.), (5., 0.), (5., 6.), (0., 6.), (0., 0.)]),
170 vec![],
171 );
172 let ls = LineString::from(vec![(3.0, 0.5), (3.0, 3.5)]);
173 assert!(poly.contains(&ls));
174 }
175 #[test]
177 fn empty_linestring_test() {
178 let linestring = LineString::new(Vec::new());
179 assert!(!linestring.contains(&Point::new(2., 1.)));
180 }
181 #[test]
182 fn linestring_point_is_vertex_test() {
183 let linestring = LineString::from(vec![(0., 0.), (2., 0.), (2., 2.)]);
184 assert!(linestring.contains(&Point::new(2., 0.)));
187 assert!(!linestring.contains(&Point::new(0., 0.)));
188 assert!(!linestring.contains(&Point::new(2., 2.)));
189 }
190 #[test]
191 fn linestring_test() {
192 let linestring = LineString::from(vec![(0., 0.), (2., 0.), (2., 2.)]);
193 assert!(linestring.contains(&Point::new(1., 0.)));
194 }
195 #[test]
197 fn empty_polygon_test() {
198 let linestring = LineString::new(Vec::new());
199 let poly = Polygon::new(linestring, Vec::new());
200 assert!(!poly.contains(&Point::new(2., 1.)));
201 }
202 #[test]
203 fn polygon_with_one_point_test() {
204 let linestring = LineString::from(vec![(2., 1.)]);
205 let poly = Polygon::new(linestring, Vec::new());
206 assert!(!poly.contains(&Point::new(3., 1.)));
207 }
208 #[test]
209 fn polygon_with_one_point_is_vertex_test() {
210 let linestring = LineString::from(vec![(2., 1.)]);
211 let poly = Polygon::new(linestring, Vec::new());
212 assert!(!poly.contains(&Point::new(2., 1.)));
213 }
214 #[test]
215 fn polygon_with_point_on_boundary_test() {
216 let linestring = LineString::from(vec![(0., 0.), (2., 0.), (2., 2.), (0., 2.), (0., 0.)]);
217 let poly = Polygon::new(linestring, Vec::new());
218 assert!(!poly.contains(&Point::new(1., 0.)));
219 assert!(!poly.contains(&Point::new(2., 1.)));
220 assert!(!poly.contains(&Point::new(1., 2.)));
221 assert!(!poly.contains(&Point::new(0., 1.)));
222 }
223 #[test]
224 fn point_in_polygon_test() {
225 let linestring = LineString::from(vec![(0., 0.), (2., 0.), (2., 2.), (0., 2.), (0., 0.)]);
226 let poly = Polygon::new(linestring, Vec::new());
227 assert!(poly.contains(&Point::new(1., 1.)));
228 }
229 #[test]
230 fn point_in_polygon_with_ray_passing_through_a_vertex_test() {
231 let linestring = LineString::from(vec![(1., 0.), (0., 1.), (-1., 0.), (0., -1.)]);
232 let poly = Polygon::new(linestring, Vec::new());
233 assert!(poly.contains(&Point::new(0., 0.)));
234 }
235 #[test]
236 fn point_in_polygon_with_ray_passing_through_a_vertex_and_not_crossing() {
237 let linestring = LineString::from(vec![
238 (0., 0.),
239 (2., 0.),
240 (3., 1.),
241 (4., 0.),
242 (4., 2.),
243 (0., 2.),
244 (0., 0.),
245 ]);
246 let poly = Polygon::new(linestring, Vec::new());
247 assert!(poly.contains(&Point::new(1., 1.)));
248 }
249 #[test]
250 fn point_out_polygon_test() {
251 let linestring = LineString::from(vec![(0., 0.), (2., 0.), (2., 2.), (0., 2.), (0., 0.)]);
252 let poly = Polygon::new(linestring, Vec::new());
253 assert!(!poly.contains(&Point::new(2.1, 1.)));
254 assert!(!poly.contains(&Point::new(1., 2.1)));
255 assert!(!poly.contains(&Point::new(2.1, 2.1)));
256 }
257 #[test]
258 fn point_polygon_with_inner_test() {
259 let linestring = LineString::from(vec![(0., 0.), (2., 0.), (2., 2.), (0., 2.), (0., 0.)]);
260 let inner_linestring = LineString::from(vec![
261 [0.5, 0.5],
262 [1.5, 0.5],
263 [1.5, 1.5],
264 [0.0, 1.5],
265 [0.0, 0.0],
266 ]);
267 let poly = Polygon::new(linestring, vec![inner_linestring]);
268 assert!(!poly.contains(&Point::new(0.25, 0.25)));
269 assert!(!poly.contains(&Point::new(1., 1.)));
270 assert!(!poly.contains(&Point::new(1.5, 1.5)));
271 assert!(!poly.contains(&Point::new(1.5, 1.)));
272 }
273
274 #[test]
276 fn empty_multipolygon_test() {
277 let multipoly = MultiPolygon::new(Vec::new());
278 assert!(!multipoly.contains(&Point::new(2., 1.)));
279 }
280 #[test]
281 fn empty_multipolygon_two_polygons_test() {
282 let poly1 = Polygon::new(
283 LineString::from(vec![(0., 0.), (1., 0.), (1., 1.), (0., 1.), (0., 0.)]),
284 Vec::new(),
285 );
286 let poly2 = Polygon::new(
287 LineString::from(vec![(2., 0.), (3., 0.), (3., 1.), (2., 1.), (2., 0.)]),
288 Vec::new(),
289 );
290 let multipoly = MultiPolygon::new(vec![poly1, poly2]);
291 assert!(multipoly.contains(&Point::new(0.5, 0.5)));
292 assert!(multipoly.contains(&Point::new(2.5, 0.5)));
293 assert!(!multipoly.contains(&Point::new(1.5, 0.5)));
294 }
295 #[test]
296 fn empty_multipolygon_two_polygons_and_inner_test() {
297 let poly1 = Polygon::new(
298 LineString::from(vec![(0., 0.), (5., 0.), (5., 6.), (0., 6.), (0., 0.)]),
299 vec![LineString::from(vec![
300 (1., 1.),
301 (4., 1.),
302 (4., 4.),
303 (1., 1.),
304 ])],
305 );
306 let poly2 = Polygon::new(
307 LineString::from(vec![(9., 0.), (14., 0.), (14., 4.), (9., 4.), (9., 0.)]),
308 Vec::new(),
309 );
310
311 let multipoly = MultiPolygon::new(vec![poly1, poly2]);
312 assert!(multipoly.contains(&Point::new(3., 5.)));
313 assert!(multipoly.contains(&Point::new(12., 2.)));
314 assert!(!multipoly.contains(&Point::new(3., 2.)));
315 assert!(!multipoly.contains(&Point::new(7., 2.)));
316 }
317 #[test]
319 fn linestring_in_polygon_with_linestring_is_boundary_test() {
320 let linestring = LineString::from(vec![(0., 0.), (2., 0.), (2., 2.), (0., 2.), (0., 0.)]);
321 let poly = Polygon::new(linestring.clone(), Vec::new());
322 assert!(!poly.contains(&linestring));
323 assert!(!poly.contains(&LineString::from(vec![(0., 0.), (2., 0.)])));
324 assert!(!poly.contains(&LineString::from(vec![(2., 0.), (2., 2.)])));
325 assert!(!poly.contains(&LineString::from(vec![(0., 2.), (0., 0.)])));
326 }
327 #[test]
328 fn linestring_outside_polygon_test() {
329 let linestring = LineString::from(vec![(0., 0.), (2., 0.), (2., 2.), (0., 2.), (0., 0.)]);
330 let poly = Polygon::new(linestring, Vec::new());
331 assert!(!poly.contains(&LineString::from(vec![(1., 1.), (3., 0.)])));
332 assert!(!poly.contains(&LineString::from(vec![(3., 0.), (5., 2.)])));
333 }
334 #[test]
335 fn linestring_in_inner_polygon_test() {
336 let poly = Polygon::new(
337 LineString::from(vec![(0., 0.), (5., 0.), (5., 6.), (0., 6.), (0., 0.)]),
338 vec![LineString::from(vec![
339 (1., 1.),
340 (4., 1.),
341 (4., 4.),
342 (1., 4.),
343 (1., 1.),
344 ])],
345 );
346 assert!(!poly.contains(&LineString::from(vec![(2., 2.), (3., 3.)])));
347 assert!(!poly.contains(&LineString::from(vec![(2., 2.), (2., 5.)])));
348 assert!(!poly.contains(&LineString::from(vec![(3., 0.5), (3., 5.)])));
349 }
350 #[test]
351 fn bounding_rect_in_inner_bounding_rect_test() {
352 let bounding_rect_xl =
353 Rect::new(coord! { x: -100., y: -200. }, coord! { x: 100., y: 200. });
354 let bounding_rect_sm = Rect::new(coord! { x: -10., y: -20. }, coord! { x: 10., y: 20. });
355 assert!(bounding_rect_xl.contains(&bounding_rect_sm));
356 assert!(!bounding_rect_sm.contains(&bounding_rect_xl));
357 }
358 #[test]
359 fn point_in_line_test() {
360 let c = |x, y| coord! { x: x, y: y };
361 let p0 = c(2., 4.);
362 let line1 = Line::new(c(2., 0.), c(2., 5.));
364 let line2 = Line::new(c(0., 6.), c(1.5, 4.5));
366 let line3 = Line::new(c(0., 6.), c(3., 3.));
368 assert!(line1.contains(&Point::from(p0)));
369 assert!(!line2.contains(&Point::from(p0)));
370 assert!(line3.contains(&Point::from(p0)));
371 }
372 #[test]
373 fn line_in_line_test() {
374 let c = |x, y| coord! { x: x, y: y };
375 let line0 = Line::new(c(0., 1.), c(3., 4.));
376 let line1 = Line::new(c(1., 2.), c(2., 2.));
378 let line2 = Line::new(c(1., 2.), c(4., 5.));
380 let line3 = Line::new(c(1., 2.), c(3., 4.));
382 assert!(!line0.contains(&line1));
383 assert!(!line0.contains(&line2));
384 assert!(line0.contains(&line3));
385 }
386 #[test]
387 fn linestring_in_line_test() {
388 let line = Line::from([(0, 10), (30, 40)]);
389 let linestring0 = LineString::from(vec![(1, 11), (10, 20), (15, 25)]);
391 let linestring1 = LineString::from(vec![(1, 11), (20, 20), (15, 25)]);
393 let linestring2 = LineString::from(vec![(1, 11), (10, 20), (40, 50)]);
395 let linestring3 = LineString::from(vec![(11, 11), (20, 20), (25, 25)]);
397 let linestring4 = LineString::from(vec![(0, 10), (0, 10), (0, 10)]);
399 let linestring5 = LineString::from(vec![(1, 11), (1, 11), (1, 11)]);
401 assert!(line.contains(&linestring0));
402 assert!(!line.contains(&linestring1));
403 assert!(!line.contains(&linestring2));
404 assert!(!line.contains(&linestring3));
405 assert!(!line.contains(&linestring4));
406 assert!(line.contains(&linestring5));
407 }
408 #[test]
409 fn line_in_polygon_test() {
410 let c = |x, y| coord! { x: x, y: y };
411 let line = Line::new(c(0.0, 10.0), c(30.0, 40.0));
412 let linestring0 = line_string![
413 c(-10.0, 0.0),
414 c(50.0, 0.0),
415 c(50.0, 50.0),
416 c(0.0, 50.0),
417 c(-10.0, 0.0)
418 ];
419 let poly0 = Polygon::new(linestring0, Vec::new());
420 let linestring1 = line_string![
421 c(0.0, 0.0),
422 c(0.0, 20.0),
423 c(20.0, 20.0),
424 c(20.0, 0.0),
425 c(0.0, 0.0)
426 ];
427 let poly1 = Polygon::new(linestring1, Vec::new());
428 assert!(poly0.contains(&line));
429 assert!(!poly1.contains(&line));
430 }
431 #[test]
432 fn line_in_polygon_edgecases_test() {
433 let c = |x, y| coord! { x: x, y: y };
437 let linestring0 = line_string![
439 c(0.0, 0.0),
440 c(1.0, 1.0),
441 c(1.0, -1.0),
442 c(-1.0, -1.0),
443 c(-1.0, 1.0)
444 ];
445 let poly = Polygon::new(linestring0, Vec::new());
446
447 assert!(poly.contains(&Line::new(c(0.0, 0.0), c(1.0, -1.0))));
448 assert!(poly.contains(&Line::new(c(-1.0, 1.0), c(1.0, -1.0))));
449 assert!(!poly.contains(&Line::new(c(-1.0, 1.0), c(1.0, 1.0))));
450 }
451 #[test]
452 fn line_in_linestring_edgecases() {
453 let c = |x, y| coord! { x: x, y: y };
454 use crate::line_string;
455 let mut ls = line_string![c(0, 0), c(1, 0), c(0, 1), c(-1, 0)];
456 assert!(!ls.contains(&Line::from([(0, 0), (0, 0)])));
457 ls.close();
458 assert!(ls.contains(&Line::from([(0, 0), (0, 0)])));
459 assert!(ls.contains(&Line::from([(-1, 0), (1, 0)])));
460 }
461 #[test]
462 fn line_in_linestring_test() {
463 let line0 = Line::from([(1., 1.), (2., 2.)]);
464 let linestring0 = LineString::from(vec![(0., 0.5), (0.5, 0.5), (3., 3.)]);
466 let linestring1 = LineString::from(vec![
468 (0., 0.5),
469 (0.5, 0.5),
470 (1.2, 1.2),
471 (1.5, 1.5),
472 (3., 3.),
473 ]);
474 let linestring2 = LineString::from(vec![
476 (0., 0.5),
477 (0.5, 0.5),
478 (1.2, 1.2),
479 (1.5, 0.),
480 (2., 2.),
481 (3., 3.),
482 ]);
483 assert!(linestring0.contains(&line0));
484 assert!(linestring1.contains(&line0));
485 assert!(!linestring2.contains(&line0));
486 }
487
488 #[test]
489 fn integer_bounding_rects() {
490 let p: Point<i32> = Point::new(10, 20);
491 let bounding_rect: Rect<i32> = Rect::new(coord! { x: 0, y: 0 }, coord! { x: 100, y: 100 });
492 assert!(bounding_rect.contains(&p));
493 assert!(!bounding_rect.contains(&Point::new(-10, -10)));
494
495 let smaller_bounding_rect: Rect<i32> =
496 Rect::new(coord! { x: 10, y: 10 }, coord! { x: 20, y: 20 });
497 assert!(bounding_rect.contains(&smaller_bounding_rect));
498 }
499
500 #[test]
501 fn triangle_not_contains_point_on_edge() {
502 let t = Triangle::from([(0.0, 0.0), (2.0, 0.0), (2.0, 2.0)]);
503 let p = Point::new(1.0, 0.0);
504 assert!(!t.contains(&p));
505 }
506
507 #[test]
508 fn triangle_not_contains_point_on_vertex() {
509 let t = Triangle::from([(0.0, 0.0), (2.0, 0.0), (2.0, 2.0)]);
510 let p = Point::new(2.0, 0.0);
511 assert!(!t.contains(&p));
512 }
513
514 #[test]
515 fn triangle_contains_point_inside() {
516 let t = Triangle::from([(0.0, 0.0), (2.0, 0.0), (2.0, 2.0)]);
517 let p = Point::new(1.0, 0.5);
518 assert!(t.contains(&p));
519 }
520
521 #[test]
522 fn triangle_not_contains_point_above() {
523 let t = Triangle::from([(0.0, 0.0), (2.0, 0.0), (2.0, 2.0)]);
524 let p = Point::new(1.0, 1.5);
525 assert!(!t.contains(&p));
526 }
527
528 #[test]
529 fn triangle_not_contains_point_below() {
530 let t = Triangle::from([(0.0, 0.0), (2.0, 0.0), (2.0, 2.0)]);
531 let p = Point::new(-1.0, 0.5);
532 assert!(!t.contains(&p));
533 }
534
535 #[test]
536 fn triangle_contains_neg_point() {
537 let t = Triangle::from([(0.0, 0.0), (-2.0, 0.0), (-2.0, -2.0)]);
538 let p = Point::new(-1.0, -0.5);
539 assert!(t.contains(&p));
540 }
541
542 #[test]
543 fn triangle_contains_collinear_points() {
545 let origin: Coord = (0., 0.).into();
546 let tri = Triangle::new(origin, origin, origin);
547 let pt: Point = (0., 1.23456).into();
548 assert!(!tri.contains(&pt));
549 let pt: Point = (0., 0.).into();
550 assert!(!tri.contains(&pt));
551 let origin: Coord = (0., 0.).into();
552 let tri = Triangle::new((1., 1.).into(), origin, origin);
553 let pt: Point = (1., 1.).into();
554 assert!(!tri.contains(&pt));
555 let pt: Point = (0.5, 0.5).into();
556 assert!(!tri.contains(&pt));
557 }
558}