fbxcel_dom/v7400/data/mesh/
polygon_vertex_index.rs

1//! Polygon vertex index.
2
3use anyhow::{bail, Error};
4use mint::Point3;
5
6use crate::v7400::data::mesh::{ControlPointIndex, ControlPoints, TriangleVertices};
7
8/// Polygon vertex index.
9///
10/// This is index of control point index.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct PolygonVertexIndex(usize);
13
14impl PolygonVertexIndex {
15    /// Creates a new `PolygonVertexIndex`.
16    pub(crate) fn new(v: usize) -> Self {
17        Self(v)
18    }
19
20    /// Returns the raw index.
21    pub(crate) fn to_usize(self) -> usize {
22        self.0
23    }
24}
25
26/// Raw polygon vertices (control point indices) data.
27#[derive(Debug, Clone, Copy)]
28pub struct RawPolygonVertices<'a> {
29    /// Polygon vertices (control point indices).
30    data: &'a [i32],
31}
32
33impl<'a> RawPolygonVertices<'a> {
34    /// Creates a new `RawPolygonVertices`.
35    pub(crate) fn new(data: &'a [i32]) -> Self {
36        Self { data }
37    }
38
39    /// Returns a polygon vertex at the given index.
40    pub(crate) fn get(&self, pvi: PolygonVertexIndex) -> Option<PolygonVertex> {
41        self.data
42            .get(pvi.to_usize())
43            .cloned()
44            .map(PolygonVertex::new)
45    }
46}
47
48/// Polygon vertices and control points data.
49#[derive(Debug, Clone, Copy)]
50pub struct PolygonVertices<'a> {
51    /// Control points.
52    control_points: ControlPoints<'a>,
53    /// Polygon vertices (control point indices).
54    polygon_vertices: RawPolygonVertices<'a>,
55}
56
57impl<'a> PolygonVertices<'a> {
58    /// Creates a new `PolygonVertices`.
59    pub(crate) fn new(
60        control_points: ControlPoints<'a>,
61        polygon_vertices: RawPolygonVertices<'a>,
62    ) -> Self {
63        Self {
64            control_points,
65            polygon_vertices,
66        }
67    }
68
69    /// Returns the raw control points
70    pub fn raw_control_points(&self) -> anyhow::Result<impl Iterator<Item = Point3<f64>> + 'a> {
71        self.control_points.iter()
72    }
73
74    /// Returns a slice of the raw polygon vertices (indices).
75    pub fn raw_polygon_vertices(&self) -> &[i32] {
76        self.polygon_vertices.data
77    }
78
79    /// Returns a polygon vertex at the given index.
80    pub fn polygon_vertex(&self, pvi: PolygonVertexIndex) -> Option<PolygonVertex> {
81        self.polygon_vertices.get(pvi)
82    }
83
84    /// Returns a control point at the given index.
85    pub fn control_point(&self, i: impl Into<IntoCpiWithPolyVerts>) -> Option<Point3<f64>> {
86        i.into()
87            .control_point_index(self)
88            .and_then(|cpi| self.control_points.get(cpi))
89    }
90
91    /// Triangulates the polygons and returns indices map.
92    pub fn triangulate_each<F>(&self, mut triangulator: F) -> Result<TriangleVertices<'a>, Error>
93    where
94        F: FnMut(
95                &Self,
96                &[PolygonVertexIndex],
97                &mut Vec<[PolygonVertexIndex; 3]>,
98            ) -> Result<(), Error>
99            + Copy,
100    {
101        let len = self.polygon_vertices.data.len();
102        let mut tri_pv_indices = Vec::new();
103        let mut tri_poly_indices = Vec::new();
104
105        let mut current_poly_index = 0;
106        let mut current_poly_pvis = Vec::new();
107        let mut pv_index_start = 0;
108        let mut tri_results = Vec::new();
109        while pv_index_start < len {
110            current_poly_pvis.clear();
111            tri_results.clear();
112
113            let pv_index_next_start = match self.polygon_vertices.data[pv_index_start..]
114                .iter()
115                .cloned()
116                .map(PolygonVertex::new)
117                .position(PolygonVertex::is_end)
118            {
119                Some(v) => pv_index_start + v + 1,
120                None => bail!(
121                    "Incomplete polygon found: pv_index_start={:?}, len={}",
122                    pv_index_start,
123                    len
124                ),
125            };
126            current_poly_pvis
127                .extend((pv_index_start..pv_index_next_start).map(PolygonVertexIndex::new));
128            triangulator(self, &current_poly_pvis, &mut tri_results)?;
129            tri_pv_indices.extend(tri_results.iter().flatten());
130            tri_poly_indices
131                .extend((0..tri_results.len()).map(|_| PolygonIndex::new(current_poly_index)));
132
133            pv_index_start = pv_index_next_start;
134            current_poly_index += 1;
135        }
136
137        Ok(TriangleVertices::new(
138            *self,
139            tri_pv_indices,
140            tri_poly_indices,
141        ))
142    }
143}
144
145/// Polygon vertex.
146///
147/// `PolygonVertex` = control point index + polygon end marker.
148#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
149pub struct PolygonVertex(i32);
150
151impl PolygonVertex {
152    /// Creates a new `PolygonVertex`.
153    pub fn new(i: i32) -> Self {
154        Self(i)
155    }
156
157    /// Returns whether the polygon vertex index is the end of a polygon.
158    pub fn is_end(self) -> bool {
159        self.0 < 0
160    }
161
162    /// Returns the polygon vertex, i.e. index of control point, in `u32`.
163    pub fn to_u32(self) -> u32 {
164        if self.0 < 0 {
165            !self.0 as u32
166        } else {
167            self.0 as u32
168        }
169    }
170
171    /// Returns the polygon vertex, i.e. index of control point, in `u32`.
172    #[deprecated(since = "0.0.3", note = "Renamed to `to_u32`")]
173    pub fn get_u32(self) -> u32 {
174        self.to_u32()
175    }
176}
177
178impl From<PolygonVertex> for ControlPointIndex {
179    fn from(pv: PolygonVertex) -> Self {
180        Self::new(pv.to_u32())
181    }
182}
183
184impl From<&PolygonVertex> for ControlPointIndex {
185    fn from(pv: &PolygonVertex) -> Self {
186        Self::new(pv.to_u32())
187    }
188}
189
190/// Polygon index.
191#[derive(Debug, Clone, Copy)]
192pub struct PolygonIndex(usize);
193
194impl PolygonIndex {
195    /// Creates a new `PolygonIndex`.
196    fn new(v: usize) -> Self {
197        Self(v)
198    }
199
200    /// Returns the index.
201    pub fn to_usize(self) -> usize {
202        self.0
203    }
204
205    /// Returns the index.
206    #[deprecated(since = "0.0.3", note = "Renamed to `to_usize`")]
207    pub fn get(self) -> usize {
208        self.to_usize()
209    }
210}
211
212/// A type to contain a value convertible into control point index.
213///
214/// This is used for [`PolygonVertices::control_point`], but not intended to be
215/// used directly by users.
216///
217/// [`PolygonVertices::control_point`]:
218/// struct.PolygonVertices.html#method.control_point
219#[derive(Debug, Clone, Copy)]
220#[non_exhaustive]
221pub enum IntoCpiWithPolyVerts {
222    /// Control point index.
223    ControlPointIndex(ControlPointIndex),
224    /// Polygon vertex.
225    PolygonVertex(PolygonVertex),
226    /// Polygon vertex index.
227    PolygonVertexIndex(PolygonVertexIndex),
228}
229
230impl IntoCpiWithPolyVerts {
231    /// Returns control point index.
232    fn control_point_index(
233        &self,
234        polygon_vertices: &PolygonVertices<'_>,
235    ) -> Option<ControlPointIndex> {
236        match *self {
237            IntoCpiWithPolyVerts::ControlPointIndex(cpi) => Some(cpi),
238            IntoCpiWithPolyVerts::PolygonVertex(pv) => Some(pv.into()),
239            IntoCpiWithPolyVerts::PolygonVertexIndex(pvi) => {
240                polygon_vertices.polygon_vertex(pvi).map(Into::into)
241            }
242        }
243    }
244}
245
246impl From<ControlPointIndex> for IntoCpiWithPolyVerts {
247    fn from(i: ControlPointIndex) -> Self {
248        IntoCpiWithPolyVerts::ControlPointIndex(i)
249    }
250}
251
252impl From<&ControlPointIndex> for IntoCpiWithPolyVerts {
253    fn from(i: &ControlPointIndex) -> Self {
254        IntoCpiWithPolyVerts::ControlPointIndex(*i)
255    }
256}
257
258impl From<PolygonVertex> for IntoCpiWithPolyVerts {
259    fn from(i: PolygonVertex) -> Self {
260        IntoCpiWithPolyVerts::PolygonVertex(i)
261    }
262}
263
264impl From<&PolygonVertex> for IntoCpiWithPolyVerts {
265    fn from(i: &PolygonVertex) -> Self {
266        IntoCpiWithPolyVerts::PolygonVertex(*i)
267    }
268}
269
270impl From<PolygonVertexIndex> for IntoCpiWithPolyVerts {
271    fn from(i: PolygonVertexIndex) -> Self {
272        IntoCpiWithPolyVerts::PolygonVertexIndex(i)
273    }
274}
275
276impl From<&PolygonVertexIndex> for IntoCpiWithPolyVerts {
277    fn from(i: &PolygonVertexIndex) -> Self {
278        IntoCpiWithPolyVerts::PolygonVertexIndex(*i)
279    }
280}