Skip to main content

ecitygml_core/operations/
geometry_index.rs

1use crate::model::common::{CityObjectClass, LevelOfDetail};
2use crate::model::core::{
3    AbstractCityObject, AbstractOccupiedSpace, AbstractSpace, AbstractThematicSurface,
4    AsAbstractCityObject, AsAbstractFeature, AsAbstractOccupiedSpace, AsAbstractSpace,
5    CityObjectRef, ImplicitGeometry,
6};
7use crate::model::core::{AsAbstractThematicSurface, CityModel};
8use egml::model::base::Id;
9use egml::model::geometry::Envelope;
10use egml::model::geometry::aggregates::{MultiCurve, MultiSurface};
11use egml::model::geometry::primitives::Solid;
12use std::collections::HashMap;
13
14#[derive(Debug, Clone, PartialEq, Default)]
15pub struct CityModelGeometryIndex {
16    pub objects: HashMap<Id, CityObjectGeometry>,
17}
18
19impl CityModelGeometryIndex {
20    pub fn from_city_model(mut city_model: CityModel) -> Self {
21        city_model.refresh_bounded_by_recursive();
22
23        let city_objects: HashMap<Id, CityObjectGeometry> = city_model
24            .iter_city_object()
25            .map(|x| (x.id().clone(), CityObjectGeometry::from_city_object(x)))
26            .collect();
27
28        Self {
29            objects: city_objects,
30        }
31    }
32
33    pub fn objects_len(&self) -> usize {
34        self.objects.len()
35    }
36
37    pub fn object_ids(&self) -> Vec<String> {
38        self.objects.keys().map(|x| x.to_string()).collect()
39    }
40
41    pub fn get(&self, id: &Id) -> Option<&CityObjectGeometry> {
42        self.objects.get(id)
43    }
44}
45
46#[derive(Debug, Clone, PartialEq)]
47pub struct CityObjectGeometry {
48    pub base: AbstractCityObject,
49    pub class: CityObjectClass,
50    pub implicit_geometries: HashMap<LevelOfDetail, ImplicitGeometry>,
51    pub multi_surfaces: HashMap<LevelOfDetail, MultiSurface>,
52    pub multi_curves: HashMap<LevelOfDetail, MultiCurve>,
53    pub solids: HashMap<LevelOfDetail, Solid>,
54}
55
56impl CityObjectGeometry {
57    pub fn new(abstract_space: AbstractCityObject, class: CityObjectClass) -> Self {
58        Self {
59            base: abstract_space,
60            class,
61            implicit_geometries: HashMap::new(),
62            multi_surfaces: HashMap::new(),
63            multi_curves: HashMap::new(),
64            solids: HashMap::new(),
65        }
66    }
67
68    pub fn from_city_object(city_object: CityObjectRef) -> Self {
69        let city_object_class = city_object.city_object_class();
70
71        match city_object {
72            CityObjectRef::AuxiliaryTrafficArea(x) => Self::from_abstract_thematic_surface(
73                city_object_class,
74                x.abstract_thematic_surface(),
75            ),
76            CityObjectRef::AuxiliaryTrafficSpace(x) => {
77                Self::from_abstract_space(city_object_class, x.abstract_space())
78            }
79            CityObjectRef::Building(x) => {
80                Self::from_abstract_space(city_object_class, x.abstract_space())
81            }
82            CityObjectRef::BuildingConstructiveElement(x) => {
83                Self::from_abstract_occupied_space(city_object_class, x.abstract_occupied_space())
84            }
85            CityObjectRef::BuildingInstallation(x) => {
86                Self::from_abstract_occupied_space(city_object_class, x.abstract_occupied_space())
87            }
88            CityObjectRef::BuildingRoom(x) => {
89                Self::from_abstract_space(city_object_class, x.abstract_space())
90            }
91            CityObjectRef::CityFurniture(x) => {
92                Self::from_abstract_occupied_space(city_object_class, x.abstract_occupied_space())
93            }
94            CityObjectRef::DoorSurface(x) => Self::from_abstract_thematic_surface(
95                city_object_class,
96                x.abstract_thematic_surface(),
97            ),
98            CityObjectRef::GroundSurface(x) => Self::from_abstract_thematic_surface(
99                city_object_class,
100                x.abstract_thematic_surface(),
101            ),
102            CityObjectRef::Intersection(x) => {
103                Self::from_abstract_space(city_object_class, x.abstract_space())
104            }
105            CityObjectRef::ReliefFeature(x) => {
106                CityObjectGeometry::new(x.abstract_city_object().clone(), city_object_class)
107            }
108            CityObjectRef::Road(x) => {
109                Self::from_abstract_space(city_object_class, x.abstract_space())
110            }
111            CityObjectRef::RoofSurface(x) => Self::from_abstract_thematic_surface(
112                city_object_class,
113                x.abstract_thematic_surface(),
114            ),
115            CityObjectRef::Section(x) => {
116                Self::from_abstract_space(city_object_class, x.abstract_space())
117            }
118            CityObjectRef::SolitaryVegetationObject(x) => {
119                Self::from_abstract_occupied_space(city_object_class, x.abstract_occupied_space())
120            }
121            CityObjectRef::Storey(x) => {
122                Self::from_abstract_space(city_object_class, x.abstract_space())
123            }
124            CityObjectRef::TinRelief(x) => {
125                CityObjectGeometry::new(x.abstract_city_object().clone(), city_object_class)
126            }
127            CityObjectRef::TrafficArea(x) => Self::from_abstract_thematic_surface(
128                city_object_class,
129                x.abstract_thematic_surface(),
130            ),
131            CityObjectRef::TrafficSpace(x) => {
132                Self::from_abstract_space(city_object_class, x.abstract_space())
133            }
134            CityObjectRef::WallSurface(x) => Self::from_abstract_thematic_surface(
135                city_object_class,
136                x.abstract_thematic_surface(),
137            ),
138            CityObjectRef::WindowSurface(x) => Self::from_abstract_thematic_surface(
139                city_object_class,
140                x.abstract_thematic_surface(),
141            ),
142        }
143    }
144
145    pub fn from_abstract_space(class: CityObjectClass, space: &AbstractSpace) -> Self {
146        let solids: HashMap<LevelOfDetail, Solid> = space
147            .solids_by_lod()
148            .into_iter()
149            .map(|(lod, x)| (lod, x.clone()))
150            .collect();
151
152        let multi_surfaces: HashMap<LevelOfDetail, MultiSurface> = space
153            .multi_surfaces_by_lod()
154            .into_iter()
155            .map(|(lod, x)| (lod, x.clone()))
156            .collect();
157
158        let multi_curves: HashMap<LevelOfDetail, MultiCurve> = space
159            .multi_curves_by_lod()
160            .into_iter()
161            .map(|(lod, x)| (lod, x.clone()))
162            .collect();
163
164        Self {
165            base: space.abstract_city_object().clone(),
166            class,
167            implicit_geometries: HashMap::new(),
168            multi_surfaces,
169            multi_curves,
170            solids,
171        }
172    }
173
174    pub fn from_abstract_occupied_space(
175        class: CityObjectClass,
176        occupied_space: &AbstractOccupiedSpace,
177    ) -> Self {
178        let mut city_object_geometry = CityObjectGeometry::from_abstract_space(
179            class,
180            &occupied_space.abstract_physical_space.abstract_space,
181        );
182
183        let implicit_representations: HashMap<LevelOfDetail, ImplicitGeometry> = occupied_space
184            .implicit_representations_by_lod()
185            .into_iter()
186            .map(|(lod, x)| (lod, x.clone()))
187            .collect();
188
189        city_object_geometry.implicit_geometries = implicit_representations;
190        city_object_geometry
191    }
192
193    pub fn from_abstract_thematic_surface(
194        class: CityObjectClass,
195        thematic_surface: &AbstractThematicSurface,
196    ) -> Self {
197        let multi_surfaces: HashMap<LevelOfDetail, MultiSurface> = thematic_surface
198            .multi_surfaces_by_lod()
199            .into_iter()
200            .map(|(lod, x)| (lod, x.clone()))
201            .collect();
202
203        Self {
204            base: thematic_surface.abstract_city_object().clone(),
205            class,
206            implicit_geometries: HashMap::new(),
207            multi_surfaces,
208            solids: HashMap::new(),
209            multi_curves: HashMap::new(),
210        }
211    }
212
213    pub fn id(&self) -> &Id {
214        self.base.id()
215    }
216
217    pub fn envelope(&self) -> Option<&Envelope> {
218        self.base.bounded_by()
219    }
220}