truck_polymesh/expand.rs
1use crate::*;
2use std::fmt::Debug;
3use std::hash::Hash;
4use truck_base::entry_map::FxEntryMap as EntryMap;
5
6impl<V: Copy + Hash + Debug + Eq, A: Attributes<V>> PolygonMesh<V, A> {
7 /// Contract attributes and expand polygon.
8 ///
9 /// # Examples
10 /// ```
11 /// use truck_polymesh::*;
12 /// let polygon = PolygonMesh::new(
13 /// StandardAttributes {
14 /// positions: vec![
15 /// Point3::new(0.0, 0.0, 0.0),
16 /// Point3::new(1.0, 0.0, 0.0),
17 /// Point3::new(0.0, 1.0, 0.0),
18 /// Point3::new(1.0, 1.0, 0.0),
19 /// ],
20 /// normals: vec![
21 /// Vector3::new(0.0, 0.0, 1.0),
22 /// Vector3::new(0.0, 0.0, -1.0),
23 /// ],
24 /// ..Default::default()
25 /// },
26 /// Faces::from_iter(&[
27 /// &[(0, None, Some(0)), (1, None, Some(0)), (2, None, Some(0))],
28 /// &[(3, None, Some(1)), (1, None, Some(1)), (2, None, Some(1))],
29 /// ])
30 /// );
31 /// let expands = polygon.expands(|attr| (attr.position, attr.normal.unwrap()));
32 /// assert_eq!(
33 /// expands,
34 /// PolygonMesh::<usize, Vec<(Point3, Vector3)>>::new(
35 /// vec![
36 /// (Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0)),
37 /// (Point3::new(1.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0)),
38 /// (Point3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 0.0, 1.0)),
39 /// (Point3::new(1.0, 1.0, 0.0), Vector3::new(0.0, 0.0, -1.0)),
40 /// (Point3::new(1.0, 0.0, 0.0), Vector3::new(0.0, 0.0, -1.0)),
41 /// (Point3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 0.0, -1.0)),
42 /// ],
43 /// Faces::from_iter(&[[0, 1, 2], [3, 4, 5]]),
44 /// )
45 /// );
46 /// ```
47 pub fn expands<T: Copy>(
48 &self,
49 contraction: impl Fn(A::Output) -> T,
50 ) -> PolygonMesh<usize, Vec<T>> {
51 let mut vec = Vec::<T>::new();
52 let mut vertex_map = EntryMap::new(
53 |x| x,
54 |vertex| {
55 let idx = vec.len();
56 vec.push(contraction(self.attributes.get(vertex).unwrap()));
57 idx
58 },
59 );
60 let faces: Faces<usize> = self
61 .face_iter()
62 .map(|face| {
63 face.iter()
64 .cloned()
65 .map(|vertex| *vertex_map.entry_or_insert(vertex))
66 .collect::<Vec<_>>()
67 })
68 .collect();
69 PolygonMesh::new(vec, faces)
70 }
71}