egml_core/model/feature/
abstract_feature.rs1use crate::model::base::{AbstractGml, AsAbstractGml, AsAbstractGmlMut};
2use crate::model::common::ApplyTransform;
3use crate::model::feature::bounding_shape::BoundingShape;
4use crate::model::geometry::Envelope;
5use nalgebra::{Isometry3, Rotation3, Scale3, Transform3, Vector3};
6
7#[derive(Debug, Clone, PartialEq, Default)]
12pub struct AbstractFeature {
13 pub abstract_gml: AbstractGml,
15 bounded_by: Option<BoundingShape>,
17}
18
19impl AbstractFeature {
20 pub fn new() -> Self {
33 Self {
34 abstract_gml: AbstractGml::default(),
35 bounded_by: None,
36 }
37 }
38
39 pub fn from_abstract_gml(abstract_gml: AbstractGml) -> Self {
40 Self {
41 abstract_gml,
42 bounded_by: None,
43 }
44 }
45}
46
47impl ApplyTransform for AbstractFeature {
48 fn apply_transform(&mut self, transform: Transform3<f64>) {
49 if let Some(bounding_shape) = self.bounded_by.as_mut() {
50 bounding_shape.apply_transform(transform);
51 }
52 }
53
54 fn apply_isometry(&mut self, isometry: Isometry3<f64>) {
55 if let Some(bounding_shape) = self.bounded_by.as_mut() {
56 bounding_shape.apply_isometry(isometry);
57 }
58 }
59
60 fn apply_translation(&mut self, vector: Vector3<f64>) {
61 if let Some(bounding_shape) = self.bounded_by.as_mut() {
62 bounding_shape.apply_translation(vector);
63 }
64 }
65
66 fn apply_rotation(&mut self, rotation: Rotation3<f64>) {
67 if let Some(bounding_shape) = self.bounded_by.as_mut() {
68 bounding_shape.apply_rotation(rotation);
69 }
70 }
71
72 fn apply_scale(&mut self, scale: Scale3<f64>) {
73 if let Some(bounding_shape) = self.bounded_by.as_mut() {
74 bounding_shape.apply_scale(scale);
75 }
76 }
77}
78
79pub trait AsAbstractFeature: AsAbstractGml {
81 fn abstract_feature(&self) -> &AbstractFeature;
83
84 fn bounded_by(&self) -> Option<&BoundingShape> {
85 self.abstract_feature().bounded_by.as_ref()
86 }
87}
88
89pub trait AsAbstractFeatureMut: AsAbstractFeature + AsAbstractGmlMut {
91 fn abstract_feature_mut(&mut self) -> &mut AbstractFeature;
93
94 fn set_bounded_by(&mut self, bounded_by: Option<BoundingShape>) {
95 self.abstract_feature_mut().bounded_by = bounded_by;
96 }
97
98 fn bounded_by_mut(&mut self) -> &mut Option<BoundingShape> {
99 &mut self.abstract_feature_mut().bounded_by
100 }
101
102 fn set_bounding_shape_from_envelope(&mut self, envelope: Option<Envelope>) {
103 let bounding_shape = envelope.map(BoundingShape::new);
104 <Self as AsAbstractFeatureMut>::abstract_feature_mut(self).bounded_by = bounding_shape;
105 }
106}
107
108impl AsAbstractFeature for AbstractFeature {
109 fn abstract_feature(&self) -> &AbstractFeature {
110 self
111 }
112}
113
114impl AsAbstractFeatureMut for AbstractFeature {
115 fn abstract_feature_mut(&mut self) -> &mut AbstractFeature {
116 self
117 }
118}
119
120#[macro_export]
121macro_rules! impl_abstract_feature_traits {
122 ($type:ty) => {
123 $crate::impl_abstract_gml_traits!($type);
124
125 impl $crate::model::base::AsAbstractGml for $type {
126 fn abstract_gml(&self) -> &$crate::model::base::AbstractGml {
127 &<$type as $crate::model::feature::AsAbstractFeature>::abstract_feature(self)
128 .abstract_gml
129 }
130 }
131 };
132}
133
134#[macro_export]
135macro_rules! impl_abstract_feature_mut_traits {
136 ($type:ty) => {
137 $crate::impl_abstract_gml_mut_traits!($type);
138
139 impl $crate::model::base::AsAbstractGmlMut for $type {
140 fn abstract_gml_mut(&mut self) -> &mut $crate::model::base::AbstractGml {
141 &mut <$type as $crate::model::feature::AsAbstractFeatureMut>::abstract_feature_mut(
142 self,
143 )
144 .abstract_gml
145 }
146 }
147 };
148}
149
150impl_abstract_feature_traits!(AbstractFeature);
151impl_abstract_feature_mut_traits!(AbstractFeature);