pub fn move_faces(
solid: &BrepSolid,
face_ids: &[u64],
translation: Vec3,
) -> Result<BrepSolid, String>Expand description
Golovanov §6.12 direct editing — translate a group of faces rigidly and heal the adjacency with the faces that stay behind.
The moved carriers translate exactly (every control point shifts by the translation, which is exact for ANY surface type), and each boundary edge between a moved face and a fixed face is recomputed as the intersection of the translated moved carrier with the fixed carrier:
- When the translation is parallel to every fixed plane a boundary vertex touches, the whole neighbourhood translates rigidly — exact for any moved carrier and any edge curve type. This is the extrude-like case: pushing a face along its own normal slides the side walls in-plane.
- Otherwise the new corner is re-solved as the common point of ALL carrier
planes meeting at the vertex (moved ones translated), and every affected
straight edge is rebuilt between the re-solved corners — the same
relocate-onto-recovered-corners move
delete_face_and_healperforms on its side edges.
Scope (honest refusals, never a bad solid): the moved faces may be any
surface type. A FIXED face that must be re-intersected — the fixed side of a
boundary edge, or any face whose boundary edges must be rebuilt — must be
PLANAR, OR an AXIS-PARALLEL ruled revolution: a cylinder OR a cone whose axis
the push is parallel to (SM1/SM1b). Such a carrier keeps its SAME surface and
only re-trims — its rim re-intersects it at a new radius, constructed by the
exact radial-scale map EdgeMoveAction::Transform (s = rho_at(z+d)/rho_at(z);
the cylinder is s = 1) and verified to lie on both modified carriers, then
grown along the axis (retrim_ruled_face). Every straight rebuilt edge (a
seam/generatrix) is verified on its carrier at its own rho_at radius.
An OBLIQUE cap push is supported on both carriers. The rim is the affine
image rim_ruled_map (a cylinder’s axis translation, a cone’s homothety
about the apex) — exact for the whole conic — and where that affine’s image
of a corner disagrees with the corner itself (a CONE, whose homothety slides
the arc’s endpoint off the fixed flat), the rim and the CURVED fixed edge it
meets are RE-BUILT as exact conic sections between the re-solved corners
(conic_arc_on_ruled, EdgeMoveAction::Replace); the corner itself comes
from the carrier-level solve corner_on_plane_and_ruled. A curved fixed edge
on a CYLINDER carrier, spheres, tori, general revolutions and a cap pushed
to/through the apex are refused (SM3 is the general offset path).
A translation that collapses an adjacent edge to zero length or reverses
its direction (moving a box face onto or past its opposite face) is
refused, as is a group that tears away from its neighbours. The input is
never mutated; the result is returned only when validate() is clean.