Commit Graph
11 Commits
Author SHA1 Message Date
Hakan Seven dcedf945ea feat(spline): correct property semantics
Merge PR #824 while keeping periodic and coplanarity geometry in cadkernel.
2026-08-20 12:13:35 +03:00
Hakan Seven 1c408e3a73 feat(spline): improve fit and CV editing
Keep planar conversions kernel-backed and leave unsupported 3D, CV-to-fit, and closed rebuilds unavailable instead of changing curve data.\n\nRefs #815
2026-08-20 00:18:45 +03:00
ramox81 1a6b61fb3a Correct spline property value semantics 2026-08-19 16:50:49 +03:00
ramox81 5595837a69 Align spline properties and editing 2026-08-19 12:00:02 +03:00
ramox81 0d37d3ff78 Improve spline fit and control vertex grips 2026-08-19 11:02:32 +03:00
Hakan Seven ac8183ec91 refactor(cad): use direct stack dependencies 2026-08-10 15:03:31 +03:00
Hakan SevenandClaude Opus 5 ece440bcab refactor(curve): draw a fit spline and an offset preview from the curve
Two places were left describing geometry for themselves.

A fit-point SPLINE was drawn from a C² cubic solved in spline.rs while
TRIM and snap cut a separate interpolation from the kernel. Near enough
to look right, far enough apart that a trim landed beside the line it
was aimed at. It now draws the curve those commands work on, and falls
back to the local solve only where the kernel declines — a fit spline
through points in space is not a planar curve, so there is nothing for
it to say.

Closed fit splines were worse than that: the kernel's interpolation is a
clamped solve with no wrap in it, so the curve TRIM used never returned
to its start and the seam cut nothing. Repeating the first fit point
closes it. The seam is C¹ where the rest of the curve is C², which is
the honest limit of a clamped solve — the alternative was a curve with a
gap in it.

OFFSET's preview sampling had drifted the same way TRIM's had: an arc
and a circle read `center.x/.y` as world coordinates when the entity
stores them in its OCS, so an extruded one previewed on the wrong side;
every curved kind was cut at a fixed twenty segments per radian whatever
its size; and an ellipse rebuilt its axis frame from the major axis' X
and Y alone, dropping the Z the entity stores. A hundred lines of that
become one tessellation. A RAY now previews as far as an XLINE does
rather than as a stub the length of its direction vector.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:08:45 +03:00
Hakan SevenandClaude Opus 5 57661c5754 feat(entities): give an entity its geometry as a curve
The same shape was being read out of an entity's fields in three places
and the three had drifted. An arc's tessellation cut it at 20 segments
per radian, TRIM's sampling at 16, and its snap points came from a
fourth expression again; a spline was sampled at a fixed 96 points
however long it was; TRIM read an arc's centre as world coordinates
when the entity stores it in its OCS, so an arc carrying the (0, 0, −1)
normal a MIRROR leaves behind acted as a boundary on the wrong side of
the drawing.

entity_curve returns a PlanarCurve: the shape, plus the plane its
coordinates are read in. The plane comes from the entity's OCS — its
extrusion normal through the DXF arbitrary-axis algorithm — not from the
UCS. A UCS is the working plane a user drew in and an entity does not
remember it: draw a circle in a UCS turned 30° about Z and the stored
normal is still +Z, which is why the header keeps the UCS separately.
The algorithm itself stays in transform.rs, where the format is
understood and where #142's degenerate case was fixed once.

Entities that store world coordinates and may not be planar at all —
LINE, SPLINE — are checked rather than assumed. A spline whose points
wander in space returns None instead of being flattened onto XY, which
would move it.

entity_curve_xy folds the plane away for the editing commands, which
work in plan view and need every boundary in one frame before two of
them can be intersected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 00:43:35 +03:00
Hakan SevenandClaude Opus 5 042a479244 fix(spline): edit fit-point splines, and stop deleting the kept half
Two faults, reported together.

Fit-point splines could not be edited at all. A SPLINE is stored either as
a control polygon the curve approaches or as fit points it must pass
through with optional end tangents, and `spline_to_nurbs` only read the
first. A fit-point spline has no control points, so every command that
touched one — TRIM, BREAK, LENGTHEN, OFFSET — got nothing back and did
nothing. Two fit points with start and end tangents, which is what a
drawing stores for the simplest curve, was the clearest case. Fit points
now interpolate into an exact curve through cadkernel, so they are as
editable as any other spline.

Trimming deleted the whole spline when the surviving piece reached the
curve's own start. `trim_spline` cut away everything before the interval
and everything after it, and a cut at either end is a no-op that reports
nothing to do — which the end case handled and the start case propagated
as failure, dropping the piece. That is why one side of the cutting line
worked and the other emptied the drawing.

Elevation is read from whichever point list the spline actually has. A
fit-point spline has no control points, so it was falling to z = 0 on the
first edit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 17:08:17 +03:00
Hakan SevenandClaude Opus 5 0f8f4864ba refactor(spline): evaluate splines with cadkernel, weights and all
The spline path ran on truck's BSplineCurve<Point3>, which is not
rational. Weights were dropped on the way in and cleared on every split,
so a NURBS circle — which is how most circles arrive once they have been
through a modeller — was evaluated as a parabola and stayed one after a
break. cadkernel's NurbsCurve carries the weights and applies them in
homogeneous coordinates, and `spline_cut` splits by raising the cut to
full knot multiplicity, so both halves are exact and both stay rational.

`spline_ops` keeps the knot-domain call shapes the commands were written
against — `spline_range` replaces reaching for `range_tuple`, `spline_cut`
replaces `cut` plus the rebuild — so TRIM, BREAK, LENGTHEN and OFFSET
changed only where they named those.

Knot vectors for a rebuilt control polygon come from the kernel too, so
the clamped uniform vector is defined once rather than assumed in two
places.

truck is now absent from the whole spline path. It remains for 3D solids.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 16:55:07 +03:00
Hakan SevenandClaude Opus 4.8 3666c7fa69 refactor(modules): rename home module to draw, restore first-tab order
The Home tab was already titled "Draw"; rename the module to match:
folder modules/home → modules/draw, HomeModule → DrawModule, id "home"
→ "draw". The inner draw/ command folder is kept (modules::draw::draw).

Update build.rs PRIORITY ("home" → "draw") so the tab returns to the
front of the ribbon; registry.rs regenerates accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 11:49:14 +03:00