geop_core_topology/euler/
kve.rs1use crate::{CoedgeId, Model, VertexId, 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 kve(
14 self: &mut Model<S>,
15 c_out: CoedgeId,
16 c_in: CoedgeId,
17 vertex: VertexId,
18 ) -> GeopResult<()> {
19 let ctx = |e: GeopError| {
20 e.with_context(format!(
21 "Model::kve(c_out={c_out}, c_in={c_in}, vertex={vertex})"
22 ))
23 };
24
25 let ce_out = self.get_coedge(c_out)?.clone();
26 let ce_in = self.get_coedge(c_in)?.clone();
27 if ce_out.edge().with_context(&ctx)? != ce_in.edge().with_context(&ctx)? {
28 return Err(ctx(GeopError::new(
29 "c_out and c_in must belong to the same edge",
30 )));
31 }
32 if ce_out.next != c_in || ce_in.prev != c_out {
33 return Err(ctx(GeopError::new(
34 "c_out and c_in must be adjacent to each other",
35 )));
36 }
37
38 let p = ce_out.prev;
39 let n = ce_in.next;
40 if self.get_coedge(p)?.next != c_out || self.get_coedge(n)?.prev != c_in {
41 return Err(ctx(GeopError::new(
42 "coedges surrounding the edge are not consistently linked",
43 )));
44 }
45
46 let edge = ce_out.edge().with_context(&ctx)?;
47 let edge_data = self.get_edge(edge)?.clone();
48 if edge_data.start_vertex != vertex && edge_data.end_vertex != vertex {
49 return Err(ctx(GeopError::new(
50 "vertex must be one of edge's two endpoints",
51 )));
52 }
53
54 self.coedges.get_mut(&p).unwrap().next = n;
55 self.coedges.get_mut(&n).unwrap().prev = p;
56 self.coedges.remove(&c_in);
57 self.coedges.remove(&c_out);
58 self.edges.remove(&edge);
59 self.vertices.remove(&vertex);
60
61 let face = self.faces.get_mut(&ce_in.face).unwrap();
62 for b in face.boundaries_mut() {
63 if *b == BoundaryType::Loop(c_in) || *b == BoundaryType::Loop(c_out) {
64 *b = BoundaryType::Loop(n);
65 }
66 }
67
68 Ok(())
69 }
70}