use std::ops::Neg;
use linear_isomorphic::InnerSpace;
use crate::data_container::StorageBuffer;
use crate::handles::edge_handle::EdgeHandle;
use crate::prelude::{half_edge_handle::HalfEdgeHandle, vert_handle::VertHandle};
use crate::topo_ids::HalfEdgeId;
use crate::{FaceData, FaceId, MeshData, MeshStorage, TopoFace, VertData, VertId};
pub struct FaceHandle<C: MeshStorage, const MANIFOLD: bool>
{
pub(crate) mesh_data: *mut MeshData<C, MANIFOLD>,
pub(crate) id: FaceId,
}
impl<C: MeshStorage, const MANIFOLD: bool> FaceHandle<C, MANIFOLD>
{
pub fn id(&self) -> FaceId { self.id }
pub fn half_edge(&self) -> HalfEdgeHandle<C, MANIFOLD>
{
unsafe {
let half_edge_id = (*self.mesh_data).face_ref(self.id).half_edge;
HalfEdgeHandle {
mesh_data: self.mesh_data,
id: half_edge_id,
}
}
}
pub fn read_data(&self) -> &FaceData<C>
{
unsafe {
(*self.mesh_data)
.geometry_data
.face_data
.read(self.id.to_index() as u64)
}
}
pub fn update_data<F: FnMut(&mut FaceData<C>)>(&mut self, update: F)
{
unsafe {
(*self.mesh_data)
.geometry_data
.face_data
.update(self.id.to_index() as u64, update)
}
}
pub fn naive_normal<S>(&self) -> VertData<C>
where
VertData<C>: linear_isomorphic::InnerSpace<S> + Neg<Output = VertData<C>>,
S: linear_isomorphic::RealField,
{
use linear_isomorphic::VectorSpace;
let e1: VertData<C> = self.half_edge().dir();
let e2: VertData<C> = self.half_edge().face_prev().dir();
return e2.cross(&e1);
}
pub fn normal<S>(&self) -> VertData<C>
where
VertData<C>: linear_isomorphic::InnerSpace<S> + Neg<Output = VertData<C>>,
S: linear_isomorphic::RealField,
{
self.naive_normal().normalized()
}
pub fn area<S>(&self) -> S
where
VertData<C>: linear_isomorphic::InnerSpace<S> + Neg<Output = VertData<C>>,
S: linear_isomorphic::RealField,
{
self.naive_normal().norm()
}
pub fn vertices(&self) -> impl Iterator<Item = VertHandle<C, MANIFOLD>>
{
self.half_edge().iter_face().map(|h| h.source())
}
pub fn replicate(&self) -> Self
{
FaceHandle {
mesh_data: self.mesh_data,
id: self.id,
}
}
pub fn unclean_delete(self)
{
unsafe {
let hedge = self.half_edge();
for h in hedge.iter_face()
{
(*self.mesh_data).half_edge_mut(h.id()).face = FaceId::default();
}
*(*self.mesh_data).face_mut(self.id) = TopoFace::default();
(*self.mesh_data)
.topology_data
.available_face_ids
.push(self.id);
}
}
pub fn delete(self)
{
unsafe {
if !MANIFOLD
{
let edges: Vec<_> =
self.half_edge().iter_face().map(|h| h.edge().id).collect();
let mesh_data = self.mesh_data;
self.unclean_delete();
for e in edges
{
if (*mesh_data).edge_ref(e).id.is_void()
{
continue;
}
let edge_handle = EdgeHandle { mesh_data, id: e };
if edge_handle.half_edge().id().is_void()
{
edge_handle.delete();
}
}
}
else
{
let half_edges: Vec<_> =
self.half_edge().iter_face().map(|h| h.id).collect();
let mesh_data = self.mesh_data;
self.unclean_delete();
for h in half_edges
{
if (*mesh_data).half_edge_ref(h).id.is_void()
{
continue;
}
let hedge_handle = HalfEdgeHandle { mesh_data, id: h };
if hedge_handle.iter_orbit().count() == 0
{
hedge_handle.delete();
}
}
}
}
}
pub fn split_and_join_to_vertex(&self, vn: VertId) -> VertId
{
unsafe {
let half_edges: Vec<_> =
self.half_edge().iter_face().map(|h| h.id()).collect();
let mut faces = Vec::new();
faces.push(self.id());
for _ in 1..half_edges.len()
{
faces.push((*self.mesh_data).reserve_face());
}
let valence = half_edges.len();
let mut new_edges = vec![[HalfEdgeId::default(); 2]; valence];
for (i, h) in half_edges.iter().enumerate()
{
let vid = (*self.mesh_data).half_edge_ref(*h).source;
let data_index = if MANIFOLD
{
h.to_index() as u64 / 2
}
else
{
(*self.mesh_data).half_edge_ref(*h).edge.to_index() as u64
};
let data = (*self.mesh_data)
.geometry_data
.edge_data
.read(data_index)
.clone();
let hn = (*self.mesh_data).add_edge(vid, vn, data);
let p = (*self.mesh_data).half_edge_ref(hn).orbit_next;
new_edges[(i + valence - 1) % valence][1] = hn;
new_edges[i][0] = p;
}
for (i, [incoming, outgoing]) in new_edges.into_iter().enumerate()
{
let fids = [incoming, half_edges[i], outgoing];
for i in 0..3
{
let (hedge1, hedge2) = crate::get_two_mut(
&mut (*self.mesh_data).topology_data.topo_half_edges,
fids[i].to_index(),
fids[(i + 1) % 3].to_index(),
);
hedge1.attach_next_in_face(hedge2);
}
crate::attach_face(&mut (*self.mesh_data).topology_data, &fids, faces[i]);
}
vn
}
}
pub fn split_and_fit(&self, data: VertData<C>) -> VertId
{
unsafe {
let vn = (*self.mesh_data).add_vert(data);
self.split_and_join_to_vertex(vn)
}
}
pub fn split<S>(&self) -> VertId
where
VertData<C>: linear_isomorphic::InnerSpace<S> + Neg<Output = VertData<C>>,
S: linear_isomorphic::RealField,
{
let mut count = 1;
let mut average = self.half_edge().source().read_data().clone();
for v in self
.half_edge()
.iter_face()
.skip(1)
.map(|h| h.source().read_data().clone())
{
average = average + v;
count += 1;
}
average = average * (S::from(1).unwrap() / S::from(count).unwrap());
self.split_and_fit(average)
}
}