use bevy::utils::{hashbrown::{hash_set::Iter, HashSet}};
use super::{traversal::Traversal, FaceId, HalfEdgeId, HalfEdgeMesh, MeshPosition, VertexId};
#[derive(Clone, PartialEq, Eq)]
pub enum MeshSelection{
Vertices(HashSet<VertexId>),
HalfEdges(HashSet<HalfEdgeId>),
Faces(HashSet<FaceId>)
}
impl MeshSelection {
pub fn len(&self) -> usize {
match self {
MeshSelection::Vertices(vec) => vec.len(),
MeshSelection::HalfEdges(vec) => vec.len(),
MeshSelection::Faces(vec) => vec.len(),
}
}
}
#[derive(Clone)]
pub struct Selection<'m> {
mesh: &'m HalfEdgeMesh,
selection:MeshSelection,
}
impl From<MeshPosition> for MeshSelection {
fn from(value: MeshPosition) -> Self {
match value {
MeshPosition::Vertex(vertex_id) => Self::Vertices(HashSet::from([vertex_id])),
MeshPosition::HalfEdge(half_edge_id) => Self::HalfEdges(HashSet::from([half_edge_id])),
MeshPosition::Face(face_id) => Self::Faces(HashSet::from([face_id])),
}
}
}
enum SelectionIteratorKeys<'m>{
Vertices(Iter<'m, VertexId>),
Edges(Iter<'m, HalfEdgeId>),
Faces(Iter<'m, FaceId>)
}
pub struct SelectionIterator<'m>{
mesh: &'m HalfEdgeMesh,
selection:SelectionIteratorKeys<'m>,
}
impl<'m> Selection<'m> {
pub(crate) fn new(mesh:&'m HalfEdgeMesh, position:MeshPosition) -> Self {
Self{mesh, selection:position.into()}
}
pub fn build(self) -> MeshSelection {
self.selection
}
pub fn append(&mut self, halfedge:HalfEdgeId) -> bool {
match &mut self.selection {
MeshSelection::Vertices(vec) => vec.insert(self.mesh[halfedge].vertex),
MeshSelection::HalfEdges(vec) => vec.insert(halfedge),
MeshSelection::Faces(vec) => vec.insert(self.mesh[halfedge].face.unwrap()),
}
}
pub fn iter(&'m self) -> SelectionIterator<'m> {
let selection = match &self.selection {
MeshSelection::Vertices(hash_set) => SelectionIteratorKeys::Vertices(hash_set.iter()),
MeshSelection::HalfEdges(hash_set) => SelectionIteratorKeys::Edges(hash_set.iter()),
MeshSelection::Faces(hash_set) => SelectionIteratorKeys::Faces(hash_set.iter()),
};
SelectionIterator { mesh: self.mesh, selection}
}
pub fn to_vertex_selection(self) -> Self {
let selection = match &self.selection {
MeshSelection::Vertices(_) => return self,
MeshSelection::HalfEdges(vec) => MeshSelection::Vertices(vec.iter().map(|e| self.mesh.goto(*e).vertex()).collect::<HashSet<_>>()),
MeshSelection::Faces(vec) => MeshSelection::Vertices(vec.iter().flat_map(|f| self.mesh.goto(*f).iter_loop().map(|t| t.vertex())).collect::<HashSet<_>>()),
};
Selection { mesh: self.mesh, selection }
}
pub fn to_edge_selection(self) -> Self {
let selection = match &self.selection {
MeshSelection::Vertices(vec) => MeshSelection::HalfEdges(vec.iter().map(|&v| self.mesh[v].halfedge).collect::<HashSet<_>>()),
MeshSelection::HalfEdges(_) => return self,
MeshSelection::Faces(vec) => MeshSelection::HalfEdges(vec.iter().flat_map(|&f| self.mesh.goto(f).iter_loop().map(|t| *t)).collect::<HashSet<_>>()),
};
Selection { mesh: self.mesh, selection }
}
pub fn to_face_selection(self) -> Self {
let selection = match &self.selection {
MeshSelection::Vertices(vec) => MeshSelection::Faces(vec.iter().flat_map(|&v| self.mesh.goto(v).adjacent_faces().map(|t| t.face().unwrap())).collect::<HashSet<_>>()),
MeshSelection::HalfEdges(vec) => MeshSelection::Faces(vec.iter().map(|&e| self.mesh[e].face.unwrap()).collect::<HashSet<_>>()),
MeshSelection::Faces(_) => return self,
};
Selection { mesh: self.mesh, selection }
}
}
impl<'m> Iterator for SelectionIterator<'m> {
type Item = Traversal<'m>;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.selection {
SelectionIteratorKeys::Vertices(iter) => iter.next().map(|&v| self.mesh.goto(v)),
SelectionIteratorKeys::Edges(iter) => iter.next().map(|&v| self.mesh.goto(v)),
SelectionIteratorKeys::Faces(iter) => iter.next().map(|&v| self.mesh.goto(v)),
}
}
}