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}