Commit Graph
132 Commits
Author SHA1 Message Date
DuBearte e70bd52409 Extrude: a side drawn in collinear pieces is one face (#1788) (#1949)
Thanks @DuBearte.
2026-10-18 05:43:23 -04:00
83c31d77c4 surface.boundary: surfaces through boundary curves and curve networks (#763) (#2129)
* feat(geom): surfaces through curve networks, and spline spaces to build them

Adds spline_space (clamped B-spline spaces, Hermite interpolation, exact
embedding by Bézier degree elevation and knot insertion, a monotone cubic
for reparameterising) and network (loft, Coons and Gordon surfaces through
curves in one or two directions, with G1/G2 cross-boundary conditions
against a neighbouring face). Part of #763.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* feat(kernel): boundary surfaces from sketch curves, 3D curves and edges

kernel::boundary_network turns sketch chains, 3D sketch polylines and edge chains
into network curves, gives G1 frames of the faces along open edges
(EdgeFaces), builds the B-spline face (sides split at chain vertices so a
join shares the body's edges) and joins it into a surface body by stitching.
G2 is refused for now (not supported yet). Part of #763.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* fix(kernel): second derivatives of B-spline surfaces in the vendored truck-geometry

BSplineSurface::uuder and vvder multiplied the second differences by p
instead of p·(p − 1), as BSplineCurve::der2 does, so every surface of
degree p ≥ 3 (NURBS too, through its homogeneous surface) reported
1/(p − 1) of its second derivative: a cubic surface's curvature read as
half. This is why a G2 boundary surface on a cylinder measured half the
curvature it carries (#763). New tests hold both to finite differences
for degrees 2 to 5.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

* feat(kernel): G2 boundary surfaces against a body's face

The network always carried the face's curvature across a G2 edge; the
refusal came from measuring it with truck's halved surface second
derivatives (fixed in the previous commit). EdgeFaces now reads the
face's second fundamental form from the exact second derivatives
instead of differencing the normal. A new test holds the curvature
across a cylinder's edge to the cylinder's within 0.1%, also with a
sheared far curve; G3 is refused (a network holds up to G2).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

* test(kernel): a boundary patch with straight corners measures its own area

A stadium's arcs meet its lines at 180°, so the Coons patch is singular
at its corners. From such a corner the reference mesher's boundary walk
ran onto the B-spline's extrapolation past its domain (a planar spline
passes through every point of its plane there), and the face measured
289 mm² for its 158.5 (#763). The vendored mesher's bounded projection
(nearest_projection, #2043) keeps the walk on the domain; this holds it
there, by the faces, the measuring mesh and the display mesh. The
display path (#1653) was never affected.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

* feat(geom,kernel): three-sided boundary surfaces (one side collapsed to a point)

A network curve may be a PointCurve: the apex where the two sides beside
it meet. The curves through it cross it at the point itself, its row of
the net collapses there, and the kernel's face leaves that side out of
its loop (three edges, one vertex at the apex). One point per patch, as
a side; refused elsewhere, when it moves, or with a continuity
condition. Tests: a triangle and a quarter disc filled flat with their
analytic areas (40 mm², 25π), by geom and by the kernel's faces and
meshes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

* feat(doc): boundary surfaces through curve networks and loops of three or four

FeatureKind::SurfaceNetwork saves a network as `u` and `v` curves, each
a sketch chain (planar or 3D), a chain of a body's edges with an
optional G1/G2 continuity, or a point (the apex of a three-sided
patch), and an `operation` that can join the surface into the body of
its edges. A SurfaceBoundary of three or four sketch curves, refused
until now, builds as the flat Coons patch of its loop (three collapse
the side opposite the first curve). The format change is one pending
file; feature-walk goldens record the new variant's sketches, bodies
and points.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

* feat(engine): surface.boundary through loops of three or four and curve networks

The command keeps its loop form (two to four curves of one sketch; three
and four now build the flat patch of the loop, crown refused there) and
gains a network form: `u` and `v`, each curve a sketch curve id, a
{sketch?, curves} chain (planar or 3D), a {body, edges, continuity?}
edge chain (g1/g2 with the face beside it) or a {point} for a
three-sided patch, with `operation` new or join. Edits may move between
the two forms (timeline.redefine accepts the command now that it has a
dialog).

Tests: analytic areas of loop patches and of a hyperbolic paraboloid
bounded by four 3D lines (every mesh vertex on z = xy/10), a loft
across two sketches, G1 and G2 measured across a cylinder's edge with
inspect.continuity (angle < 0.1°; curvature jump 1e-16 with G2 against
0.027 with G1), 26 hostile networks refused without panicking, and u/v
added to hostile_params_never_panic.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

* feat(ui): Boundary Surface dialog

Curves and Cross curves take sketch curves and edges (picks that meet
end to end in one sketch or body are one chain); Continuity and
Operation (New Body or Join). Two to four sketch curves of one sketch
with nothing across are the loop patch; anything else is a network.
Edit Feature brings either back (per-side orders, crown and stations
the dialog does not show are kept). Strings in en, ja and zh.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

* docs: ROADMAP M8 and the bridge patch's notes for boundary networks (#763)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

* test(oracle): a boundary surface through a loop, thickened (#763)

Case 83: four sketch curves (a square's three sides and a half circle
for its top) make one boundary surface, thickened 2 mm; analytic values
from tools/oracle-analytic/cases_surfaces.py (V = 2A, area 2A + 2P,
centroid by moments). Recipes gain boundary_surface, thicken and remove.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

* refactor: boundary surfaces, review cleanups

Project onto the face once per derivative evaluation (the frame is
passed to natural() and reused by scale()), keep each track's
finite-difference step instead of rescanning its table, export the
kernel's edge-pick and chain caps and the default station count for
the engine, doc and dialog to share, map TooLarge spline errors to
KernelError::TooLarge, reuse the engine's operation parser, and skip
the dialog's sketch lookup when the picks are no loop.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM

---------

Co-authored-by: jyviko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: bherbruck <[email protected]>
2026-10-17 21:47:38 -04:00
Koschtetnix 487aa64e10 Multi profile extrusion performance (#2064)
Thanks @Koschtetnix.
2026-10-17 18:30:52 -04:00
fkirill 2c924fd385 Sweep: close circular tools before cutting a torus (#2005) (#2010)
Thanks @fkirill.
2026-10-17 12:46:21 -04:00
NOWN-DEV 8a2d142333 fix: a cut takes only its sketch, a join adds only it (#1310)
Thanks @NOWN-DEV.
2026-10-17 08:42:17 -04:00
NOWN-DEV 40abcbc8cf Booleans: prism cuts whose walls only touch the target are exact (#1894)
Thanks @NOWN-DEV.
2026-10-17 08:00:06 -04:00
DuBearte b04e0801d6 Per-command timings for script runs and batches (#1868)
Thanks @DuBearte.
2026-10-17 07:26:20 -04:00
Mateusz Sych d1b96100d3 Split Body: a plane lying on a face of the body splits it exactly (#1510) (#1897)
Thanks @SychPL.
2026-10-17 07:21:06 -04:00
NOWN-DEV 186555dbe9 Clearance report: overlaps, near pairs and nearest bodies (#1900)
Thanks @NOWN-DEV.
2026-10-17 04:54:39 -04:00
Mateusz Sych 3eae8c34f6 Fillet beside a hole: the suggested largest radius fits (#324) (#1885)
Thanks @SychPL.
2026-10-17 04:08:39 -04:00
NOWN-DEV c38992fc09 fix: booleans with whole-turn round faces read from STEP are exact instead of failing (#1892)
Thanks @NOWN-DEV.
2026-10-17 04:08:34 -04:00
NOWN-DEV 962070e955 Interference: a pin a hair off the axis of its hole gets its crescent (#1893)
Thanks @NOWN-DEV.
2026-10-17 04:08:31 -04:00
Irakli Kourtis 98ce6a4ee8 Sweep guide rails and two-rail sweep (#771) (#1806)
Thanks @jyviko.
2026-10-17 04:07:46 -04:00
Mateusz Sych 920ea42fe1 Revolve: a partial turn's planar faces come out whole (#726) (#1718)
Thanks @SychPL.
2026-10-16 15:26:10 -04:00
Mateusz Sych 31b2ddc0cf Split Body: the face a plane split cuts takes an attachment that follows the plane (#565) (#1746)
Thanks @SychPL.
2026-10-16 13:26:11 -04:00
cronos bba03803b7 Accelerate current-view DXF export and keep desktop exports responsive (#1738)
Thanks @crono2250.
2026-10-16 10:26:27 -04:00
bherbruck 2c020dbcbc Revert #1682 (three-axis milling) (#1715)
Thanks @bherbruck.
2026-10-16 09:02:19 -04:00
CypherNaugh_0x 737c9358d0 Add three-axis milling with independent CAM and Fusion validation (#1682)
Thanks @CypherNaught-0x.
2026-10-16 08:26:28 -04:00
Mateusz Sych d84d8c3222 Joint origin: a circle given by its centre (#393) (#1686)
Thanks @SychPL.
2026-10-16 08:26:14 -04:00
midasdf bbd4f29ebb Class-A surfacing 3/3: blend curves, curved-edge fillets, the G2 corner and continuity analysis (#1642)
Thanks @midasdf.
2026-10-16 06:26:27 -04:00
midasdf 07da7f8065 Class-A surfacing 2/3: surface match, boundary patch and CV fairing (#1487)
Thanks @midasdf.
2026-10-16 03:26:20 -04:00
phanoob 9bb65b4d68 Booleans: a prism cut beside the target's other faces takes the exact 2D route in a column (#1629)
Thanks @phanoob.
2026-10-16 03:26:13 -04:00
JIJINBEI 3333f8a62b Divide intersection edges from their neighbours' parameters (#1038) (#1412)
Thanks @jijinbei.
2026-10-16 00:27:55 -04:00
Irakli Kourtis fac3f96bdd Patch: G1/G2 to the faces beside the loop, general and N-sided loops, points (#759) (#1521)
Thanks @jyviko.
2026-10-15 23:07:24 -04:00
rlartot daf618c344 Edge division: evaluate each point once (#1560)
Thanks @rlartot.
2026-10-15 22:19:51 -04:00
6ad391fd75 Chamfer: refuse a result that grows a convex edge's part (#1428)
* Chamfer: refuse a result that grew a convex edge's part (or shrank a concave one's)

A chamfer of a curved edge that runs off a face it skims (robustness seed 57's
ball rim) built a part bigger than before. Checked from the two faces' normals
at the edge; rounds and unclear angles are left to the wedge bound.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Action matrix: the sheet metal tray's relief corners refuse a 0.25 mm chamfer

Each is a 2.5 mm concave edge (the corner of a corner relief, between two
planes at right angles): a chamfer there fills at most 0.25²/2 × 2.5 = 0.08
mm³. What was built took 0.95 mm³ away; the chamfer guard now refuses it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Robustness goldens: seed 57's wrong-way chamfer is now refused (#1390)

On main with #391, seed 57's chamfer grew the part; this refuses it, so the run goes on
to its later steps and ends ok.

---------

Co-authored-by: Phanoob <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: bherbruck <[email protected]>
2026-10-15 14:26:30 -04:00
midasdf e8e2ccc8a9 Class-A surfacing 1/3: the continuity core, a G3 free-form blend and patch crown (#1249)
The continuity core (kernel bridge: Hermite control rows reproducing a support surface's position, tangent, curvature and change of curvature, G0 to G3), surface.blend between two edge chains (#764), and a crown for fitted patches. Existing patches and fillets are unchanged by default (crown 0 is the plain patch bit for bit). SurfaceBlend and Patch.crown are noted under format 22.
2026-10-15 13:32:16 -04:00
bherbruckandClaude Opus 5.5 4c7ea34a68 Web app: open and insert STEP files over frames, with progress and Cancel (#1376) (#1424)
* Web app: read a STEP file a piece per frame, with progress and Cancel (#1376)

The kernel's STEP reader walks the file first and converts its solids afterwards,
and StepReading exposes those stages: parse and walk, then convert a solid (or a
batch) per step, then finish into the shared import cache. The web app's file
load drives it from the frame loop for about 30 ms a frame, shows the same
progress card and Cancel as the desktop, and then runs the insert or open, which
finds the file already read. The desktop path is unchanged in behaviour.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Web app: make the imported bodies' meshes a few per frame too (#1376)

After the read, the insert or open runs, and then the bodies' display meshes are
made a frame's worth at a time ("Preparing the view"), as the desktop worker
warms them, instead of all in the first frame that draws the design.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-15 10:28:09 -04:00
bherbruckandClaude Opus 5.5 1744fbb262 Measure: centre-to-centre for holes, diameters for circles and arcs, slot sizes (#1392) (#1419)
Measure now reads the picked item's exact shape (cylindrical faces, circular and arc edges,
sketch circles, arcs and lines, profiles, planes, points):

- A circle, hole or arc shows Ø, R and its length (circumference, or arc length and angle).
- A slot (a sketch profile, or a half-cylinder end of a slot in a solid) shows its width,
  centre-to-centre length and overall length.
- Two items where one is round measure from the centre or axis by default (axis to axis,
  axis to plane, edge or point), with the closest and farthest distances listed too; the
  panel switches between centre, min and max, and the canvas line follows.
- inspect.measure and MCP `measure` (new `items` argument) add diameter, radius,
  center_distance, min and max; existing fields are unchanged.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-15 10:27:13 -04:00
Irakli Kourtis 5fa8e7d60a Sweep: orientation, twist and end scale (#1269)
Part of #771 and #772. solid.sweep and surface.sweep take orientation (perpendicular, parallel or a direction), twist (up to 4 turns) and end scale (0.01 to 100), applied about the profile's normal through the path's start; default options run the old sweep, so existing sweeps are unchanged. New fields are optional, left out when unset and noted under format 21; twist and scale are model parameters. Both sweep dialogs get Orientation, Twist and End Scale rows; labels in every catalog. Checked on main + this branch: cargo check --workspace, kernel/engine/UI sweep tests, the doc suite and the robustness goldens.
2026-10-15 06:24:31 -04:00
bherbruckandClaude Opus 5.5 8535d229ff Display helical-trimmed faces from imported threads correctly (#1289) (#1300)
A modelled thread as other CAD systems write it to STEP has cylinder faces trimmed by helices
that turn several times around the shaft, and cylinder faces bounded by two circles with no
seam edge. The display planner refused any face whose boundary winds around its surface, so
the whole body fell back to the reference mesher, which drew those faces with triangles across
the solid.

The planner now cuts such a face along a parameter line into one period: every loop and its
copies a period apart are clipped to the strip, and the parts of the cut line inside the face
join the pieces into closed loops, with the seam nodes made once for both sides. The cut face
is meshed by Delaunay with sag refinement, and the sag check runs once more after shaping.
Bodies with a face trimmed by more than one turn take their reference mesh (picking, measuring,
the CPU viewport) from the plan too.

Tests: an ISO M10x1.5 and M12x1.75 thread built from helices, as made and after a STEP round
trip: the display mesh stays within the tolerance of its surfaces and the thread's volume, and
has no degenerate, sliver or flipped triangles.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-15 00:51:30 -04:00
Irakli Kourtis b4edf05373 Extend any surface: natural, tangent and curvature, up to a target (#760) (#1166)
Extend works on any surface: natural (continuing the face's own surface), tangent (G1 run-off) or curvature (G2 run-off), by a distance, up to a plane or face, or back to the surface's bounds, with neighbouring edges lengthened to meet. Untrim and Extend share face parameter-loop helpers. The new SurfaceExtend fields are noted under format 21. Closes #760.
2026-10-14 22:46:29 -04:00
Irakli Kourtis 2a4907884b Ruled Surface: strips off an edge chain, exact where possible (#762) (#1151)
Ruled Surface: strips off an edge chain in normal, tangent, angle or direction mode, exact planes/cylinders/cones where possible, mitred or round corners, stitched into one surface body. SurfaceRuled is noted under format 21. Closes #762.
2026-10-14 21:44:56 -04:00
Irakli Kourtis 16c49c3e86 Untrim: holes removed and a face restored to its natural bounds (#1150)
Adds surface.untrim (#761); the SurfaceUntrim feature is first saved in format 21.
2026-10-14 20:29:25 -04:00
NOWN-DEV 2cab09f65b Join keeps its tool exact where the tool ends in the part's faces (#1244) 2026-10-14 20:18:09 -04:00
Que 1cc65cbc91 fix: a lip swept flush around a rounded rim joins the body it sits on (#1164)
fix: a lip swept flush around a rounded rim joins the body it sits on.
2026-10-14 18:49:45 -04:00
Lasse Lian 8f081679bc Equal cylinders crossing each other no longer refuse a cut (#788) (#1179)
Equal cylinders crossing each other no longer refuse a cut (#788).
2026-10-14 17:56:02 -04:00
NOWN-DEV c3aae64a63 Sheet metal: a cut-out with a corner a hair beside a bend line refolds (#1095)
Edges shorter than the model tolerance are dropped from the flat cells, and the refold sews touching corners, so a cut-out across a bend line no longer fails with a degenerate edge.
2026-10-14 13:59:07 -04:00
bherbruckandClaude Opus 5.5 563bcaff5b Refuse fillets and chamfers that run past their faces or cross each other (#1080) (#1124)
* Refuse fillets and chamfers that run past their faces or cross each other (#1080)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Blend fit: chamfers keep their old acceptance of crossed loops; skip the volume bound along tangent chains

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Blend fit: one selection per check, a coarse volume pass first; record the refused oversize blends in the action matrix baseline

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 11:46:44 -04:00
phanoob 4dbc0efff9 Taper any profile, sketch text included (#1014)
A tapered extrude now offsets spline and conic curves as well as lines and arcs, so sketch text and any other profile can take a taper, and the join of tapered letters onto a face finds its boolean result.
2026-10-14 09:47:44 -04:00
bherbruck 2f91338d3d Large STEP imports: no more multi-minute hang, shared STEP text, cancel and progress (#925) 2026-10-14 05:01:12 -04:00
midasdfandmidasdf 6e84c03946 Curvature-continuous (G2) fillets for straight planar edges (#862)
Fillet gets a Curvature (G2) radius type (type: "curvature", alias "g2"): a quintic blend whose size is the equivalent circular setback, for convex and concave straight edges between planar faces with a perpendicular planar end face at each end. Unsupported cases are refused rather than falling back to a circular fillet, and a blend that would cross a loop in its end face is refused. Persisted as a fillet style under format 19; labels in en/de/ja/ko/zh.

Co-authored-by: midasdf <[email protected]>
2026-10-14 04:26:53 -04:00
bherbruckandClaude Opus 5.5 813bee8914 Fillet: refuse a result with openings in its surface (#871) (#949)
* Fillet: refuse a result with openings in its surface (#871)

A fillet on #871's part (radius 1 on a window's edges and on the sides of a
block 1.26 mm away) came back closed as topology with every face meshing, but
the rounds overlapped and the end faces' boundary loops crossed, so the model
showed holes. The constant-radius fillet now checks its result before taking it:
the body's mesh, welded within a millionth of its size, must have no edge
without as many triangles running the other way along it, except for cracks
within the mesh tolerance where fitted curves meet. A result that fails is
refused, so the corner build gets its try and the radius search treats it as
too large.

Body::open_mesh_edges is the check. Kernel tests cover the #871 part (refused
at radius 1, closed with a round on every edge at 0.5), and an engine test runs
the fillet from the report and leaves the part as it was. All 96 robustness
seeds build the same with and without it.

Fixes #871

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Check fillets for crossed face boundaries, not free mesh edges

Free edges in the mesh also come from cracks where fitted curves meet (corner
patches, rounds ending on curved edges), so the mesh test refused good fillets.
The check is now on the cause of #871: a planar face whose boundary loops cross
each other or themselves has no inside. Body::crossed_face_loops samples each
planar face's loops within 1/1000 of the size and counts proper crossings
(touching within a millionth doesn't count).

The pyramid apex blend and the loft fillets build again. Ten action-matrix fillets
stay refused, recorded in the baseline: r = 3 on the 2 mm rim of oracle 09's
shelled box (the round runs past the inner wall; the result was 240 mm3 lighter
than any round can make it), and the six seam-edge fillets on oracle 60's bolt
holes, whose boundary jumps across the hole.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 01:36:30 -04:00
Lasse Lianandlasselian a2c7396160 Fillets and chamfers where edges meet at corners on a curved wall or a knife-edge tip (#851) (#935)
Rolling-ball blends now handle knife edges, where the two faces have opposite normals; an edge that runs out along an end face tangent to one side; and rounds that end in an earlier round on curved faces, picked together or one after another. The three edges at a vertex of smooth faces, rounded to one radius, end in a piece of sphere. When the given order of up to four edges is refused, or leaves a face boundary off its surface, other orders are tried.

Closes #851.

Co-authored-by: lasselian <[email protected]>
2026-10-13 23:21:47 -04:00
Irakli Kourtisandjyviko 2b70ed7b72 Offset Surface: faces copied out at a distance, exact or fitted (#758) (#872)
Offsets picked faces along their normals into a new surface body: planes and cylinders move exactly, other faces get a fitted B-spline within tolerance, and offsets that would fold over are refused. Adds the SurfaceOffset feature (noted under format 18), the surface.offset engine command and an Offset Surface dialog.

Closes #758.

Co-authored-by: jyviko <[email protected]>
2026-10-13 22:34:16 -04:00
Irakli Kourtis 897b7d93b5 Surface Loft: sheets through open or closed sections (#847)
Surface Loft lofts open or closed curve chains, one section per sketch in pick order, into surface bodies. Adds the SurfaceLoft feature (format 18 note), the surface.loft command, a dialog with Edit Feature support, and kernel and engine tests.

Part of #757.
2026-10-13 21:07:16 -04:00
Irakli Kourtis aba57f1ca2 Surface Sweep: sheets carried from open curves and profiles along a path (#843)
Surface Sweep carries open curves and closed profile boundaries along a sketch path into surface bodies, with smooth walls along curved point paths. Adds the SurfaceSweep feature (format 18 note), the surface.sweep command, a dialog with Edit Feature support, and kernel and engine tests.

Part of #757.
2026-10-13 20:48:30 -04:00
Giovanni 57d738eac4 Join walls swept along splines in 2D (#908)
Walls swept along a spline have flat B-spline tops and bottoms, so booleans between them went to the general intersection, which fails on coincident spline faces. Such faces are now put on true planes, and two prisms of the same height and direction are decided in 2D with their spline outlines fitted by arcs within a micron. The result is kept only when its volume is plausible; otherwise the general boolean takes over. The free-form flag is cleared by a drop guard so an unwinding boolean can't leave it set.

Fixes #844.
2026-10-13 20:48:27 -04:00
Irakli Kourtis 2eb292dd4a Surface Revolve: sheets turned from open curves and profiles (#824)
Surface Revolve turns open curves and closed profile boundaries about a sketch axis into surface bodies, with cone apexes and sphere poles where a chain ends on the axis, and a closed shell made solid. Adds the SurfaceRevolve feature (format 18 note), the surface.revolve command, a dialog with Edit Feature support and analytic kernel and engine tests.

Part of #757.
2026-10-13 20:30:41 -04:00
Irakli Kourtis b52d4390a0 face.delete heal: false leaves an open surface body (#861)
Delete Face takes heal (default true, as before). With heal: false the picked faces are removed and the gap stays open, leaving the remaining faces as a surface body (kernel remove_faces); deleting every face is refused. Saved only when false, noted under format 18.
2026-10-13 19:53:17 -04:00