geop_core_topology/euler/
kemr.rs1use crate::{CoedgeId, Model, argument_validation::validate_same_loop, boundary::BoundaryType};
2use geop_core_math::{
3 geop_error::{GeopError, GeopResult, WithContext},
4 scalars::Scalar,
5};
6
7impl<S: Scalar> Model<S> {
8 pub fn kemr(self: &mut Model<S>, ca_id: CoedgeId, cb_id: CoedgeId) -> GeopResult<()> {
14 let ctx =
15 |e: GeopError| e.with_context(format!("Model::kemr(ca_id={ca_id}, cb_id={cb_id})"));
16
17 let ca = self.get_coedge(ca_id)?.clone();
18 let cb = self.get_coedge(cb_id)?.clone();
19 if ca.edge().with_context(&ctx)? != cb.edge().with_context(&ctx)? {
20 return Err(ctx(GeopError::new(
21 "ca_id and cb_id must belong to the same edge",
22 )));
23 }
24 if ca.face != cb.face {
25 return Err(ctx(GeopError::new(
26 "ca_id and cb_id must belong to the same face",
27 )));
28 }
29 validate_same_loop(&self, ca_id, cb_id).with_context(&ctx)?;
30
31 let face_id = ca.face;
32 let ring_index = self
33 .find_boundary_containing(face_id, ca_id)
34 .with_context(&ctx)?;
35
36 let ring1 = cb.next;
37 let ring2 = ca.next;
38
39 self.coedges.get_mut(&ca.prev).unwrap().next = cb.next;
43 self.coedges.get_mut(&cb.next).unwrap().prev = ca.prev;
44 self.coedges.get_mut(&cb.prev).unwrap().next = ca.next;
45 self.coedges.get_mut(&ca.next).unwrap().prev = cb.prev;
46 self.coedges.remove(&ca_id);
47 self.coedges.remove(&cb_id);
48 self.edges.remove(&ca.edge().with_context(&ctx)?);
49
50 let face = self.faces.get_mut(&face_id).unwrap();
55 face.set_boundary(ring_index, BoundaryType::Loop(ring1));
56 face.holes.push(BoundaryType::Loop(ring2));
57
58 Ok(())
59 }
60}