use crate::data_container::StorageBuffer;
use crate::prelude::{
edge_handle::EdgeHandle,
face_handle::FaceHandle,
half_edge_handle::HalfEdgeHandle,
half_edge_handle::OrbitHalfEdgeIterator,
};
use crate::{EdgeId, HalfEdgeId, MeshData, MeshStorage, VertData, VertId};
pub struct VertHandle<C: MeshStorage, const MANIFOLD: bool>
{
pub(crate) mesh_data: *mut MeshData<C, MANIFOLD>,
pub(crate) id: VertId,
}
impl<C: MeshStorage, const MANIFOLD: bool> VertHandle<C, MANIFOLD>
{
pub(crate) fn new(mesh_data: *mut MeshData<C, MANIFOLD>, id: VertId) -> Self
{
Self { mesh_data, id }
}
pub fn id(&self) -> VertId { self.id }
pub fn is_isolated(&self) -> bool
{
unsafe { (*self.mesh_data).vert_ref(self.id).arc.is_void() }
}
pub fn read_data(&self) -> &VertData<C>
{
unsafe {
(*self.mesh_data)
.geometry_data
.vert_data
.read(self.id.to_index() as u64)
}
}
pub fn update_data<F: FnMut(&mut VertData<C>)>(&mut self, update: F)
{
unsafe {
(*self.mesh_data)
.geometry_data
.vert_data
.update(self.id.to_index() as u64, update)
}
}
pub fn edge(&self) -> EdgeHandle<C, MANIFOLD>
{
assert!(
!MANIFOLD,
"Cannot call `edge()` on a manifold vertex handle."
);
unsafe {
let edge_id = (*self.mesh_data).vert_ref(self.id).arc.to_edge_id();
EdgeHandle {
mesh_data: self.mesh_data,
id: edge_id,
}
}
}
pub fn half_edge(&self) -> HalfEdgeHandle<C, MANIFOLD>
{
unsafe {
if MANIFOLD
{
let half_edge_id =
(*self.mesh_data).vert_ref(self.id).arc.to_half_edge_id();
HalfEdgeHandle {
mesh_data: self.mesh_data,
id: half_edge_id,
}
}
else
{
self.edge().half_edge()
}
}
}
pub fn iter_star_edges(&self) -> impl Iterator<Item = EdgeHandle<C, MANIFOLD>>
{
if !MANIFOLD
{
NonManifoldStarIterator::new(self.edge(), self.id())
}
else
{
panic!("Calling edge iterator on a manifold mesh.")
}
}
pub fn iter_star_half_edges(&self) -> AgnosticStarHalfEdgeIterator<C, MANIFOLD>
{
if !MANIFOLD
{
AgnosticStarHalfEdgeIterator::NonManifold(
NonManifoldUniqueStarHalfEdgesIterator::new(self.edge(), self.id()),
)
}
else
{
AgnosticStarHalfEdgeIterator::Manifold(ManifoldStarIterator::new(
self.half_edge(),
))
}
}
pub fn valence(&self) -> usize { self.iter_star_half_edges().count() }
pub fn is_in_boundary(&self) -> bool
{
self.iter_star_half_edges().any(|h| h.is_in_boundary())
}
pub fn iter_neighbours(&self) -> impl Iterator<Item = VertHandle<C, MANIFOLD>>
{
self.iter_star_half_edges().map(|h| h.dest())
}
pub fn iter_incident_faces(&self) -> impl Iterator<Item = FaceHandle<C, MANIFOLD>>
{
self.iter_star_half_edges().map(|h| h.face())
}
pub(crate) fn find_distinct_edge(
&self,
hid: HalfEdgeId,
) -> Option<HalfEdgeHandle<C, MANIFOLD>>
{
self.iter_star_half_edges().find(|h| {
if MANIFOLD
{
h.id() != hid
}
else
{
h.edge().id() != unsafe { (*self.mesh_data).half_edge_ref(hid).edge }
}
})
}
}
pub enum AgnosticStarHalfEdgeIterator<C: MeshStorage, const MANIFOLD: bool>
{
Manifold(ManifoldStarIterator<C, MANIFOLD>),
NonManifold(NonManifoldUniqueStarHalfEdgesIterator<C, MANIFOLD>),
}
impl<C: MeshStorage, const MANIFOLD: bool> Iterator
for AgnosticStarHalfEdgeIterator<C, MANIFOLD>
{
type Item = HalfEdgeHandle<C, MANIFOLD>;
fn next(&mut self) -> Option<Self::Item>
{
match self
{
Self::Manifold(iter) => iter.next(),
Self::NonManifold(iter) => iter.next(),
}
}
}
pub struct ManifoldStarIterator<C: MeshStorage, const MANIFOLD: bool>
{
start: HalfEdgeId,
current: HalfEdgeHandle<C, MANIFOLD>,
finished: bool,
}
impl<C: MeshStorage, const MANIFOLD: bool> ManifoldStarIterator<C, MANIFOLD>
{
pub(crate) fn new(hedge: HalfEdgeHandle<C, MANIFOLD>) -> Self
{
Self {
start: hedge.id(),
current: hedge,
finished: false,
}
}
}
impl<C: MeshStorage, const MANIFOLD: bool> Iterator for ManifoldStarIterator<C, MANIFOLD>
{
type Item = HalfEdgeHandle<C, MANIFOLD>;
fn next(&mut self) -> Option<Self::Item>
{
if self.finished || self.current.id().is_void()
{
return None;
}
let current_edge = self.current.replicate();
self.current = self.current.orbit_next().face_next();
if self.current.id() == self.start
{
self.finished = true;
}
Some(current_edge)
}
}
pub struct NonManifoldStarIterator<C: MeshStorage, const MANIFOLD: bool>
{
start: EdgeId,
current: EdgeHandle<C, MANIFOLD>,
locus: VertId,
finished: bool,
}
impl<C: MeshStorage, const MANIFOLD: bool> NonManifoldStarIterator<C, MANIFOLD>
{
pub(crate) fn new(edge: EdgeHandle<C, MANIFOLD>, locus: VertId) -> Self
{
Self {
start: edge.id(),
current: edge,
locus,
finished: false,
}
}
}
impl<C: MeshStorage, const MANIFOLD: bool> Iterator
for NonManifoldStarIterator<C, MANIFOLD>
{
type Item = EdgeHandle<C, MANIFOLD>;
fn next(&mut self) -> Option<Self::Item>
{
if self.finished || self.current.id().is_void()
{
return None;
}
let current_edge = self.current.replicate();
self.current = self.current.next_at(self.locus);
if self.current.id() == self.start
{
self.finished = true;
}
Some(current_edge)
}
}
pub struct NonManifoldStarHalfEdgesIterator<C: MeshStorage, const MANIFOLD: bool>
{
start: EdgeId,
current_edge: EdgeHandle<C, MANIFOLD>,
current_hedge_iter: OrbitHalfEdgeIterator<C, MANIFOLD>,
locus: VertId,
}
impl<C: MeshStorage, const MANIFOLD: bool> NonManifoldStarHalfEdgesIterator<C, MANIFOLD>
{
pub(crate) fn new(edge: EdgeHandle<C, MANIFOLD>, locus: VertId) -> Self
{
Self {
start: edge.id(),
current_hedge_iter: OrbitHalfEdgeIterator::new(edge.half_edge()),
current_edge: edge,
locus,
}
}
}
impl<C: MeshStorage, const MANIFOLD: bool> Iterator
for NonManifoldStarHalfEdgesIterator<C, MANIFOLD>
{
type Item = HalfEdgeHandle<C, MANIFOLD>;
fn next(&mut self) -> Option<Self::Item>
{
if self.current_edge.id().is_void()
{
return None;
}
if let Some(hedge) = self.current_hedge_iter.next()
{
return Some(hedge);
}
loop
{
self.current_edge = self.current_edge.next_at(self.locus);
let hedge = self.current_edge.half_edge();
self.current_hedge_iter = hedge.iter_orbit();
if let Some(handle) = self.current_hedge_iter.next()
{
return Some(handle);
}
if self.current_edge.id() == self.start
{
return None;
}
}
}
}
pub struct NonManifoldUniqueStarHalfEdgesIterator<C: MeshStorage, const MANIFOLD: bool>
{
start: EdgeId,
current_edge: EdgeHandle<C, MANIFOLD>,
locus: VertId,
finished: bool,
}
impl<C: MeshStorage, const MANIFOLD: bool>
NonManifoldUniqueStarHalfEdgesIterator<C, MANIFOLD>
{
pub(crate) fn new(edge: EdgeHandle<C, MANIFOLD>, locus: VertId) -> Self
{
Self {
start: edge.id(),
current_edge: edge,
locus,
finished: false,
}
}
}
impl<C: MeshStorage, const MANIFOLD: bool> Iterator
for NonManifoldUniqueStarHalfEdgesIterator<C, MANIFOLD>
{
type Item = HalfEdgeHandle<C, MANIFOLD>;
fn next(&mut self) -> Option<Self::Item>
{
if self.current_edge.id().is_void()
{
return None;
}
loop
{
let current_edge = self.current_edge.replicate();
if self.current_edge.id() == self.start && self.finished
{
return None;
}
self.finished = true;
self.current_edge = self.current_edge.next_at(self.locus);
let hedge = current_edge.half_edge();
if let Some(handle) =
hedge.iter_orbit().find(|h| h.source().id() == self.locus)
{
return Some(handle);
}
}
}
}