Split Face records the new edges as polylines on the body (Body::split_lines); the document carries them through later features. STEP export no longer joins pieces of one surface across such a line, and healing (fillets, chamfers, booleans, shell, draft) no longer merges coplanar pieces there, while incidental pieces (boolean leftovers, seam halves) still merge as before. Tests: plane and cylinder splits keep their face count through a STEP round trip (and join without the record), a second split keeps both lines, and an engine test exports a split box after a fillet with 8 faces.
Fixes#11
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT
blend_corner.rs rebuilds the planar faces at the ends of the filleted edges (three planar faces and three straight edges at each such vertex) and keeps the rest. One round at a vertex ends in the third face's exact section of its cylinder; two rounds with the third edge sharp trim each other (rolling ball: the crease from where their contact lines cross to the third edge for equal radii, else to the smaller round's contact line on the face that ends the larger one, which gets the exact section between); three rounds meet a sphere for equal radii, else a rational degree-4 patch through plane sections of the cylinders, the sections turned so that the cylinders' curvatures agree where two meet on a face and the patch fitted tangent to all three (within 0.01 degrees) and to the face at its closed corner.
kernel::fillet falls back to it when the local blends refuse: an edge that ends on an earlier round (any radius) takes the round off (delete_faces) and blends both edges together, so r3 next to r2 and a third edge into a mitred pair work. delete_faces: a gap stretch along several deleted faces keeps the corners between them (two rounds meeting in a mitre come off back to the sharp corner). splitface::fit is shared for the crease.
Tests: volumes against the strips-minus-overlap reference (exact strips, overlap integrated; checked against an independent 1D integral), the sphere-octant formula for three equal rounds, tangency along the patch, closed meshes, refusals without panics.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New kernel file blend_variable.rs. The hooks into blend.rs are visibility
only: plane_normal, vtx, rebuild_face and unsupported are now pub(crate).
- fillet_variable(body, edge, start, r0, r1) works on the same edge
configuration as the constant fillet (straight edge, planar faces, end
faces square to it). The radius runs linearly from the end nearest
`start`, and every section square to the edge is a circular arc. The
blend is an exact degree (2, 1) rational B-spline: arc control points
move linearly.
- fillet_chord(body, edges, chord): the radius per edge comes from its
face angle (chord = 2 r cos(phi/2)).
Fillet feature: style constant | chord | variable {radius2, start};
FusionFilletEdgesCommand takes type, radius2 and start.
Tests:
- Variable 2 -> 5 on a box edge removes (1 - pi/4) L (r0^2 + r0 r1 + r1^2)/3.
Starting from the other end gives the same solid; equal radii give the
constant fillet; too large is refused.
- Chord 4 on a right angle equals radius 4/sqrt(2).
- Engine: both types by command.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Export: ExportCommand/CLI --out/MCP export with .3mf write a 3MF Core package
([Content_Types].xml, _rels/.rels, 3D/3dmodel.model; millimetres), one
mesh object and build item per body, named after it, vertices shared and
welded watertight (T-junctions between faces split), base-material colours
when bodies carry one (STEP colours now ride on bodies). Tessellation as
for STL. File > Export 3MF.
Import: doc.open/drag-drop/CLI/MCP open accept .3mf and .stl; Insert Mesh
(ParaMeshInsertAlignCommand) adds them to a design as a MeshImport feature.
Kernel mesh bodies render, measure exactly, move and export; solid
features refuse them with a clear error. 3MF reading flattens components
and build transforms, converts units, reads colours; sizes, entries,
nesting and element counts are capped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
The kernel moved from monstertruck to truck: truck's booleans handle blind
holes, pockets and bosses that monstertruck's did not (see the ADR). Fillets
and chamfers on straight convex edges between planar faces are our own exact
local B-rep operation. The document holds parameters with unit-aware
expressions and a timeline that re-evaluates incrementally.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>