Commit Graph
31 Commits
Author SHA1 Message Date
Dylan M. Taylorandskylartaylor 0158712bfd security: bound geometry-kernel degree and work (CWE-407) (#1848)
* security: bound geometry-kernel degree and work (CWE-407)

Several geometry routines let a crafted spline or region cause quadratic or
worse CPU work:

- B-spline basis evaluation is O(degree²) per sample and tessellation takes
  O(degree) samples, so a HATCH/DXF spline edge declaring a very high degree
  (DXF allows up to 100 000) turned a tiny spline into billions of iterations.
  Add `MAX_DEGREE = 64` and treat higher-degree splines as invalid, so
  `eval`/`tessellate` fall back to the control polygon. The render clip boundary
  also rejects such degrees up front (rows 18, 28).
- `Spline::derivative` re-ran the O(knots) validity scan on every call, and
  arc-length integration calls it once per sample, making a valid spline's
  measurement quadratic. Split off `derivative_unchecked` and have integration
  (validated once by its public entry points) use it (row 24).
- `infer_knot_param` matched each fit parameter against the whole knot vector
  from the start. Both are ascending, so replace it with a linear merge (row 16).
- Fillet seed collection did not stop the enclosing run-pair loops when the
  per-call candidate cap was hit, and refined duplicate candidates. Bound total
  seeds across pairs and deduplicate before Newton refinement (row 36).
- Region grid intersection counted only distinct pairs against its budget, so a
  long segment replicated across many cells re-visited the same pair unbounded.
  Charge every candidate-pair visit against a budget (row 41).

New spline degree tests added; all geom and render tests pass, clippy clean.

Addresses findings rows 16, 18, 24, 28, 36, 41.

* fix: preserve spline knot and fillet search behavior

---------

Co-authored-by: skylartaylor <26588250+skylartaylor@users.noreply.github.com>
2026-10-22 17:05:16 -04:00
skylar taylor-barrick 78254b4d3f Merge pull request #1480 from Silvertree2010/fix/h2426-polyline-segments-with-a-tiny-no
Treat polyline bulges with a sub-EPS sweep as straight segments
2026-10-22 07:50:53 -06:00
13a3ebc0d1 AREA: an ellipse's perimeter is its exact length, not a closed-form estimate (#1471)
AREA's Object option reported a full ellipse's perimeter with
Ramanujan's closed-form estimate, which falls short as the ellipse
flattens: 46.0256 for a 10 x 4 ellipse (exactly 46.0262), 39.8741 for a
10 x 0.1 one (exactly 40.0110, 0.34% short). It now integrates the
perimeter with the geometry crate's ellipse arc length, the one LENGTHEN
measures with, so both report the same length for the same ellipse.

Ellipse::arc_length_from halves a panel where it needs it (the same
adaptive Gauss-Legendre as spline arc lengths): with fixed panels a
100:1 ellipse came out 4e-8 long, as it turns sharply at its ends.

Tests check four ellipses (round to 100:1) against the
arithmetic-geometric mean to 1e-9, and the printed AREA line.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 02:57:04 -04:00
ba27f36b58 Inquiry: SHAPES reports closed-shape geometry facts (#1507)
* Inquiry: SHAPES reports closed-shape geometry facts

`shapes` is a read-only command that reports, for every closed shape in the
current space (closed polylines, circles, full ellipses, closed splines),
its perimeter, area, centroid, winding, first self-intersection and
coincident vertices, exact with arcs and bulges. It filters and pages like
`entities` and counts other matches under `skipped` with the reason.

`Polyline::centroid` and `polygon_centroid` give the area centroid.

Fixes #1436.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* shapes: cap the quadratic self-intersection test at 4000 edges

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-19 02:53:10 -04:00
NetterSilverandClaude Haiku 5.5 4c75b0c458 Treat polyline bulges with a sub-EPS sweep as straight segments
Found while testing crates/geom/src/curve.rs:435 (bulge_to_arc) together with crates/geom/src/lib.rs:45-48 (ccw_sweep)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 04:43:01 +00:00
64b7825d08 Property-based and hostile-input tests for geometry numerics (gaps.md S6) (#733)
* Property-based and hostile-input tests for geometry numerics (gaps.md S6)

A deterministic xorshift64* generator (no new dependency) drives a few
thousand cases per property in crates/geom/src/property_tests.rs:

- line/line: hits lie on both lines, parameters reproduce the point,
  swapping the operands gives the same point, finite results agree with
  the infinite parameters
- line/circle and circle/circle: hits lie on both curves, results are
  symmetric, properly crossing circles match the closed form; hostile
  inputs (NaN, infinities, subnormals, raw bit patterns, 1e300) never
  panic and the guarded functions return only finite hits or none
- segments: extending only adds hits
- closest points: fixed point of closest, perpendicular inside the
  segment, endpoints outside
- arcs: at(0)/at(1) are the endpoints at radii from 1e-6 to 1e6; the
  three-point arc keeps {start, end} = {p1, p3} and contains p2 (the
  CCW-only storage swaps the pair when p2 is on the clockwise side, as
  DXF stores arcs) and matches the circumradius closed form; collinear
  inputs are rejected
- bounds and vector identities
- known answers at 1e6-1e7 coordinates hold to 1e-9 relative

gaps.md S6 removed and geometry-parity.md's Tests section updated in
the same change.

* docs: drop the sentence the new numerics tests make stale

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:16:44 -04:00
b209bb53e9 Geometry: param_at_length checks spline validity before clamping to the domain (fixes #704) (#741)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:09:01 -04:00
Jason Brashear 89c834155d Geometry: keep vector midpoints finite at coordinate extremes (#793) 2026-10-13 04:36:51 -04:00
c0335161c3 Geometry: spline arc length converges on tight bends, so LENGTHEN shortens to the target (#786)
* Geometry: spline arc length converges on tight bends, so LENGTHEN shortens to the target (fixes #705)

* Geometry: cap adaptive spline quadrature (depth 10, 1e-10 relative) so a hostile spline can't make LENGTHEN slow

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:36:28 -04:00
Marco Arnulfo 045212139a Geometry: fit splines with too many points use them as control points instead of a dense solve (fixes #702) (#773) 2026-10-13 04:34:56 -04:00
Valentin KleinandClaude Opus 5.5 d2fda54e8a feat(modify): PEDIT Edit vertex Break/Straighten/Tangent/Regen, SPLINEDIT fit data and vertex options, closed-spline fit tolerance (part of #554) (#558)
Squash of PR #558 by @vangel76.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:12:46 -04:00
Valentin KleinandClaude Opus 5.5 c0a19dfb9e FILLET with elliptical arcs and splines (part of #466) (#470)
Squash of PR #470 by @vangel76.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:41:59 -04:00
Valentin KleinandClaude Opus 5.5 ea0f866c7c EXTEND, JOIN and LENGTHEN on elliptical arcs and splines (part of #466) (#469)
Squash of PR #469 by @vangel76.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:41:45 -04:00
Valentin KleinandClaude Opus 5.5 d6aa802c75 Hatch: HPGAPTOL, pattern origin, separate hatches, island style; HATCHEDIT options and -HATCHEDIT (fixes #451) (#457)
Squash of PR #457 by @vangel76.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:29:05 -04:00
Valentin KleinandClaude Opus 5.5 e02d1ebd08 Hatch: associative hatches follow their boundary objects; DXF 97/330 source objects (part of #451) (#454)
Squash of PR #454 by @vangel76.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:28:33 -04:00
Valentin KleinandClaude Opus 5.5 a395ec3d2d SPLINE: Knots, start/end Tangency, toLerance and Object (part of #408) (#413)
SPLINE's Knots, Object, start/end Tangency and toLerance options printed
"not available yet". Fit-point splines now take a knot parametrisation
(chord, square root, uniform), end tangents (clamped cubic with derivative
constraints) and a fit tolerance (least-squares approximation with the
fewest control points that stay within it). The spline keeps these options
so grip and SPLINEDIT edits refit the same way; DXF writes the tolerance
(44) and tangents (12/13) and recovers the parametrisation from the knots.
Object turns 2D/3D polylines with straight segments (PEDIT Spline output)
into splines through their vertices.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:19:57 -04:00
Brandon ThomasandClaude Opus 5.5 0ef61cdff5 cargo fmt after the community PR batch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 18:44:34 -04:00
Nigel Ihza Firdausy 95dc3f22a7 fix(geom): keep finite-scale tolerance and midpoint math stable (#400) 2026-10-10 18:43:10 -04:00
Brandon ThomasandClaude Opus 5.5 964eb0fb40 cargo fmt after the community PR batch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 18:11:18 -04:00
Nigel Ihza Firdausy 35a8617855 fix(geom): use scale-aware circle-circle intersections (#384) 2026-10-10 18:08:37 -04:00
Nigel Ihza Firdausy 7bb64e5fce fix(geom): preserve boundary vertices far from the origin (#386) 2026-10-10 18:08:32 -04:00
Valentin KleinandClaude Opus 5.5 c55feb79da SPLINE Close is periodic, options report; POLYGON typed radius has a flat bottom; CIRCLE rejects bad input (fixes #238) (#240)
SPLINE Close now builds a smooth closed (periodic) curve through the fit points
instead of repeating the first point. The geometry gets Spline::from_fit_points_closed:
chord-length parameters including the closing chord, a periodic knot vector, and the
first three control points repeated at the end. The fit data no longer duplicates the
first point. DXF writes group 70 bit 2 (periodic) for it, and a file whose closed spline
needs refitting is refitted closed. SPLINEDIT Close/refit/move and fit-point grips keep
a closed spline periodic.

SPLINE Method asks Fit/CV, and CV continues as SPLINE by control vertices. Knots, Object,
start/end Tangency and toLerance report "not available yet" and stay at the prompt.
Garbage text reports "Point or option keyword required.".

POLYGON with a typed radius puts the bottom edge horizontal for Inscribed and for
Circumscribed. The JSON form uses the same orientation when no angle is given.

CIRCLE reports "Point or option keyword required." for an invalid token at the centre
prompt, and "Invalid point." at the 3P/2P point prompts, then asks again.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:34:24 -04:00
Brandon ThomasandClaude Opus 5.5 06f742c787 Clippy (as_chunks) and rustfmt after the community PR batch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:50:54 -04:00
Nigel Ihza Firdausy 9441dad29f fix(geom): avoid false line-circle tangencies on long construction lines (#214)
* fix(geom): avoid false line-circle tangencies on long lines

* fix(geom): construct tangent points relative to the projection foot
2026-10-10 14:39:13 -04:00
Nigel Ihza Firdausy c52f4d190e fix(geom): measure bulged polylines and distant polygons accurately (#212)
* fix(geom): compute polyline bulge areas without tessellation error

* fix(geom): preserve polygon area far from the coordinate origin
2026-10-10 14:38:57 -04:00
Nigel Ihza Firdausy f38b3a6447 fix(geom): calculate tight ellipse and arc bounds analytically (#211) 2026-10-10 14:38:42 -04:00
Nigel Ihza Firdausy 2e3dbe029f fix(geom): preserve three-point circle precision at large coordinates (#210) 2026-10-10 14:36:05 -04:00
Valentin KleinandClaude Opus 5.5 7666c1cd68 LINE: deferred tangent/perpendicular for the first point (fixes #69) (#168)
TAN and PER snaps need the other end of the line, so the first point of a
LINE (no base point yet) could never snap tangent: a belt line tangent to
two circles was impossible to draw.

Now, as in AutoCAD, a point prompt can accept *deferred* snaps:

- snap: with no base and the new `deferred` flag, osnap offers "Deferred
  Tangent" (circles, arcs) and "Deferred Perpendicular" (circles, arcs,
  lines, xlines, rays) where no other snap wins. The hit carries the curve
  (`SnapHit::deferred`, `Deferred`, `SnapCurve`).
- `resolve_deferred` solves the line once the other end is known: tangent
  or perpendicular from a point, tangent-to-tangent (common tangents of two
  circles, new `Circle::common_tangents` in geom) and the perpendicular
  mixes. Among several solutions the one nearest the picks wins. No
  solution (point inside the circle, concentric or nested circles,
  non-finite input) is `None`, never a panic.
- prompt: `Prompt::deferred()` opts a prompt in; `Input::Deferred` reaches
  only such prompts, everywhere else the session turns it into the point it
  was picked at, so other commands snap as before.
- LINE opts in for its first point (and the next one while the first is
  still deferred). No solution reports and re-prompts; Undo drops the
  deferred point. The rubber band shows the resolved line, also the
  tangent-to-tangent one while hovering the second curve
  (`Session::cursor_deferred`, set by the canvas).
- canvas: passes the prompt's flag to osnap and sends a deferred pick as
  `Input::Deferred`.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:15:18 -04:00
Valentin KleinandClaude Opus 5.5 4d61f57eec HATCH/GRADIENT/BOUNDARY: islands made of separate lines (fixes #106) (#163)
Point picks found the outer boundary by tracing the planar graph of all
curves, but islands only came from single closed objects (circles, closed
polylines, full ellipses, closed splines). A square drawn as four LINEs
inside a rectangle was ignored: HATCH drew through it, GRADIENT filled it
and BOUNDARY created only the outer polyline.

- geom::region::boundary_at returns the outer loop plus islands: every
  connected group of curves inside the face that doesn't touch its
  boundary and doesn't surround the pick point. Each island is the
  outline of the group's outside, traced with the same sharpest-turn
  walk from its leftmost vertex after dangling ends are pruned. Islands
  report which input curves they came from. Traces are bounded by the
  group's edge count and islands are capped at MAX_ISLANDS.
- loops_at (shared by HATCH, GRADIENT and BOUNDARY) adds those islands
  when every curve in the group is an open LINE, ARC, elliptical arc,
  open polyline or open spline. Groups containing a closed object keep
  the existing per-object islands, so closed-polyline and circle islands
  are unchanged (bulges kept).
- Tests: geom region tests for separate-line islands, dangling ends,
  open and attached curves, nesting and hostile input; engine tests for
  HATCH (rendered pattern stays out of the hole), GRADIENT (375 filled,
  hole clear) and BOUNDARY (two polylines) with four-line and
  closed-polyline islands.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:15:09 -04:00
Brandon ThomasandClaude Opus 5.5 cb68bed225 M4/M5: dimension commands, multileader, hatch boundary detection, blocks
DIMLINEAR/ALIGNED/RADIUS/DIAMETER/ANGULAR/ARC/ORDINATE/CONTINUE/BASELINE, QDIM, MLEADER, LEADER;
HATCH/GRADIENT/BOUNDARY/REGION with pick-point boundary tracing (planar face walk with islands);
BLOCK/INSERT/ATTDEF/ATTEDIT/WBLOCK/PURGE/BATTMAN; dimension text gaps and horizontal text;
DXF header writer whitelist (correct group codes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:31:44 -04:00
Brandon ThomasandClaude Opus 5.5 d9ab00c53c M0: CADCraft skeleton and vertical slice
Workspace (geom, dxf, color, doc, fonts, render, io, engine, ui-egui, mcp; apps cadcraft,
cadcraft-cli, cadcraft-web; xtask), AutoCAD-for-Mac style UI with code-drawn icons, command line
with prompts/keywords/AutoComplete, draw and modify commands, object snaps, polar/ortho,
selection, undo, layers and properties palettes, DXF read/write, SVG/PNG export, MCP server,
JSON control channel, CLI, wasm build, README, ROADMAP, AGENTS.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:22:25 -04:00