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