egml_core/model/geometry/complexes/
composite_surface.rs1use crate::model::geometry::aggregates::AggregationType;
2use crate::model::geometry::primitives::{
3 AbstractSurface, AsAbstractSurface, AsAbstractSurfaceMut, SurfaceProperty, TriangulatedSurface,
4};
5use crate::model::geometry::{DirectPosition, Envelope};
6use crate::{Error, impl_abstract_surface_traits};
7use nalgebra::Isometry3;
8use rayon::iter::IntoParallelRefMutIterator;
9use rayon::iter::ParallelIterator;
10
11#[derive(Debug, Clone, PartialEq)]
18pub struct CompositeSurface {
19 pub(crate) abstract_surface: AbstractSurface,
20 surface_member: Vec<SurfaceProperty>,
21 aggregation_type: AggregationType,
22}
23
24impl CompositeSurface {
25 pub fn new(
31 surface_members: impl IntoIterator<Item = SurfaceProperty>,
32 aggregation_type: AggregationType,
33 ) -> Result<Self, Error> {
34 let surface_members: Vec<SurfaceProperty> = surface_members.into_iter().collect();
35 if surface_members.is_empty() {
36 return Err(Error::TooFewElements {
37 geometry: "gml:CompositeSurface",
38 minimum: 1,
39 spec: Some("OGC 07-036 §10.5.11.4"),
40 id: None,
41 detail: None,
42 });
43 }
44
45 Ok(CompositeSurface {
46 abstract_surface: AbstractSurface::default(),
47 surface_member: surface_members,
48 aggregation_type,
49 })
50 }
51
52 pub fn surface_member(&self) -> &[SurfaceProperty] {
54 &self.surface_member
55 }
56
57 pub fn set_surface_member(&mut self, surface_members: Vec<SurfaceProperty>) {
58 self.surface_member = surface_members;
59 }
60
61 pub fn push_surface_member(&mut self, member: SurfaceProperty) {
62 self.surface_member.push(member);
63 }
64
65 pub fn extend_surface_members(&mut self, members: impl IntoIterator<Item = SurfaceProperty>) {
66 self.surface_member.extend(members);
67 }
68
69 pub fn aggregation_type(&self) -> AggregationType {
71 self.aggregation_type
72 }
73
74 pub fn set_aggregation_type(&mut self, aggregation_type: AggregationType) {
75 self.aggregation_type = aggregation_type;
76 }
77}
78
79impl CompositeSurface {
80 pub fn surface_member_count(&self) -> usize {
82 self.surface_member.len()
83 }
84
85 pub fn triangulate(&self) -> Result<TriangulatedSurface, Error> {
91 let triangulated_surfaces = self
92 .surface_member
93 .iter()
94 .flat_map(|x| x.object.as_ref())
95 .map(|x| x.triangulate())
96 .collect::<Result<Vec<TriangulatedSurface>, Error>>()?;
97
98 TriangulatedSurface::from_triangulated_surfaces(triangulated_surfaces)
99 }
100
101 pub fn compute_envelope(&self) -> Option<Envelope> {
103 let envelopes: Vec<Envelope> = self
104 .surface_member
105 .iter()
106 .flat_map(|x| x.object.as_ref())
107 .flat_map(|x| x.compute_envelope())
108 .collect::<Vec<_>>();
109
110 Envelope::from_envelopes(&envelopes)
111 }
112
113 pub fn area_3d(&self) -> Result<f64, Error> {
114 self.surface_member
115 .iter()
116 .map(|s| {
117 s.object
118 .as_ref()
119 .ok_or_else(|| Error::UnresolvedSurfaceReference {
120 href: s.href.clone(),
121 })
122 .and_then(|kind| kind.area_3d())
123 })
124 .collect::<Result<Vec<f64>, Error>>()
125 .map(|area_3ds| area_3ds.into_iter().sum())
126 }
127
128 pub fn apply_transform(&mut self, m: &Isometry3<f64>) {
129 self.surface_member
130 .par_iter_mut()
131 .flat_map(|x| x.object.as_mut())
132 .for_each(|x| x.apply_transform(m));
133 }
134
135 pub fn points(&self) -> Vec<&DirectPosition> {
136 todo!("needs to be implemented")
137 }
138}
139
140impl AsAbstractSurface for CompositeSurface {
141 fn abstract_surface(&self) -> &AbstractSurface {
142 &self.abstract_surface
143 }
144}
145
146impl AsAbstractSurfaceMut for CompositeSurface {
147 fn abstract_surface_mut(&mut self) -> &mut AbstractSurface {
148 &mut self.abstract_surface
149 }
150}
151
152impl_abstract_surface_traits!(CompositeSurface);