use super::{ForwardEdgeIterator, HalfEdgeImplMeshType};
use crate::{
math::IndexType,
mesh::{
DefaultFacePayload, EdgeBasics, Face, Face3d, FaceBasics, FacePayload, HalfEdge,
MeshBasics, MeshType3D,
},
util::Deletable,
};
#[derive(Clone, Copy, Hash)]
pub struct HalfEdgeFaceImpl<T: HalfEdgeImplMeshType> {
id: T::F,
edge: T::E,
curved: bool,
payload: T::FP,
}
impl<T: HalfEdgeImplMeshType + MeshType3D> Face3d<T> for HalfEdgeFaceImpl<T> {}
impl<T: HalfEdgeImplMeshType> FaceBasics<T> for HalfEdgeFaceImpl<T> {
#[inline(always)]
fn edge(&self, mesh: &T::Mesh) -> T::Edge {
mesh.edge(self.edge).clone()
}
#[inline(always)]
fn edge_id(&self) -> T::E {
self.edge
}
#[inline(always)]
fn set_edge(&mut self, edge: T::E) {
self.edge = edge;
}
#[inline(always)]
fn id(&self) -> T::F {
self.id
}
fn may_be_curved(&self) -> bool {
self.curved
}
fn num_edges(&self, mesh: &T::Mesh) -> usize {
let (min, max) = self.edges(mesh).size_hint();
assert!(min == max.unwrap());
min
}
fn num_vertices(&self, mesh: &T::Mesh) -> usize {
FaceBasics::num_edges(self, mesh)
}
fn num_triangles(&self, mesh: &T::Mesh) -> usize {
(FaceBasics::num_vertices(self, mesh) - 2) * 3
}
fn payload(&self) -> &T::FP {
&self.payload
}
fn payload_mut(&mut self) -> &mut T::FP {
&mut self.payload
}
#[inline(always)]
fn vertices<'a>(
&'a self,
mesh: &'a T::Mesh,
) -> impl Iterator<Item = T::Vertex> + 'a + Clone + ExactSizeIterator {
self.edges(mesh).map(|e| e.target(mesh).clone())
}
#[inline(always)]
#[allow(refining_impl_trait)]
fn edges<'a>(&'a self, mesh: &'a T::Mesh) -> ForwardEdgeIterator<'a, T> {
ForwardEdgeIterator::new(self.edge(mesh), mesh)
}
}
impl<T: HalfEdgeImplMeshType> Face for HalfEdgeFaceImpl<T> {
type T = T;
fn triangle_touches_boundary(
&self,
mesh: &T::Mesh,
v0: T::V,
v1: T::V,
v2: T::V,
) -> Option<bool> {
if let Some(e) = mesh.shared_edge(v0, v1) {
if e.face_id() != self.id() {
return Some(false);
}
return Some(!e.is_boundary_self());
}
if let Some(e) = mesh.shared_edge(v1, v2) {
if e.face_id() != self.id() {
return Some(false);
}
return Some(!e.is_boundary_self());
}
if let Some(e) = mesh.shared_edge(v2, v0) {
if e.face_id() != self.id() {
return Some(false);
}
return Some(!e.is_boundary_self());
}
return None;
}
}
impl<T: HalfEdgeImplMeshType> HalfEdgeFaceImpl<T> {
pub fn new(edge: T::E, curved: bool, payload: T::FP) -> Self {
assert!(edge != IndexType::max());
Self {
id: IndexType::max(),
edge,
curved,
payload,
}
}
}
impl<T: HalfEdgeImplMeshType> std::fmt::Debug for HalfEdgeFaceImpl<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{: >w$}) {}",
self.id().index(),
self.edge.index(),
w = 2,
)
}
}
impl<T: HalfEdgeImplMeshType> Deletable<T::F> for HalfEdgeFaceImpl<T> {
fn delete(&mut self) {
assert!(self.id != IndexType::max(), "Face is already deleted");
self.id = IndexType::max();
}
fn is_deleted(&self) -> bool {
self.id == IndexType::max()
}
fn set_id(&mut self, id: T::F) {
assert!(self.id == IndexType::max());
assert!(id != IndexType::max());
self.id = id;
}
fn allocate() -> Self {
Self {
id: IndexType::max(),
edge: IndexType::max(),
curved: false,
payload: T::FP::allocate(),
}
}
}
impl<T: HalfEdgeImplMeshType> Default for HalfEdgeFaceImpl<T>
where
T::FP: DefaultFacePayload,
{
fn default() -> Self {
Self {
id: IndexType::max(),
edge: IndexType::max(),
curved: false,
payload: T::FP::default(),
}
}
}