ecitygml_core/model/
core.rs

1use crate::operations::FeatureWithGeometry;
2use egml::model::base::AbstractGml;
3use egml::model::geometry;
4use egml::model::geometry::{DirectPosition, Envelope};
5use egml::operations::geometry::Geometry;
6use nalgebra::Isometry3;
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct CityObject {
10    pub abstract_gml: AbstractGml,
11    pub generic_attributes: Vec<GenericAttribute>,
12}
13
14impl CityObject {
15    pub fn new(abstract_gml: AbstractGml, generic_attributes: Vec<GenericAttribute>) -> Self {
16        Self {
17            abstract_gml,
18            generic_attributes,
19        }
20    }
21}
22
23#[derive(Debug, Clone, PartialEq, Default)]
24pub struct ImplicitGeometry {
25    pub reference_point: geometry::DirectPosition,
26}
27
28impl ImplicitGeometry {
29    pub fn new(reference_point: geometry::DirectPosition) -> Self {
30        Self { reference_point }
31    }
32}
33
34impl Geometry for ImplicitGeometry {
35    fn points(&self) -> Vec<&DirectPosition> {
36        vec![&self.reference_point]
37    }
38
39    fn apply_transform(&mut self, m: &Isometry3<f64>) {
40        self.reference_point.apply_transform(m);
41    }
42}
43
44#[derive(Debug, Clone, PartialEq)]
45pub struct Space {
46    pub city_object: CityObject,
47
48    pub lod1_solid: Option<geometry::Solid>,
49    pub lod2_solid: Option<geometry::Solid>,
50    pub lod3_solid: Option<geometry::Solid>,
51
52    pub lod0_multi_surface: Option<geometry::MultiSurface>,
53    pub lod2_multi_surface: Option<geometry::MultiSurface>,
54    pub lod3_multi_surface: Option<geometry::MultiSurface>,
55}
56
57impl Space {
58    pub fn new(city_object: CityObject) -> Self {
59        Self {
60            city_object,
61            lod1_solid: None,
62            lod2_solid: None,
63            lod3_solid: None,
64            lod0_multi_surface: None,
65            lod2_multi_surface: None,
66            lod3_multi_surface: None,
67        }
68    }
69}
70
71impl FeatureWithGeometry for Space {
72    fn envelope(&self) -> Option<Envelope> {
73        let envelopes: Vec<Option<Envelope>> = vec![
74            self.lod1_solid.as_ref().map(|x| x.envelope()),
75            self.lod2_solid.as_ref().map(|x| x.envelope()),
76            self.lod3_solid.as_ref().map(|x| x.envelope()),
77            self.lod0_multi_surface.as_ref().map(|x| x.envelope()),
78            self.lod2_multi_surface.as_ref().map(|x| x.envelope()),
79            self.lod3_multi_surface.as_ref().map(|x| x.envelope()),
80        ];
81
82        Envelope::from_optional_envelopes(&envelopes).expect("should work")
83    }
84
85    fn apply_transform(&mut self, m: &Isometry3<f64>) {
86        if let Some(g) = &mut self.lod0_multi_surface {
87            g.apply_transform(m);
88        }
89        if let Some(g) = &mut self.lod1_solid {
90            g.apply_transform(m);
91        }
92        if let Some(g) = &mut self.lod2_solid {
93            g.apply_transform(m);
94        }
95        if let Some(g) = &mut self.lod3_solid {
96            g.apply_transform(m);
97        }
98
99        if let Some(g) = &mut self.lod0_multi_surface {
100            g.apply_transform(m);
101        }
102        if let Some(g) = &mut self.lod2_multi_surface {
103            g.apply_transform(m);
104        }
105        if let Some(g) = &mut self.lod3_multi_surface {
106            g.apply_transform(m);
107        }
108    }
109}
110
111#[derive(Debug, Clone, PartialEq)]
112pub struct OccupiedSpace {
113    pub space: Space,
114    pub lod1_implicit_representation: Option<ImplicitGeometry>,
115    pub lod2_implicit_representation: Option<ImplicitGeometry>,
116    pub lod3_implicit_representation: Option<ImplicitGeometry>,
117}
118
119impl OccupiedSpace {
120    pub fn new(space: Space) -> Self {
121        Self {
122            space,
123            lod1_implicit_representation: None,
124            lod2_implicit_representation: None,
125            lod3_implicit_representation: None,
126        }
127    }
128}
129
130impl FeatureWithGeometry for OccupiedSpace {
131    fn envelope(&self) -> Option<Envelope> {
132        let envelopes: Vec<Option<Envelope>> = vec![
133            self.space.envelope(),
134            self.lod1_implicit_representation
135                .as_ref()
136                .map(|x| x.envelope()),
137            self.lod2_implicit_representation
138                .as_ref()
139                .map(|x| x.envelope()),
140            self.lod3_implicit_representation
141                .as_ref()
142                .map(|x| x.envelope()),
143        ];
144
145        Envelope::from_optional_envelopes(&envelopes).expect("should work")
146    }
147
148    fn apply_transform(&mut self, m: &Isometry3<f64>) {
149        self.space.apply_transform(m);
150
151        if let Some(g) = &mut self.lod1_implicit_representation {
152            g.apply_transform(m);
153        }
154        if let Some(g) = &mut self.lod2_implicit_representation {
155            g.apply_transform(m);
156        }
157        if let Some(g) = &mut self.lod3_implicit_representation {
158            g.apply_transform(m);
159        }
160    }
161}
162
163#[derive(Debug, Clone, PartialEq)]
164pub struct ThematicSurface {
165    pub city_object: CityObject,
166    pub lod0_multi_surface: Option<geometry::MultiSurface>,
167    pub lod1_multi_surface: Option<geometry::MultiSurface>,
168    pub lod2_multi_surface: Option<geometry::MultiSurface>,
169    pub lod3_multi_surface: Option<geometry::MultiSurface>,
170}
171
172impl ThematicSurface {
173    pub fn new(city_object: CityObject) -> Self {
174        Self {
175            city_object,
176            lod0_multi_surface: None,
177            lod1_multi_surface: None,
178            lod2_multi_surface: None,
179            lod3_multi_surface: None,
180        }
181    }
182}
183
184impl FeatureWithGeometry for ThematicSurface {
185    fn envelope(&self) -> Option<Envelope> {
186        let envelopes: Vec<Option<Envelope>> = vec![
187            self.lod0_multi_surface.as_ref().map(|x| x.envelope()),
188            self.lod1_multi_surface.as_ref().map(|x| x.envelope()),
189            self.lod2_multi_surface.as_ref().map(|x| x.envelope()),
190            self.lod3_multi_surface.as_ref().map(|x| x.envelope()),
191        ];
192
193        Envelope::from_optional_envelopes(&envelopes).expect("should work")
194    }
195
196    fn apply_transform(&mut self, m: &Isometry3<f64>) {
197        if let Some(g) = &mut self.lod0_multi_surface {
198            g.apply_transform(m);
199        }
200        if let Some(g) = &mut self.lod1_multi_surface {
201            g.apply_transform(m);
202        }
203        if let Some(g) = &mut self.lod2_multi_surface {
204            g.apply_transform(m);
205        }
206        if let Some(g) = &mut self.lod3_multi_surface {
207            g.apply_transform(m);
208        }
209    }
210}
211
212#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
213pub struct StringAttribute {
214    pub name: String,
215    pub value: String,
216}
217
218#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
219pub struct IntAttribute {
220    pub name: String,
221    pub value: i64,
222}
223
224#[derive(Debug, Clone, PartialEq, PartialOrd)]
225pub struct DoubleAttribute {
226    pub name: String,
227    pub value: f64,
228}
229
230#[derive(Debug, Clone, PartialEq)]
231pub enum GenericAttribute {
232    String(StringAttribute),
233    Int(IntAttribute),
234    Double(DoubleAttribute),
235}
236
237impl GenericAttribute {
238    pub fn name(&self) -> &str {
239        match self {
240            GenericAttribute::String(attr) => &attr.name,
241            GenericAttribute::Int(attr) => &attr.name,
242            GenericAttribute::Double(attr) => &attr.name,
243        }
244    }
245
246    pub fn as_string(&self) -> Option<&StringAttribute> {
247        if let GenericAttribute::String(attr) = self {
248            Some(attr)
249        } else {
250            None
251        }
252    }
253
254    pub fn as_int(&self) -> Option<&IntAttribute> {
255        if let GenericAttribute::Int(attr) = self {
256            Some(attr)
257        } else {
258            None
259        }
260    }
261
262    pub fn as_double(&self) -> Option<&DoubleAttribute> {
263        if let GenericAttribute::Double(attr) = self {
264            Some(attr)
265        } else {
266            None
267        }
268    }
269}
270
271impl From<StringAttribute> for GenericAttribute {
272    fn from(attr: StringAttribute) -> Self {
273        GenericAttribute::String(attr)
274    }
275}
276
277impl From<IntAttribute> for GenericAttribute {
278    fn from(attr: IntAttribute) -> Self {
279        GenericAttribute::Int(attr)
280    }
281}
282
283impl From<DoubleAttribute> for GenericAttribute {
284    fn from(attr: DoubleAttribute) -> Self {
285        GenericAttribute::Double(attr)
286    }
287}