galileo_types/
geometry.rs1use serde::{Deserialize, Serialize};
7
8use crate::cartesian::{CartesianPoint2d, Rect};
9use crate::geo::Projection;
10use crate::geometry_type::{CartesianSpace2d, GeometryType, PointGeometryType};
11use crate::impls::{Contour, MultiContour, MultiPoint, MultiPolygon, Polygon};
12
13#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize, Serialize)]
16pub enum Geom<P> {
17 Point(P),
19 MultiPoint(MultiPoint<P>),
21 Contour(Contour<P>),
23 MultiContour(MultiContour<P>),
25 Polygon(Polygon<P>),
27 MultiPolygon(MultiPolygon<P>),
29}
30
31impl<P: GeometryType + Copy> Geometry for Geom<P> {
32 type Point = P;
33
34 fn project<Proj>(&self, projection: &Proj) -> Option<Geom<Proj::OutPoint>>
35 where
36 Proj: Projection<InPoint = <Self as Geometry>::Point> + ?Sized,
37 {
38 match &self {
39 Geom::Point(v) => Some(Geom::Point(projection.project(v)?)),
40 Geom::MultiPoint(v) => v.project(projection),
41 Geom::Contour(v) => v.project(projection),
42 Geom::MultiContour(v) => v.project(projection),
43 Geom::Polygon(v) => v.project(projection),
44 Geom::MultiPolygon(v) => v.project(projection),
45 }
46 }
47}
48
49impl<P> CartesianGeometry2d<P> for Geom<P>
50where
51 P: CartesianPoint2d + GeometryType<Type = PointGeometryType, Space = CartesianSpace2d> + Copy,
52{
53 fn is_point_inside<Other: CartesianPoint2d<Num = P::Num>>(
54 &self,
55 point: &Other,
56 tolerance: P::Num,
57 ) -> bool {
58 match self {
59 Geom::Point(v) => v.is_point_inside(point, tolerance),
60 Geom::MultiPoint(v) => v.is_point_inside(point, tolerance),
61 Geom::Contour(v) => v.is_point_inside(point, tolerance),
62 Geom::MultiContour(v) => v.is_point_inside(point, tolerance),
63 Geom::Polygon(v) => v.is_point_inside(point, tolerance),
64 Geom::MultiPolygon(v) => v.is_point_inside(point, tolerance),
65 }
66 }
67
68 fn bounding_rectangle(&self) -> Option<Rect<P::Num>> {
69 match self {
70 Geom::Point(v) => v.bounding_rectangle(),
71 Geom::MultiPoint(v) => v.bounding_rectangle(),
72 Geom::Contour(v) => v.bounding_rectangle(),
73 Geom::MultiContour(v) => v.bounding_rectangle(),
74 Geom::Polygon(v) => v.bounding_rectangle(),
75 Geom::MultiPolygon(v) => v.bounding_rectangle(),
76 }
77 }
78}
79
80pub trait Geometry {
85 type Point;
87 fn project<Proj>(&self, projection: &Proj) -> Option<Geom<Proj::OutPoint>>
93 where
94 Proj: Projection<InPoint = Self::Point> + ?Sized;
95}
96
97pub trait CartesianGeometry2d<P: CartesianPoint2d>: Geometry<Point = P> {
99 fn is_point_inside<Other: CartesianPoint2d<Num = P::Num>>(
101 &self,
102 point: &Other,
103 tolerance: P::Num,
104 ) -> bool;
105 fn bounding_rectangle(&self) -> Option<Rect<P::Num>>;
107}
108
109impl<P> From<P> for Geom<P> {
110 fn from(value: P) -> Self {
111 Self::Point(value)
112 }
113}
114
115impl<P> From<Contour<P>> for Geom<P> {
116 fn from(value: Contour<P>) -> Self {
117 Self::Contour(value)
118 }
119}
120
121impl<P> From<Polygon<P>> for Geom<P> {
122 fn from(value: Polygon<P>) -> Self {
123 Self::Polygon(value)
124 }
125}
126
127impl<P> From<MultiPolygon<P>> for Geom<P> {
128 fn from(value: MultiPolygon<P>) -> Self {
129 Self::MultiPolygon(value)
130 }
131}
132
133pub trait GeometrySpecialization<GT, ST>: GeometryType {
135 type Point;
137
138 fn project_spec<Proj>(&self, projection: &Proj) -> Option<Geom<Proj::OutPoint>>
140 where
141 Proj: Projection<InPoint = Self::Point> + ?Sized;
142}
143
144impl<T> Geometry for T
145where
146 T: GeometrySpecialization<<Self as GeometryType>::Type, <Self as GeometryType>::Space>,
147{
148 type Point = <Self as GeometrySpecialization<
149 <Self as GeometryType>::Type,
150 <Self as GeometryType>::Space,
151 >>::Point;
152
153 fn project<Proj>(&self, projection: &Proj) -> Option<Geom<Proj::OutPoint>>
154 where
155 Proj: Projection<InPoint = Self::Point> + ?Sized,
156 {
157 <Self as GeometrySpecialization<
158 <Self as GeometryType>::Type,
159 <Self as GeometryType>::Space,
160 >>::project_spec(self, projection)
161 }
162}
163
164pub trait CartesianGeometry2dSpecialization<P: CartesianPoint2d + Copy, GT>:
166 GeometryType<Space = CartesianSpace2d> + Geometry<Point = P>
167{
168 fn is_point_inside_spec<Other: CartesianPoint2d<Num = P::Num>>(
170 &self,
171 point: &Other,
172 tolerance: P::Num,
173 ) -> bool;
174 fn bounding_rectangle_spec(&self) -> Option<Rect<P::Num>>;
176}
177
178impl<P, T> CartesianGeometry2d<P> for T
179where
180 P: CartesianPoint2d + Copy,
181 T: CartesianGeometry2dSpecialization<P, <Self as GeometryType>::Type>,
182{
183 fn is_point_inside<Other: CartesianPoint2d<Num = P::Num>>(
184 &self,
185 point: &Other,
186 tolerance: P::Num,
187 ) -> bool {
188 self.is_point_inside_spec(point, tolerance)
189 }
190
191 fn bounding_rectangle(&self) -> Option<Rect<P::Num>> {
192 self.bounding_rectangle_spec()
193 }
194}