geop_core_topology/euler/
kef.rs1use crate::{EdgeId, FaceId, Model, boundary::BoundaryType};
2use geop_core_math::{
3 geop_error::{GeopError, GeopResult},
4 scalars::Scalar,
5};
6
7impl<S: Scalar> Model<S> {
8 pub fn kef(self: &mut Model<S>, edge: EdgeId, killed_face: FaceId) -> GeopResult<()> {
15 let ctx = |e: GeopError| {
16 e.with_context(format!(
17 "Model::kef(edge={edge}, killed_face={killed_face})"
18 ))
19 };
20
21 let refs = self.coedges_of_edge(edge);
22 if refs.len() != 2 {
23 return Err(ctx(GeopError::new("edge must have exactly two coedges")));
24 }
25 let (c0_id, c1_id) = (refs[0], refs[1]);
26 let c0 = self.get_coedge(c0_id)?.clone();
27 let c1 = self.get_coedge(c1_id)?.clone();
28 if c0.face == c1.face {
29 return Err(ctx(GeopError::new(
30 "edge's coedges must belong to different faces (use ker to merge two rings of the same face)",
31 )));
32 }
33
34 let absorbed_face_id = killed_face;
35 let absorbed_face = self.get_face(absorbed_face_id)?.clone();
36
37 let ((ca_id, ca), (cb_id, cb)) = if c0.face == killed_face {
38 ((c1_id, c1), (c0_id, c0))
39 } else {
40 ((c0_id, c0), (c1_id, c1))
41 };
42
43 let surviving_face_id = ca.face;
44 let keep_index = self
45 .find_boundary_containing(surviving_face_id, ca_id)
46 .map_err(|_| {
47 ctx(GeopError::new(
48 "could not find the ring containing the surviving coedge",
49 ))
50 })?;
51
52 let survivor = ca.prev;
53
54 self.coedges.get_mut(&ca.prev).unwrap().next = cb.next;
59 self.coedges.get_mut(&cb.next).unwrap().prev = ca.prev;
60 self.coedges.get_mut(&cb.prev).unwrap().next = ca.next;
61 self.coedges.get_mut(&ca.next).unwrap().prev = cb.prev;
62 self.coedges.remove(&ca_id);
63 self.coedges.remove(&cb_id);
64 self.edges.remove(&edge);
65
66 for c in self.iterate_loop_coedges(survivor).collect::<Vec<_>>() {
69 self.coedges.get_mut(&c).unwrap().face = surviving_face_id;
70 }
71
72 let absorbed_holes = absorbed_face.holes.clone();
77 let surviving = self.faces.get_mut(&surviving_face_id).unwrap();
78 surviving.set_boundary(keep_index, BoundaryType::Loop(survivor));
79 surviving.holes.extend(absorbed_holes);
80 self.faces.remove(&absorbed_face_id);
81 if let Some(shell) = self.shells.get_mut(&absorbed_face.shell) {
82 shell.faces.retain(|&f| f != absorbed_face_id);
83 }
84
85 Ok(())
86 }
87}