1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Direct editing — Golovanov §6.12: "delete face and heal" and "move a face
//! group" (see [`move_faces`] for the sibling operation's algorithm and
//! honest v1 scope).
//!
//! Removes a transition face (a chamfer, a constant-radius fillet, or any
//! simple 4-sided face) that sits between two larger neighbour faces, and
//! heals the resulting hole by EXTENDING the neighbours' carrier surfaces and
//! RE-INTERSECTING them so the neighbours meet each other directly where the
//! deleted face used to be. The classic use is "undo a chamfer/fillet": the
//! two large planes that flanked the bevel extend and re-intersect at the
//! original sharp edge, the end-cap faces lose the bevel corner, and the
//! solid returns to its pre-blend shape.
//!
//! ## Algorithm (extend → re-intersect → re-trim → reconnect)
//!
//! For a 4-sided transition face `F` with neighbours `N0..N3` (one per
//! boundary edge, in loop order):
//!
//! 1. **Classify.** The two neighbours on OPPOSITE boundary edges whose
//! (planar) carriers re-intersect in a line passing through `F`'s region
//! are the *primary* pair (the faces to extend and rejoin). The other two
//! opposite neighbours are the *lateral* faces (the end caps). Exactly one
//! opposite pairing must qualify, otherwise the heal is refused.
//! 2. **Re-intersect (extend).** Because analytic planes are unbounded
//! carriers, the primary pair's intersection line `S` is computed in closed
//! form (no marching within a bounded patch). `S` clipped by each lateral
//! plane gives the two recovered corner points — the new sharp edge's
//! endpoints (`triple points`).
//! 3. **Re-trim.** Every side edge that met `F` at a transition corner is
//! relocated onto the recovered corner; the deleted face's two support
//! edges become the single new edge `S` in both primary faces; the two
//! lateral (cap) edges collapse to points. Each affected neighbour face's
//! carrier plane is rebuilt large enough to cover its new boundary and all
//! its pcurves are recomputed against it (analytic planes extend for free).
//! 4. **Reconnect.** `F` and its boundary edges/vertices are pruned, `S` and
//! its two vertices are inserted, the shell is reassembled, the genus is
//! preserved, and the result must `validate()` or the whole operation is
//! refused.
//!
//! ## Covered vs deferred (honest scope of this first slice)
//!
//! - COVERED: a 4-sided chamfer/fillet (or any simple 4-edge transition face)
//! between two PLANAR primary neighbours with two PLANAR lateral caps, convex
//! or concave. Chamfer (planar transition) and fillet (cylindrical
//! transition) both reduce to the same planar-neighbour heal. CURVED
//! ANALYTIC neighbours route to [`heal_open_transition_mixed`], which
//! handles both curved primaries (plane × cylinder/ruled revolution
//! re-intersection) and curved lateral caps (the re-intersection branch is
//! clipped by curve×surface intersection against the cap's carrier).
//! - DEFERRED (returns a clear `Err`, never a bad solid): free-form
//! neighbours (need NURBS carrier extension + marched re-intersect),
//! transition faces that are not 4-sided (multi-face gaps), a neighbour that
//! borders the transition more than once (periodic/closed transition), and
//! configurations where the neighbours cannot re-intersect cleanly (parallel
//! planes, non-adjacent healing).
use crate;
use crate;
// The shared re-trim home (offset-unification audit §10). `Plane`,
// `plane_of_surface` and `retrim_planar_face` are re-exported by `geom` /
// `delete_face` so their existing call sites are untouched; these two are the
// new names direct-edit uses directly.
use crate;
// The shared RE-INTERSECTION seam (offset-unification audit §2.3). The exact
// closed forms stay reachable directly (`intersect_analytic_pair` below, on the
// lanes that always used them); this is the two-lane service the generic
// neighbour classes go through.
use crate;
use crate::;
use ;
use *;
use *;
use *;
use *;
use *;
pub use ;
pub use move_faces;
pub use offset_ruled_face;
pub use offset_sphere_face;
pub use offset_torus_face;
pub use offset_revolution_face;
pub use offset_freeform_face;