Skip to main content

egml_core/model/geometry/
abstract_geometry_kind.rs

1use crate::model::common::{
2    ApplyTransform, ComputeEnvelope, GeometryType, HasGeometryType, IterGeometries, Triangulate,
3    Triangulation,
4};
5use crate::model::geometry::aggregates::AbstractGeometricAggregateKind;
6use crate::model::geometry::primitives::AbstractGeometricPrimitiveKind;
7use crate::model::geometry::refs::AbstractGeometryKindRef;
8use crate::model::geometry::{
9    AbstractGeometry, AsAbstractGeometry, AsAbstractGeometryMut, Envelope,
10};
11use crate::{Error, impl_abstract_geometry_mut_traits, impl_abstract_geometry_traits};
12use nalgebra::{Isometry3, Rotation3, Scale3, Transform3, Vector3};
13
14#[derive(Debug, Clone, PartialEq)]
15pub enum AbstractGeometryKind {
16    AbstractGeometricAggregateKind(AbstractGeometricAggregateKind),
17    AbstractGeometricPrimitiveKind(AbstractGeometricPrimitiveKind),
18    // AbstractGeometricComplexKind(AbstractGeometricComplexKind),
19    // ImplicitGeometryKind(ImplicitGeometryKind),
20}
21
22impl AsAbstractGeometry for AbstractGeometryKind {
23    fn abstract_geometry(&self) -> &AbstractGeometry {
24        match self {
25            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.abstract_geometry(),
26            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.abstract_geometry(),
27            // GeometryKind::GeometricComplexKind(x) => x.abstract_geometry(),
28        }
29    }
30}
31
32impl AsAbstractGeometryMut for AbstractGeometryKind {
33    fn abstract_geometry_mut(&mut self) -> &mut AbstractGeometry {
34        match self {
35            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.abstract_geometry_mut(),
36            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.abstract_geometry_mut(),
37            // GeometryKind::GeometricComplexKind(x) => x.abstract_geometry_mut(),
38            // GeometryKind::ImplicitGeometryKind(x) => x.abstract_geometry_mut(),
39        }
40    }
41}
42
43impl_abstract_geometry_traits!(AbstractGeometryKind);
44impl_abstract_geometry_mut_traits!(AbstractGeometryKind);
45
46impl HasGeometryType for AbstractGeometryKind {
47    fn geometry_type(&self) -> GeometryType {
48        match self {
49            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.geometry_type(),
50            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.geometry_type(),
51        }
52    }
53}
54
55#[macro_export]
56macro_rules! impl_from_for_abstract_geometry_kind {
57    ($variant:ident, $type:ty) => {
58        impl From<$type> for $crate::model::geometry::AbstractGeometryKind {
59            #[allow(unreachable_code)]
60            fn from(x: $type) -> Self {
61                $crate::model::geometry::AbstractGeometryKind::$variant(x.into())
62            }
63        }
64        $crate::impl_from_for_abstract_gml_kind!(AbstractGeometryKind, $type);
65    };
66    ($variant:ident) => {
67        $crate::impl_from_for_abstract_geometry_kind!($variant, $variant);
68    };
69}
70
71#[macro_export]
72macro_rules! impl_try_from_for_abstract_geometry_kind {
73    ($variant:ident, $type:ty) => {
74        impl TryFrom<$crate::model::geometry::AbstractGeometryKind> for $type {
75            type Error = ();
76            #[allow(unreachable_code)]
77            fn try_from(x: $crate::model::geometry::AbstractGeometryKind) -> Result<Self, ()> {
78                match x {
79                    $crate::model::geometry::AbstractGeometryKind::$variant(k) => {
80                        k.try_into().map_err(|_| ())
81                    }
82                    #[allow(unreachable_patterns)]
83                    _ => Err(()),
84                }
85            }
86        }
87        $crate::impl_try_from_for_abstract_gml_kind!(AbstractGeometryKind, $type);
88    };
89    ($variant:ident) => {
90        $crate::impl_try_from_for_abstract_geometry_kind!($variant, $variant);
91    };
92}
93
94impl_from_for_abstract_geometry_kind!(AbstractGeometricAggregateKind);
95impl_from_for_abstract_geometry_kind!(AbstractGeometricPrimitiveKind);
96impl_try_from_for_abstract_geometry_kind!(AbstractGeometricAggregateKind);
97impl_try_from_for_abstract_geometry_kind!(AbstractGeometricPrimitiveKind);
98
99impl Triangulate for AbstractGeometryKind {
100    fn triangulate(&self) -> Result<Triangulation, Error> {
101        match self {
102            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.triangulate(),
103            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.triangulate(),
104        }
105    }
106}
107
108impl IterGeometries for AbstractGeometryKind {
109    fn iter_geometries(&self) -> Box<dyn Iterator<Item = AbstractGeometryKindRef<'_>> + '_> {
110        match self {
111            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.iter_geometries(),
112            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.iter_geometries(),
113        }
114    }
115}
116
117impl ApplyTransform for AbstractGeometryKind {
118    fn apply_transform(&mut self, transform: Transform3<f64>) {
119        match self {
120            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.apply_transform(transform),
121            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.apply_transform(transform),
122            // GeometryKind::GeometricComplexKind(x) => x.apply_transform(transform),
123            // GeometryKind::ImplicitGeometryKind(x) => x.apply_transform(transform),
124        }
125    }
126
127    fn apply_isometry(&mut self, isometry: Isometry3<f64>) {
128        match self {
129            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.apply_isometry(isometry),
130            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.apply_isometry(isometry),
131            // GeometryKind::GeometricComplexKind(x) => x.apply_isometry(isometry),
132            // GeometryKind::ImplicitGeometryKind(x) => x.apply_isometry(isometry),
133        }
134    }
135
136    fn apply_translation(&mut self, vector: Vector3<f64>) {
137        match self {
138            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.apply_translation(vector),
139            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.apply_translation(vector),
140            // GeometryKind::GeometricComplexKind(x) => x.apply_translation(vector),
141            // GeometryKind::ImplicitGeometryKind(x) => x.apply_translation(vector),
142        }
143    }
144
145    fn apply_rotation(&mut self, rotation: Rotation3<f64>) {
146        match self {
147            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.apply_rotation(rotation),
148            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.apply_rotation(rotation),
149            // GeometryKind::GeometricComplexKind(x) => x.apply_rotation(rotation),
150            // GeometryKind::ImplicitGeometryKind(x) => x.apply_rotation(rotation),
151        }
152    }
153
154    fn apply_scale(&mut self, scale: Scale3<f64>) {
155        match self {
156            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.apply_scale(scale),
157            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.apply_scale(scale),
158            // GeometryKind::GeometricComplexKind(x) => x.apply_scale(scale),
159            // GeometryKind::ImplicitGeometryKind(x) => x.apply_scale(scale),
160        }
161    }
162}
163
164impl ComputeEnvelope for AbstractGeometryKind {
165    fn compute_envelope(&self) -> Option<Envelope> {
166        match self {
167            AbstractGeometryKind::AbstractGeometricAggregateKind(x) => x.compute_envelope(),
168            AbstractGeometryKind::AbstractGeometricPrimitiveKind(x) => x.compute_envelope(),
169            // GeometryKind::GeometricComplexKind(x) => x.compute_envelope(),
170            // GeometryKind::ImplicitGeometryKind(x) => x.compute_envelope(),
171        }
172    }
173}
174
175#[cfg(test)]
176mod tests {
177    use super::AbstractGeometryKind;
178    use crate::model::common::{GeometryType, HasGeometryType};
179    use crate::model::geometry::DirectPosition;
180    use crate::model::geometry::aggregates::{AbstractGeometricAggregateKind, MultiSurface};
181    use crate::model::geometry::primitives::{
182        AbstractGeometricPrimitiveKind, AbstractRingKind, AbstractRingProperty,
183        AbstractSurfaceKind, AbstractSurfaceProperty, LinearRing, Point, Polygon,
184    };
185
186    #[test]
187    fn point_reports_point_geometry_type() {
188        let kind = AbstractGeometryKind::AbstractGeometricPrimitiveKind(
189            AbstractGeometricPrimitiveKind::Point(Point::new(
190                DirectPosition::new(1.0, 2.0, 3.0).unwrap(),
191            )),
192        );
193
194        assert_eq!(kind.geometry_type(), GeometryType::Point);
195    }
196
197    #[test]
198    fn polygon_nested_three_levels_deep_reports_polygon_geometry_type() {
199        let points = vec![
200            DirectPosition::new(0.0, 0.0, 0.0).unwrap(),
201            DirectPosition::new(1.0, 0.0, 0.0).unwrap(),
202            DirectPosition::new(0.0, 1.0, 0.0).unwrap(),
203        ];
204        let ring = AbstractRingKind::LinearRing(LinearRing::new(points).unwrap());
205        let polygon = Polygon::new(Some(AbstractRingProperty::from_object(ring)), []).unwrap();
206        let kind = AbstractGeometryKind::AbstractGeometricPrimitiveKind(
207            AbstractGeometricPrimitiveKind::AbstractSurfaceKind(AbstractSurfaceKind::Polygon(
208                polygon,
209            )),
210        );
211
212        assert_eq!(kind.geometry_type(), GeometryType::Polygon);
213    }
214
215    #[test]
216    fn multi_surface_reports_multi_surface_geometry_type() {
217        let points = vec![
218            DirectPosition::new(0.0, 0.0, 0.0).unwrap(),
219            DirectPosition::new(1.0, 0.0, 0.0).unwrap(),
220            DirectPosition::new(0.0, 1.0, 0.0).unwrap(),
221        ];
222        let ring = AbstractRingKind::LinearRing(LinearRing::new(points).unwrap());
223        let polygon = Polygon::new(Some(AbstractRingProperty::from_object(ring)), []).unwrap();
224        let member = AbstractSurfaceProperty::from_object(AbstractSurfaceKind::Polygon(polygon));
225        let multi_surface = MultiSurface::new([member]).unwrap();
226        let kind = AbstractGeometryKind::AbstractGeometricAggregateKind(
227            AbstractGeometricAggregateKind::MultiSurface(multi_surface),
228        );
229
230        assert_eq!(kind.geometry_type(), GeometryType::MultiSurface);
231    }
232}