egml_core/model/geometry/primitives/
solid.rs

1use crate::error::Error;
2use crate::model::base::Gml;
3use crate::model::geometry::{DirectPosition, SurfaceProperty, TriangulatedSurface};
4use crate::operations::geometry::Geometry;
5use crate::operations::triangulate::Triangulate;
6use nalgebra::Isometry3;
7use rayon::prelude::*;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct Solid {
11    pub gml: Gml,
12    members: Vec<SurfaceProperty>,
13}
14
15impl Solid {
16    pub fn new(gml: Gml, members: Vec<SurfaceProperty>) -> Result<Self, Error> {
17        if members.is_empty() {
18            return Err(Error::MustNotBeEmpty("solid"));
19        }
20
21        Ok(Self { gml, members })
22    }
23
24    pub fn members(&self) -> &Vec<SurfaceProperty> {
25        self.members.as_ref()
26    }
27
28    pub fn set_members(&mut self, val: Vec<SurfaceProperty>) -> Result<(), Error> {
29        if val.is_empty() {
30            return Err(Error::MustNotBeEmpty("solid"));
31        }
32        self.members = val;
33        Ok(())
34    }
35}
36
37impl Geometry for Solid {
38    fn points(&self) -> Vec<&DirectPosition> {
39        self.members.iter().fold(Vec::new(), |mut acc, x| {
40            acc.extend(x.points().iter());
41            acc
42        })
43    }
44
45    fn apply_transform(&mut self, m: &Isometry3<f64>) {
46        self.members.par_iter_mut().for_each(|p| {
47            p.apply_transform(m);
48        });
49    }
50}
51
52impl Triangulate for Solid {
53    fn triangulate(&self) -> Result<TriangulatedSurface, Error> {
54        let triangulated_surfaces: Vec<TriangulatedSurface> = self
55            .members
56            .iter()
57            .flat_map(|x| &x.linear_ring)
58            .map(|x| x.triangulate())
59            .collect::<Result<Vec<TriangulatedSurface>, Error>>()?;
60
61        let combined_triangulated_surface =
62            TriangulatedSurface::from_triangulated_surfaces(triangulated_surfaces)?;
63        Ok(combined_triangulated_surface)
64    }
65}