galileo_types/
multi_contour.rs

1use crate::cartesian::{CartesianPoint2d, Rect};
2use crate::contour::Contour;
3use crate::geo::Projection;
4use crate::geometry::{
5    CartesianGeometry2d, CartesianGeometry2dSpecialization, Geom, Geometry, GeometrySpecialization,
6};
7use crate::geometry_type::{CartesianSpace2d, GeometryType, MultiContourGeometryType};
8
9/// Geometry consisting of several contours.
10pub trait MultiContour {
11    /// Contour type.
12    type Contour: Contour;
13
14    /// Iterator over contours.
15    fn contours(&self) -> impl Iterator<Item = &Self::Contour>;
16}
17
18impl<C, Space> GeometrySpecialization<MultiContourGeometryType, Space> for C
19where
20    C: MultiContour + GeometryType<Type = MultiContourGeometryType, Space = Space>,
21    C::Contour: Geometry,
22{
23    type Point = <C::Contour as Geometry>::Point;
24
25    fn project_spec<Proj>(&self, projection: &Proj) -> Option<Geom<Proj::OutPoint>>
26    where
27        Proj: Projection<InPoint = Self::Point> + ?Sized,
28    {
29        let contours = self
30            .contours()
31            .map(|c| {
32                c.project(projection).and_then(|c| match c {
33                    Geom::Contour(contour) => Some(contour),
34                    _ => None,
35                })
36            })
37            .collect::<Option<Vec<crate::impls::Contour<Proj::OutPoint>>>>()?;
38        Some(Geom::MultiContour(contours.into()))
39    }
40}
41
42impl<P, C> CartesianGeometry2dSpecialization<P, MultiContourGeometryType> for C
43where
44    P: CartesianPoint2d + Copy,
45    C: MultiContour
46        + GeometryType<Type = MultiContourGeometryType, Space = CartesianSpace2d>
47        + Geometry<Point = P>,
48    C::Contour: Contour<Point = P> + CartesianGeometry2d<P>,
49{
50    fn is_point_inside_spec<Other: CartesianPoint2d<Num = P::Num>>(
51        &self,
52        point: &Other,
53        tolerance: P::Num,
54    ) -> bool {
55        self.contours().any(|c| c.is_point_inside(point, tolerance))
56    }
57
58    fn bounding_rectangle_spec(&self) -> Option<Rect<P::Num>> {
59        self.contours()
60            .filter_map(|c| c.bounding_rectangle())
61            .collect()
62    }
63}