egml_core/model/geometry/primitives/
triangulated_surface.rs1use crate::error::Error;
2use crate::model::common::{ApplyTransform, ComputeEnvelope, IterGeometries};
3use crate::model::geometry::primitives::abstract_surface_patch_kind::AbstractSurfacePatchKind;
4use crate::model::geometry::primitives::{
5 AbstractSurfacePatchArrayProperty, AsSurface, AsSurfaceMut, Surface, Triangle,
6};
7use crate::model::geometry::refs::AbstractGeometryKindRef;
8use crate::model::geometry::{DirectPosition, Envelope};
9use crate::{impl_has_geometry_type, impl_surface_mut_traits, impl_surface_traits};
10use nalgebra::{Isometry3, Rotation3, Scale3, Transform3, Vector3};
11
12#[derive(Debug, Clone, PartialEq)]
17pub struct TriangulatedSurface {
18 surface: Surface,
19}
20
21impl TriangulatedSurface {
22 pub fn new(surface: Surface) -> Result<Self, Error> {
24 Ok(TriangulatedSurface { surface })
25 }
26
27 pub fn surface(&self) -> &Surface {
28 &self.surface
29 }
30}
31
32impl TriangulatedSurface {
33 pub fn from_triangles(triangles: Vec<Triangle>) -> Result<Self, Error> {
39 Self::validate_triangles(&triangles)?;
40
41 let patches: Vec<AbstractSurfacePatchKind> = triangles
42 .into_iter()
43 .map(AbstractSurfacePatchKind::Triangle)
44 .collect();
45 let surface_patch_array_property: AbstractSurfacePatchArrayProperty =
46 AbstractSurfacePatchArrayProperty::from_objects(patches);
47
48 Self::new(Surface::new(surface_patch_array_property))
49 }
50
51 pub fn from_triangulated_surfaces(surfaces: Vec<TriangulatedSurface>) -> Result<Self, Error> {
57 Self::validate_surfaces(&surfaces)?;
58
59 let patches: Vec<AbstractSurfacePatchKind> = surfaces
60 .into_iter()
61 .flat_map(|surface| {
62 let mut patch_array = surface.surface.into_patches();
63 std::mem::take(patch_array.objects_mut())
64 })
65 .collect();
66
67 let surface_patch_array_property: AbstractSurfacePatchArrayProperty =
68 AbstractSurfacePatchArrayProperty::from_objects(patches);
69
70 let surface = Surface::new(surface_patch_array_property);
71 Ok(TriangulatedSurface { surface })
72 }
73
74 fn validate_triangles(triangles: &[Triangle]) -> Result<(), Error> {
75 if triangles.is_empty() {
76 return Err(Error::TooFewElements {
77 geometry: "gml:TriangulatedSurface",
78 minimum: 1,
79 spec: Some("OGC 07-036 §10.5.11.4"),
80 id: None,
81 detail: None,
82 });
83 }
84 Ok(())
85 }
86
87 fn validate_surfaces(surfaces: &[TriangulatedSurface]) -> Result<(), Error> {
88 if surfaces.is_empty() {
89 return Err(Error::TooFewElements {
90 geometry: "TriangulatedSurface::from_triangulated_surfaces",
91 minimum: 1,
92 spec: None,
93 id: None,
94 detail: None,
95 });
96 }
97 Ok(())
98 }
99
100 pub fn triangles(&self) -> Vec<&Triangle> {
102 self.surface
103 .patches()
104 .objects()
105 .iter()
106 .filter_map(|patch| match patch {
107 AbstractSurfacePatchKind::Triangle(triangle) => Some(triangle),
108 _ => None,
109 })
110 .collect()
111 }
112
113 pub fn points(&self) -> Vec<&DirectPosition> {
114 self.surface.points()
115 }
116
117 pub fn area_3d(&self) -> Result<f64, Error> {
118 self.surface.area_3d()
119 }
120}
121
122impl AsSurface for TriangulatedSurface {
123 fn surface(&self) -> &Surface {
124 &self.surface
125 }
126}
127
128impl AsSurfaceMut for TriangulatedSurface {
129 fn surface_mut(&mut self) -> &mut Surface {
130 &mut self.surface
131 }
132}
133
134impl_surface_traits!(TriangulatedSurface);
135impl_surface_mut_traits!(TriangulatedSurface);
136impl_has_geometry_type!(TriangulatedSurface, TriangulatedSurface);
137
138impl IterGeometries for TriangulatedSurface {
139 fn iter_geometries(&self) -> Box<dyn Iterator<Item = AbstractGeometryKindRef<'_>> + '_> {
140 Box::new(std::iter::once(self.into()))
141 }
142}
143
144impl ApplyTransform for TriangulatedSurface {
145 fn apply_transform(&mut self, transform: Transform3<f64>) {
146 self.surface.apply_transform(transform);
147 }
148
149 fn apply_isometry(&mut self, isometry: Isometry3<f64>) {
150 self.surface.apply_isometry(isometry);
151 }
152
153 fn apply_translation(&mut self, vector: Vector3<f64>) {
154 self.surface.apply_translation(vector);
155 }
156
157 fn apply_rotation(&mut self, rotation: Rotation3<f64>) {
158 self.surface.apply_rotation(rotation);
159 }
160
161 fn apply_scale(&mut self, scale: Scale3<f64>) {
162 self.surface.apply_scale(scale);
163 }
164}
165
166impl ComputeEnvelope for TriangulatedSurface {
167 fn compute_envelope(&self) -> Option<Envelope> {
169 self.surface.compute_envelope()
170 }
171}