Skip to main content

geop_core_topology/edit/
merge_edge.rs

1use crate::{CoedgeGeometry, EdgeId, Model};
2use geop_core_math::geop_error::{GeopError, GeopResult};
3
4impl Model {
5    /// Merges `edge_deleted_id` into `edge_into_id`: repoints every coedge
6    /// tracing the deleted edge to the surviving one, then drops the
7    /// now-unreferenced edge. `reversed` says whether the deleted edge ran
8    /// start<->end the *other* way round relative to the surviving one — if
9    /// so, every repointed coedge's `sense` is flipped so it keeps tracing
10    /// the same physical direction it always did.
11    ///
12    /// TODO: `edge_into_id`'s own curve currently stays exactly as it was —
13    /// it should instead be widened (unioned) to certainly contain the
14    /// deleted edge's curve too, so the kept edge's geometry honestly
15    /// reflects both original edges' combined tolerance instead of silently
16    /// favoring whichever one happened to survive.
17    pub fn merge_edge(
18        &mut self,
19        edge_into_id: EdgeId,
20        edge_deleted_id: EdgeId,
21        reversed: bool,
22    ) -> GeopResult<()> {
23        // Same self-merge hazard as `merge_vertex` — always a caller bug
24        // (typically: acting on a stale edge snapshot), rejected rather than
25        // silently absorbed.
26        if edge_into_id == edge_deleted_id {
27            return Err(GeopError::new(format!(
28                "Model::merge_edge: edge_into_id and edge_deleted_id are both {edge_into_id} — refusing to merge an edge into itself"
29            )));
30        }
31
32        // Only the coedges of the deleted edge are touched, so that a model
33        // sharing its arenas with a copy copies only those.
34        for id in self.coedges_of_edge(edge_deleted_id) {
35            let coedge = self.get_coedge_mut(id)?;
36            coedge.geometry = CoedgeGeometry::Edge(edge_into_id);
37            if reversed {
38                coedge.sense = coedge.sense.opposite();
39            }
40        }
41
42        self.edges.remove(&edge_deleted_id);
43
44        Ok(())
45    }
46}