Skip to main content

geop_core_topology/edit/
merge_vertex.rs

1use crate::{CoedgeGeometry, Model, VertexId, boundary::BoundaryType};
2use geop_core_math::{
3    geop_error::{GeopError, GeopResult},
4    scalars::Scalar,
5};
6
7impl<S: Scalar> Model<S> {
8    /// Merges `vertex_deleted_id` into `vertex_into_id`: unions their points
9    /// into `vertex_into_id`, repoints every edge/coedge/boundary reference
10    /// from `vertex_deleted_id` to `vertex_into_id`, then drops the now
11    ///-unreferenced vertex.
12    pub fn merge_vertex(
13        &mut self,
14        vertex_into_id: VertexId,
15        vertex_deleted_id: VertexId,
16    ) -> GeopResult<()> {
17        // A self-merge would delete a vertex still referenced everywhere it
18        // stood in for `vertex_into_id` a moment ago — always a caller bug
19        // (typically: merging against a stale vertex snapshot taken before
20        // an earlier merge already welded the two together), so this is
21        // rejected rather than silently absorbed.
22        if vertex_into_id == vertex_deleted_id {
23            return Err(GeopError::new(format!(
24                "Model::merge_vertex: vertex_into_id and vertex_deleted_id are both {vertex_into_id} — refusing to merge a vertex into itself"
25            )));
26        }
27
28        // union the deleted vertex into point
29        let deleted_point = self.get_vertex(vertex_deleted_id)?.point;
30        let vertex_into = self.get_vertex_mut(vertex_into_id)?;
31        vertex_into.point = vertex_into.point.union(&deleted_point);
32
33        // Find all occurences of vertex_deleted_id and replace with vertex_into_id
34        for edge in self.edges.values_mut() {
35            if edge.start_vertex == vertex_deleted_id {
36                edge.start_vertex = vertex_into_id;
37            }
38            if edge.end_vertex == vertex_deleted_id {
39                edge.end_vertex = vertex_into_id;
40            }
41        }
42
43        for coedge in self.coedges.values_mut() {
44            if coedge.geometry == CoedgeGeometry::Vertex(vertex_deleted_id) {
45                coedge.geometry = CoedgeGeometry::Vertex(vertex_into_id);
46            }
47        }
48
49        for face in self.faces.values_mut() {
50            for boundary in face.boundaries_mut() {
51                if *boundary == BoundaryType::Vertex(vertex_deleted_id) {
52                    *boundary = BoundaryType::Vertex(vertex_into_id);
53                }
54            }
55        }
56
57        self.vertices.remove(&vertex_deleted_id);
58
59        Ok(())
60    }
61}