ecitygml_transform/
filter.rs

1use crate::error::Error;
2use ecitygml_core::model::city_model::CitygmlModel;
3use ecitygml_core::model::core::{OccupiedSpace, Space, ThematicSurface};
4use egml::model::geometry::Envelope;
5use egml::operations::geometry::Geometry;
6
7pub fn filter_by_bounding_box(
8    mut city_model: CitygmlModel,
9    filter_envelope: &Envelope,
10) -> Result<CitygmlModel, Error> {
11    city_model.building.retain(|f| {
12        f.wall_surface
13            .iter()
14            .any(|w| contains_thematic_surface(filter_envelope, &w.thematic_surface))
15            || f.roof_surface
16                .iter()
17                .any(|w| contains_thematic_surface(filter_envelope, &w.thematic_surface))
18            || f.ground_surface
19                .iter()
20                .any(|w| contains_thematic_surface(filter_envelope, &w.thematic_surface))
21            || f.building_constructive_element
22                .iter()
23                .any(|w| contains_occupied_space(filter_envelope, &w.occupied_space))
24    });
25
26    // TODO road
27
28    city_model
29        .city_furniture
30        .retain(|f| contains_occupied_space(filter_envelope, &f.occupied_space));
31
32    city_model
33        .solitary_vegetation_object
34        .retain(|f| contains_occupied_space(filter_envelope, &f.occupied_space));
35
36    Ok(city_model)
37}
38
39fn contains_thematic_surface(
40    filter_envelope: &Envelope,
41    thematic_surface: &ThematicSurface,
42) -> bool {
43    if let Some(g) = &thematic_surface.lod0_multi_surface
44        && filter_envelope.contains_envelope_partially(&g.envelope())
45    {
46        return true;
47    }
48    if let Some(g) = &thematic_surface.lod1_multi_surface
49        && filter_envelope.contains_envelope_partially(&g.envelope())
50    {
51        return true;
52    }
53    if let Some(g) = &thematic_surface.lod2_multi_surface
54        && filter_envelope.contains_envelope_partially(&g.envelope())
55    {
56        return true;
57    }
58    if let Some(g) = &thematic_surface.lod3_multi_surface
59        && filter_envelope.contains_envelope_partially(&g.envelope())
60    {
61        return true;
62    }
63
64    false
65}
66
67fn contains_occupied_space(filter_envelope: &Envelope, occupied_space: &OccupiedSpace) -> bool {
68    if let Some(g) = &occupied_space.lod1_implicit_representation
69        && filter_envelope.contains(&g.reference_point)
70    {
71        return true;
72    }
73    if let Some(g) = &occupied_space.lod2_implicit_representation
74        && filter_envelope.contains(&g.reference_point)
75    {
76        return true;
77    }
78    if let Some(g) = &occupied_space.lod3_implicit_representation
79        && filter_envelope.contains(&g.reference_point)
80    {
81        return true;
82    }
83
84    contains_space(filter_envelope, &occupied_space.space)
85}
86
87fn contains_space(filter_envelope: &Envelope, space: &Space) -> bool {
88    if let Some(g) = &space.lod1_solid
89        && filter_envelope.contains_envelope_partially(&g.envelope())
90    {
91        return true;
92    }
93    if let Some(g) = &space.lod2_solid
94        && filter_envelope.contains_envelope_partially(&g.envelope())
95    {
96        return true;
97    }
98    if let Some(g) = &space.lod3_solid
99        && filter_envelope.contains_envelope_partially(&g.envelope())
100    {
101        return true;
102    }
103
104    if let Some(g) = &space.lod0_multi_surface
105        && filter_envelope.contains_envelope_partially(&g.envelope())
106    {
107        return true;
108    }
109    if let Some(g) = &space.lod2_multi_surface
110        && filter_envelope.contains_envelope_partially(&g.envelope())
111    {
112        return true;
113    }
114    if let Some(g) = &space.lod3_multi_surface
115        && filter_envelope.contains_envelope_partially(&g.envelope())
116    {
117        return true;
118    }
119
120    false
121}