use anyhow::{bail, Error};
use mint::Point3;
use crate::v7400::data::mesh::{ControlPointIndex, ControlPoints, TriangleVertices};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PolygonVertexIndex(usize);
impl PolygonVertexIndex {
pub(crate) fn new(v: usize) -> Self {
Self(v)
}
pub(crate) fn to_usize(self) -> usize {
self.0
}
}
#[derive(Debug, Clone, Copy)]
pub struct RawPolygonVertices<'a> {
data: &'a [i32],
}
impl<'a> RawPolygonVertices<'a> {
pub(crate) fn new(data: &'a [i32]) -> Self {
Self { data }
}
pub(crate) fn get(&self, pvi: PolygonVertexIndex) -> Option<PolygonVertex> {
self.data
.get(pvi.to_usize())
.cloned()
.map(PolygonVertex::new)
}
}
#[derive(Debug, Clone, Copy)]
pub struct PolygonVertices<'a> {
control_points: ControlPoints<'a>,
polygon_vertices: RawPolygonVertices<'a>,
}
impl<'a> PolygonVertices<'a> {
pub(crate) fn new(
control_points: ControlPoints<'a>,
polygon_vertices: RawPolygonVertices<'a>,
) -> Self {
Self {
control_points,
polygon_vertices,
}
}
pub fn raw_control_points(&self) -> anyhow::Result<impl Iterator<Item = Point3<f64>> + 'a> {
self.control_points.iter()
}
pub fn raw_polygon_vertices(&self) -> &[i32] {
self.polygon_vertices.data
}
pub fn polygon_vertex(&self, pvi: PolygonVertexIndex) -> Option<PolygonVertex> {
self.polygon_vertices.get(pvi)
}
pub fn control_point(&self, i: impl Into<IntoCpiWithPolyVerts>) -> Option<Point3<f64>> {
i.into()
.control_point_index(self)
.and_then(|cpi| self.control_points.get(cpi))
}
pub fn triangulate_each<F>(&self, mut triangulator: F) -> Result<TriangleVertices<'a>, Error>
where
F: FnMut(
&Self,
&[PolygonVertexIndex],
&mut Vec<[PolygonVertexIndex; 3]>,
) -> Result<(), Error>
+ Copy,
{
let len = self.polygon_vertices.data.len();
let mut tri_pv_indices = Vec::new();
let mut tri_poly_indices = Vec::new();
let mut current_poly_index = 0;
let mut current_poly_pvis = Vec::new();
let mut pv_index_start = 0;
let mut tri_results = Vec::new();
while pv_index_start < len {
current_poly_pvis.clear();
tri_results.clear();
let pv_index_next_start = match self.polygon_vertices.data[pv_index_start..]
.iter()
.cloned()
.map(PolygonVertex::new)
.position(PolygonVertex::is_end)
{
Some(v) => pv_index_start + v + 1,
None => bail!(
"Incomplete polygon found: pv_index_start={:?}, len={}",
pv_index_start,
len
),
};
current_poly_pvis
.extend((pv_index_start..pv_index_next_start).map(PolygonVertexIndex::new));
triangulator(self, ¤t_poly_pvis, &mut tri_results)?;
tri_pv_indices.extend(tri_results.iter().flatten());
tri_poly_indices
.extend((0..tri_results.len()).map(|_| PolygonIndex::new(current_poly_index)));
pv_index_start = pv_index_next_start;
current_poly_index += 1;
}
Ok(TriangleVertices::new(
*self,
tri_pv_indices,
tri_poly_indices,
))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PolygonVertex(i32);
impl PolygonVertex {
pub fn new(i: i32) -> Self {
Self(i)
}
pub fn is_end(self) -> bool {
self.0 < 0
}
pub fn to_u32(self) -> u32 {
if self.0 < 0 {
!self.0 as u32
} else {
self.0 as u32
}
}
#[deprecated(since = "0.0.3", note = "Renamed to `to_u32`")]
pub fn get_u32(self) -> u32 {
self.to_u32()
}
}
impl From<PolygonVertex> for ControlPointIndex {
fn from(pv: PolygonVertex) -> Self {
Self::new(pv.to_u32())
}
}
impl From<&PolygonVertex> for ControlPointIndex {
fn from(pv: &PolygonVertex) -> Self {
Self::new(pv.to_u32())
}
}
#[derive(Debug, Clone, Copy)]
pub struct PolygonIndex(usize);
impl PolygonIndex {
fn new(v: usize) -> Self {
Self(v)
}
pub fn to_usize(self) -> usize {
self.0
}
#[deprecated(since = "0.0.3", note = "Renamed to `to_usize`")]
pub fn get(self) -> usize {
self.to_usize()
}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub enum IntoCpiWithPolyVerts {
ControlPointIndex(ControlPointIndex),
PolygonVertex(PolygonVertex),
PolygonVertexIndex(PolygonVertexIndex),
}
impl IntoCpiWithPolyVerts {
fn control_point_index(
&self,
polygon_vertices: &PolygonVertices<'_>,
) -> Option<ControlPointIndex> {
match *self {
IntoCpiWithPolyVerts::ControlPointIndex(cpi) => Some(cpi),
IntoCpiWithPolyVerts::PolygonVertex(pv) => Some(pv.into()),
IntoCpiWithPolyVerts::PolygonVertexIndex(pvi) => {
polygon_vertices.polygon_vertex(pvi).map(Into::into)
}
}
}
}
impl From<ControlPointIndex> for IntoCpiWithPolyVerts {
fn from(i: ControlPointIndex) -> Self {
IntoCpiWithPolyVerts::ControlPointIndex(i)
}
}
impl From<&ControlPointIndex> for IntoCpiWithPolyVerts {
fn from(i: &ControlPointIndex) -> Self {
IntoCpiWithPolyVerts::ControlPointIndex(*i)
}
}
impl From<PolygonVertex> for IntoCpiWithPolyVerts {
fn from(i: PolygonVertex) -> Self {
IntoCpiWithPolyVerts::PolygonVertex(i)
}
}
impl From<&PolygonVertex> for IntoCpiWithPolyVerts {
fn from(i: &PolygonVertex) -> Self {
IntoCpiWithPolyVerts::PolygonVertex(*i)
}
}
impl From<PolygonVertexIndex> for IntoCpiWithPolyVerts {
fn from(i: PolygonVertexIndex) -> Self {
IntoCpiWithPolyVerts::PolygonVertexIndex(i)
}
}
impl From<&PolygonVertexIndex> for IntoCpiWithPolyVerts {
fn from(i: &PolygonVertexIndex) -> Self {
IntoCpiWithPolyVerts::PolygonVertexIndex(*i)
}
}