Skip to main content

geop_core_topology/euler/
kve.rs

1use 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    // Kill the vertex and edge spliced in by mve: c_out and c_in are mve's own two
9    // coedges (its returned coedge_forward and coedge_reversed) and must be adjacent
10    // to each other (c_out immediately followed by c_in), forming a dead-end spur off
11    // the rest of the loop. vertex must be one of their shared edge's two endpoints;
12    // it is removed along with the edge.
13    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}