egml_core/model/geometry/
abstract_geometry_kind.rs1use 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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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}