egml_core/model/geometry/primitives/
triangulated_surface.rs

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