use maplike::{Get, Insert, StableRemove};
use crate::{
Dcel, EdgeId, Face, FaceId, HalfEdge, HalfEdgeId, Vertex, VertexId,
track::{HalfEdgesCounter, VertexesCounter},
};
impl<
VW: Clone,
HEW: Clone,
FW: Clone,
VC: Get<usize, Value = Vertex<VW>> + Insert<usize> + StableRemove<usize>,
HEC: Get<usize, Value = HalfEdge<HEW>> + Insert<usize> + StableRemove<usize>,
FC: Get<usize, Value = Face<FW>> + Insert<usize> + StableRemove<usize>,
> Dcel<VW, HEW, FW, VC, HEC, FC>
{
pub fn smoothen_vertex(&mut self, vertex: VertexId) {
let representative = self.vertex_representative(vertex);
self.link_subsequent_half_edges(self.prev(representative), self.next(representative));
self.link_subsequent_half_edges(
self.prev(self.twin(representative)),
self.next(self.twin(representative)),
);
self.remove_orphaned_edges([self.full_edge(representative)]);
self.remove_orphaned_vertices([vertex]);
}
pub fn merge_faces_around_vertex(&mut self, inner_vertex: VertexId) {
let absorbing_face = self.incident_face(self.vertex_representative(inner_vertex));
self.absorb_faces_around_vertex(absorbing_face, inner_vertex);
}
pub fn absorb_faces_around_vertex(&mut self, absorbing_face: FaceId, inner_vertex: VertexId) {
let initial_half_edge = self.vertex_representative(inner_vertex);
let inner_edges: Vec<EdgeId> = self.spokes(initial_half_edge).collect();
let perimeter_half_edges: Vec<HalfEdgeId> = self
.vertex_rim_half_edges(inner_vertex)
.collect::<Vec<HalfEdgeId>>();
self.absorb_faces_over_edges_and_vertices_in_perimeter(
absorbing_face,
self.interspokes(initial_half_edge)
.filter(|face| face.id() != absorbing_face.id())
.collect::<Vec<FaceId>>(),
inner_edges,
[inner_vertex],
&perimeter_half_edges,
);
}
pub(crate) fn merge_faces_over_edges_and_vertices(
&mut self,
faces: impl IntoIterator<Item = FaceId>,
edges: impl IntoIterator<Item = EdgeId>,
vertices: impl IntoIterator<Item = VertexId>,
) {
let mut faces = faces.into_iter();
let absorbing_face = faces.next().unwrap();
self.absorb_faces_over_edges_and_vertices(
absorbing_face,
faces.filter(|face| face.id() != absorbing_face.id()),
edges,
vertices,
);
}
pub(crate) fn absorb_faces_over_edges_and_vertices(
&mut self,
absorbing_face: FaceId,
faces: impl IntoIterator<Item = FaceId>,
edges: impl IntoIterator<Item = EdgeId>,
vertices: impl IntoIterator<Item = VertexId>,
) {
let edges: Vec<EdgeId> = edges.into_iter().collect();
let excluded_half_edges: Vec<HalfEdgeId> = edges
.iter()
.flat_map(|edge| [edge.lesser(), edge.greater()])
.collect();
let initial_half_edge = self
.face_half_edges(absorbing_face)
.find(|half_edge| !excluded_half_edges.contains(half_edge))
.unwrap_or_else(|| {
self.face_rim_half_edges(absorbing_face)
.find(|half_edge| !excluded_half_edges.contains(half_edge))
.unwrap()
});
let perimeter_half_edges: Vec<HalfEdgeId> = self
.circulate_half_edges_with_excludes(initial_half_edge, excluded_half_edges.clone())
.collect();
self.absorb_faces_over_edges_and_vertices_in_perimeter(
absorbing_face,
faces,
edges,
vertices,
&perimeter_half_edges,
);
}
pub fn merge_faces(&mut self, faces: impl IntoIterator<Item = FaceId>) {
let mut faces = faces.into_iter();
let absorbing_face = faces.next().unwrap();
self.absorb_faces(
absorbing_face,
faces.filter(|face| face.id() != absorbing_face.id()),
);
}
pub fn absorb_faces(
&mut self,
absorbing_face: FaceId,
faces: impl IntoIterator<Item = FaceId>,
) {
let mut half_edges_counter = HalfEdgesCounter::new();
let mut vertex_weights_counter = VertexesCounter::new();
let faces: Vec<FaceId> = faces.into_iter().collect();
half_edges_counter.visit_face_half_edges(self, absorbing_face);
vertex_weights_counter.visit_face_vertices(self, absorbing_face);
for &face in &faces {
half_edges_counter.visit_face_half_edges(self, face);
vertex_weights_counter.visit_face_vertices(self, face);
}
self.absorb_faces_over_edges_and_vertices_in_perimeter(
absorbing_face,
faces,
half_edges_counter
.inner_edges(self)
.collect::<Vec<EdgeId>>(),
vertex_weights_counter
.visited_vertices()
.filter(|&vertex| {
self.spokes_reverse(self.vertex_representative(vertex))
.all(|edge| half_edges_counter.is_inner_edge(edge))
})
.collect::<Vec<VertexId>>(),
&half_edges_counter
.outer_edges(self)
.map(|(half_edge, _)| half_edge)
.collect::<Vec<HalfEdgeId>>(),
);
}
pub(crate) fn absorb_faces_over_edges_and_vertices_in_perimeter(
&mut self,
absorbing_face: FaceId,
faces_to_absorb: impl IntoIterator<Item = FaceId>,
edges_to_remove: impl IntoIterator<Item = EdgeId>,
vertices_to_remove: impl IntoIterator<Item = VertexId>,
perimeter_half_edges: &[HalfEdgeId],
) {
self.remove_orphaned_faces(faces_to_absorb);
self.remove_orphaned_edges(edges_to_remove);
self.remove_orphaned_vertices(vertices_to_remove);
self.wire_inner_half_edge_chain(absorbing_face, perimeter_half_edges);
}
}
#[cfg(all(test, feature = "stable-vec"))]
mod test {
use crate::{
EdgeId, FaceId, HalfEdgeId, StableDcel, VertexId, assert_face_boundary,
init_dcel_with_3x3_hex_mesh,
};
#[test]
fn test_merge_faces_around_vertex() {
let mut dcel = init_dcel_with_3x3_hex_mesh!(StableDcel<(i32, i32)>);
dcel.merge_faces_around_vertex(VertexId::new(8));
assert_eq!(dcel.vertices().num_elements(), 29);
assert_eq!(dcel.half_edges().num_elements(), 70);
assert_eq!(dcel.faces().num_elements(), 8);
assert_face_boundary!(&dcel, 0, 0);
assert_face_boundary!(&dcel, 1, 6);
assert_face_boundary!(&dcel, 3, 6);
assert_face_boundary!(&dcel, 5, 12);
assert_face_boundary!(&dcel, 6, 6);
assert_face_boundary!(&dcel, 7, 6);
assert_face_boundary!(&dcel, 8, 6);
assert_face_boundary!(&dcel, 9, 6);
}
#[test]
fn test_absorb_faces_around_vertex() {
let mut dcel = init_dcel_with_3x3_hex_mesh!(StableDcel<(i32, i32)>);
dcel.absorb_faces_around_vertex(FaceId::new(2), VertexId::new(8));
assert_eq!(dcel.vertices().num_elements(), 29);
assert_eq!(dcel.half_edges().num_elements(), 70);
assert_eq!(dcel.faces().num_elements(), 8);
assert_face_boundary!(&dcel, 0, 0);
assert_face_boundary!(&dcel, 1, 6);
assert_face_boundary!(&dcel, 2, 12);
assert_face_boundary!(&dcel, 3, 6);
assert_face_boundary!(&dcel, 6, 6);
assert_face_boundary!(&dcel, 7, 6);
assert_face_boundary!(&dcel, 8, 6);
assert_face_boundary!(&dcel, 9, 6);
}
#[test]
fn test_merge_faces_over_edge() {
let mut dcel = init_dcel_with_3x3_hex_mesh!(StableDcel<(i32, i32)>);
dcel.merge_faces_over_edges_and_vertices(
[FaceId::new(5), FaceId::new(6)],
[EdgeId::new(HalfEdgeId::new(44), HalfEdgeId::new(45))],
[],
);
assert_eq!(dcel.vertices().num_elements(), 30);
assert_eq!(dcel.half_edges().num_elements(), 74);
assert_eq!(dcel.faces().num_elements(), 9);
assert_face_boundary!(&dcel, 0, 0);
assert_face_boundary!(&dcel, 1, 6);
assert_face_boundary!(&dcel, 2, 6);
assert_face_boundary!(&dcel, 3, 6);
assert_face_boundary!(&dcel, 4, 6);
assert_face_boundary!(&dcel, 5, 10);
assert_face_boundary!(&dcel, 7, 6);
assert_face_boundary!(&dcel, 8, 6);
assert_face_boundary!(&dcel, 9, 6);
}
#[test]
fn test_absorb_face_into_face_over_edge() {
let mut dcel = init_dcel_with_3x3_hex_mesh!(StableDcel<(i32, i32)>);
dcel.absorb_faces_over_edges_and_vertices(
FaceId::new(6),
[FaceId::new(5)],
[EdgeId::new(HalfEdgeId::new(44), HalfEdgeId::new(45))],
[],
);
assert_eq!(dcel.vertices().num_elements(), 30);
assert_eq!(dcel.half_edges().num_elements(), 74);
assert_eq!(dcel.faces().num_elements(), 9);
assert_face_boundary!(&dcel, 0, 0);
assert_face_boundary!(&dcel, 1, 6);
assert_face_boundary!(&dcel, 2, 6);
assert_face_boundary!(&dcel, 3, 6);
assert_face_boundary!(&dcel, 4, 6);
assert_face_boundary!(&dcel, 6, 10);
assert_face_boundary!(&dcel, 7, 6);
assert_face_boundary!(&dcel, 8, 6);
assert_face_boundary!(&dcel, 9, 6);
}
#[test]
fn merge_two_faces() {
let mut dcel = init_dcel_with_3x3_hex_mesh!(StableDcel<(i32, i32)>);
dcel.merge_faces([FaceId::new(7), FaceId::new(8)]);
assert_eq!(dcel.vertices().num_elements(), 30);
assert_eq!(dcel.half_edges().num_elements(), 74);
assert_eq!(dcel.faces().num_elements(), 9);
assert_face_boundary!(&dcel, 0, 0);
assert_face_boundary!(&dcel, 1, 6);
assert_face_boundary!(&dcel, 2, 6);
assert_face_boundary!(&dcel, 3, 6);
assert_face_boundary!(&dcel, 4, 6);
assert_face_boundary!(&dcel, 5, 6);
assert_face_boundary!(&dcel, 6, 6);
assert_face_boundary!(&dcel, 7, 10);
assert_face_boundary!(&dcel, 9, 6);
}
#[test]
fn absorb_face_into_face() {
let mut dcel = init_dcel_with_3x3_hex_mesh!(StableDcel<(i32, i32)>);
dcel.absorb_faces(FaceId::new(8), [FaceId::new(7)]);
assert_eq!(dcel.vertices().num_elements(), 30);
assert_eq!(dcel.half_edges().num_elements(), 74);
assert_eq!(dcel.faces().num_elements(), 9);
assert_face_boundary!(&dcel, 0, 0);
assert_face_boundary!(&dcel, 1, 6);
assert_face_boundary!(&dcel, 2, 6);
assert_face_boundary!(&dcel, 3, 6);
assert_face_boundary!(&dcel, 4, 6);
assert_face_boundary!(&dcel, 5, 6);
assert_face_boundary!(&dcel, 6, 6);
assert_face_boundary!(&dcel, 8, 10);
assert_face_boundary!(&dcel, 9, 6);
}
}