Skip to main content

ecitygml_core/model/core/
city_model.rs

1use crate::model::building::Building;
2use crate::model::city_furniture::CityFurniture;
3use crate::model::core::{
4    AbstractFeature, AsAbstractFeature, AsAbstractFeatureMut, CityObjectKind, CityObjectRef,
5};
6use crate::model::transportation::Road;
7use crate::model::vegetation::SolitaryVegetationObject;
8use crate::operations::{Visitable, Visitor};
9use egml::model::base::Id;
10use egml::model::geometry::Envelope;
11use nalgebra::Isometry3;
12use rayon::prelude::*;
13
14#[derive(Debug, Clone, PartialEq)]
15pub struct CityModel {
16    pub(crate) abstract_feature: AbstractFeature,
17    pub city_objects: Vec<CityObjectKind>,
18}
19
20impl CityModel {
21    pub fn new(abstract_feature: AbstractFeature, city_objects: Vec<CityObjectKind>) -> Self {
22        Self {
23            abstract_feature,
24            city_objects,
25        }
26    }
27
28    pub fn from_city_models(city_models: Vec<Self>) -> Self {
29        let abstract_feature = AbstractFeature::new(Id::generate_uuid_v4());
30
31        let combined_city_objects: Vec<CityObjectKind> = city_models
32            .into_iter()
33            .flat_map(|x| x.city_objects)
34            .collect();
35
36        CityModel::new(abstract_feature, combined_city_objects)
37    }
38
39    pub fn is_empty(&self) -> bool {
40        self.city_objects.is_empty()
41    }
42
43    pub fn city_objects(&self) -> &Vec<CityObjectKind> {
44        &self.city_objects
45    }
46
47    pub fn city_objects_len(&self) -> usize {
48        self.city_objects.len()
49    }
50
51    pub fn iter_city_object<'a>(&'a self) -> impl Iterator<Item = CityObjectRef<'a>> + 'a {
52        self.city_objects.iter().flat_map(|x| x.iter_city_object())
53    }
54
55    pub fn refresh_bounded_by_recursive(&mut self) {
56        self.city_objects
57            .par_iter_mut()
58            .for_each(|x| x.refresh_bounded_by_recursive());
59
60        let envelopes: Vec<Envelope> = self
61            .city_objects
62            .iter()
63            .filter_map(|x| x.bounded_by())
64            .cloned()
65            .collect();
66
67        self.set_bounded_by(Envelope::from_envelopes(&envelopes));
68    }
69
70    pub fn apply_transform_recursive(&mut self, m: &Isometry3<f64>) {
71        self.city_objects
72            .par_iter_mut()
73            .for_each(|x| x.apply_transform_recursive(m));
74    }
75
76    pub fn filter_city_objects_by_envelope(&mut self, filter_envelope: &Envelope) {
77        self.city_objects.retain(|obj| {
78            obj.bounded_by()
79                .is_some_and(|env| filter_envelope.contains_envelope_partially(env))
80        });
81    }
82
83    pub fn roads(&self) -> Vec<&Road> {
84        self.city_objects
85            .iter()
86            .filter_map(|x| match x {
87                CityObjectKind::Road(x) => Some(x),
88                _ => None,
89            })
90            .collect()
91    }
92
93    pub fn buildings(&self) -> Vec<&Building> {
94        self.city_objects
95            .iter()
96            .filter_map(|x| match x {
97                CityObjectKind::Building(x) => Some(x),
98                _ => None,
99            })
100            .collect()
101    }
102
103    pub fn solitary_vegetation_objects(&self) -> Vec<&SolitaryVegetationObject> {
104        self.city_objects
105            .iter()
106            .filter_map(|x| match x {
107                CityObjectKind::SolitaryVegetationObject(x) => Some(x),
108                _ => None,
109            })
110            .collect()
111    }
112
113    pub fn city_furniture_objects(&self) -> Vec<&CityFurniture> {
114        self.city_objects
115            .iter()
116            .filter_map(|x| match x {
117                CityObjectKind::CityFurniture(x) => Some(x),
118                _ => None,
119            })
120            .collect()
121    }
122}
123
124impl AsAbstractFeature for CityModel {
125    fn abstract_feature(&self) -> &AbstractFeature {
126        &self.abstract_feature
127    }
128}
129
130impl AsAbstractFeatureMut for CityModel {
131    fn abstract_feature_mut(&mut self) -> &mut AbstractFeature {
132        &mut self.abstract_feature
133    }
134}
135
136impl Visitable for CityModel {
137    fn accept<V: Visitor>(&self, visitor: &mut V) {
138        visitor.visit_city_model(self);
139
140        for feature in &self.city_objects {
141            match feature {
142                CityObjectKind::Building(x) => {
143                    x.accept(visitor);
144                }
145                CityObjectKind::BuildingConstructiveElement(x) => {
146                    x.accept(visitor);
147                }
148                CityObjectKind::BuildingInstallation(x) => {
149                    x.accept(visitor);
150                }
151                CityObjectKind::BuildingRoom(x) => {
152                    x.accept(visitor);
153                }
154                CityObjectKind::CityFurniture(x) => {
155                    x.accept(visitor);
156                }
157                CityObjectKind::ReliefFeature(x) => {
158                    x.accept(visitor);
159                }
160                CityObjectKind::Road(x) => {
161                    x.accept(visitor);
162                }
163                CityObjectKind::SolitaryVegetationObject(x) => {
164                    x.accept(visitor);
165                }
166                CityObjectKind::Storey(x) => {
167                    x.accept(visitor);
168                }
169                CityObjectKind::TinRelief(x) => {
170                    x.accept(visitor);
171                }
172                CityObjectKind::TrafficSpace(x) => {
173                    x.accept(visitor);
174                }
175                CityObjectKind::AuxiliaryTrafficSpace(x) => {
176                    x.accept(visitor);
177                }
178                CityObjectKind::TrafficArea(x) => {
179                    x.accept(visitor);
180                }
181                CityObjectKind::AuxiliaryTrafficArea(x) => {
182                    x.accept(visitor);
183                }
184                CityObjectKind::Section(x) => {
185                    x.accept(visitor);
186                }
187                CityObjectKind::Intersection(x) => {
188                    x.accept(visitor);
189                }
190                CityObjectKind::DoorSurface(x) => {
191                    x.accept(visitor);
192                }
193                CityObjectKind::GroundSurface(x) => {
194                    x.accept(visitor);
195                }
196                CityObjectKind::RoofSurface(x) => {
197                    x.accept(visitor);
198                }
199                CityObjectKind::WallSurface(x) => {
200                    x.accept(visitor);
201                }
202                CityObjectKind::WindowSurface(x) => {
203                    x.accept(visitor);
204                }
205            }
206        }
207    }
208}