galileo_types/
multi_contour.rs1use 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
9pub trait MultiContour {
11 type Contour: Contour;
13
14 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}