Sketch layer
- Trim/extend of an arc (and a circle opened into an arc) rewrites p0/p1 from the new angles;
the wire builder, the solver and snapping read them.
- Tangency binds the arc end that touches the line (or the other arc) instead of always the
start, so a fillet tangent to both legs solves; circle-circle / circle-arc tangency uses the
centre distance instead of CURVE_CURVE_TANGENT, which aborts on a circle.
- Point-on-line distances and circle-line tangency keep the side the geometry is on; a point
on an arc's rim uses PT_ON_CIRCLE.
- The partitioned solve keeps constraints onto the origin/axes and counts free entities' DOF.
- Zero-radius circles get no solver primitive and build no wire; constraints the solver cannot
apply are reported in SketchSolveResult::skipped.
- EllipseArc: mirror no longer yields the complement; after a solve its angles and ends are
re-derived; on the XZ plane it is no longer built mirrored.
- Offset: a circle follows the "+d = left of travel" rule (it shrinks, like a CCW arc chain);
chains are joined at the weld tolerance. Bridge end pole fixed (G1, no cusp). Negative-scale
transforms keep arcs and ellipses on their ends. Inference tolerances aligned with the weld.
Model layer
- Body references follow the body across delete / reorder / hide (resolved by the feature
that made it); datum-plane ordinals are re-pointed; an index past the end is an error, not
"the last body". New set_feature_enabled(). A move that puts a consumer above its input is
refused.
- Threads made from now on read thread_radius as the nominal major radius (internal: bore to
minor, groove to major; external: groove cut into the rod); older recipes build as before.
Bad thread parameters say why. Circular patterns span their angle end to end (new ones);
add_pattern pivots on the modeling origin.
- clear() drops variables; expression fields the GUI offers are bindable (thread_diameter,
helix_*, thicken_thickness, ...); deg()/rad() in expressions; the recipe saves the modeling
origin and body colours; names/colours follow bodies by identity.
- Boolean and dress-up failures throw instead of returning the input; one produces_body();
hole standards corrected (82° inch countersinks, UNC names, #10-24); legacy profile solve
validates indices and writes back only on success; v4 recipes read with a frozen field list.
Tests cover each of the above.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QK4VgguuCAk2hZLWgcjJb9
Review request on PR #15238: "Place CAD-related files (e.g. CadDocument/
GeometryEngine) into a separate folder."
src/libslic3r/CAD/ the kernel — CadDocument, GeometryEngine, the four
Sketch* units, SketchSolver, ThreadStandards
src/slic3r/GUI/CAD/ the tab — DesignPanel, DesignCanvas, DesignSketchTool,
SketchInlineEditor, McpControl, generated DesignOffer
Pure relocation: no line of logic changes. Two include rewrites follow from it —
files that moved re-spell their own neighbours against src/ (already on the
include path), and files that did not move pick up the new folder. docs and
docs/ux/mockups/gen_offer_table.py follow the same paths.
Verified: libslic3r, libslic3r_gui and libslic3r_tests all build, CAD suite green
at 2518 assertions in 194 test cases, and the sibling fork builds identically —
17 shared sources still byte-identical, 8 diverging by their expected counts.