After 1b, triangulating both polygons on every pair was the largest
remaining overlap cost (27% of main-thread samples on the corpus job).
PartOverlapChecker now triangulates each part at most once per check,
lazily after the bounding-box gate, and passes the triangles to a new
internal Collision.HasOverlap overload that runs the unchanged
OverlapRegions body. Triangles are only read by clipping and hole
subtraction, so reuse gives identical verdicts.
Verification:
- 49,000 seeded decisions with reused triangles match LegacyCollision;
triangles stay bit-identical to a fresh triangulation afterwards.
- Debug PolygonTriangulations: 246 -> 40 and 64 -> 36 per grid check;
sharing triangles per Program instead fails 23 tests.
- Corpus job (169 parts, --engines Default --parallel 1): median
13,398 -> 12,702 ms over 4+4 alternating runs vs 1b, identical
outcomes; serialized layout byte-identical to the base.
Also records the Follow-up B' (Slices 1a, 1b, 2a) measurements in
docs/performance/fill-performance.md.
Both HasOverlappingParts loops rebuilt each part's polygon from its
Program on every pair. PartOverlapChecker prepares each distinct Program
(reference identity) once and each part's world polygon once per call,
then uses the overlap-only Collision.HasOverlap. Loop order, bounding-box
prefilter, early exit and returned indices are unchanged; Part.Intersects
shares the material/polygon recipe and still returns crossing points.
Verification:
- Frozen LegacyPartOverlap differential (original Intersects and both
loops): verdicts, indices and world polygons bit-identical across fill
grids, patterns, touching/epsilon gaps, scribe/rapid/empty programs.
- Debug OverlapPolygonPreparations: 246 -> 1 and 64 -> 2 per check.
- Corpus job (169 parts, --engines Default --parallel 1, with 1a):
median 18,885 -> 13,464 ms over 4+4 alternating runs, identical
outcomes; serialized layout byte-identical to the base.
FillLinear re-prepared offset perimeter geometry (ConvertProgram ->
ShapeProfile -> OffsetOutward) for every part it measured, although
tiled copies share one Program and differ only by Location. A CPU
profile of a 169-part Default job put 62% of wall time there.
Prepare each distinct Program (reference identity) once per public
Fill/FillRow call in local frame, then clone and translate for each
location. The cache is created per call and passed down privately
because FillHelpers.FillPattern calls Fill concurrently on one
instance. PartGeometry gains a local-frame Program overload that the
Part overload now delegates to.
Evaluation order, lazy preparation, fallbacks and tiling are
unchanged. Differential tests against a frozen copy of the previous
FillLinear check bitwise equality, including concurrent calls; Debug
work tests pin preparation counts. With the thread pool capped at one
worker, before/after whole-job layouts are byte-identical. The
Default corpus job median drops from 40,715 to 18,810 ms.
CincinnatiSheetWriter.WriteHoleSubprogramCall emitted
`M98 P<num> X<x> Y<y>`, but per manual §3.98 ("M98 SUB-PROGRAM CALL
WITH NO ARGUMENTS") M98 takes only P and L — the X/Y had no defined
meaning to the control. The intent was to position the sub-program at
the hole center, which is what G52 is for per §1.52 ("local work
coordinate system") and which explicitly does not move the nozzle.
Emit the documented G52 bracket instead:
G52 X<hole.x> Y<hole.y>
M98 P<holeSubNum>
G52 X0 Y0
The hole sub-program is authored in hole-local coordinates, so its
first rapid (the lead-in to the pierce point) resolves to the absolute
pierce under the G52 shift and moves the tool directly there from the
previous feature's end — no phantom rapid to the hole center.
Also add docs/cincinnati-post-output.md as the reference for the full
post output format, with every emitted G/M code cross-referenced to
the Cincinnati programming manual. Un-ignore docs/ (docs/superpowers/
stays ignored) and track the PDF manual alongside the reference.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove implemented plan/spec docs from docs/superpowers/ (recoverable
from git history). Add .superpowers/ and launchSettings.json to gitignore.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three tasks: add TrimToCount with tests, replace shrink loop, replace
Take(N) in DefaultNestEngine.Fill.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clarify sort direction (ascending, keep nearest to origin), document
parameter changes, MeasureDimension behavior, and behavioral trade-off.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace expensive ShrinkFiller re-fill loop with axis-aware edge-sorted
trim. Also replaces blind Take(N) in DefaultNestEngine.Fill.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Includes fix for unlimited qty items (Quantity <= 0) that
RemnantFiller.FillItems silently skips. Workaround: convert
to estimated max capacity before passing in.
Also removes caliper angle sections from spec — RotationAnalysis
already feeds the caliper angle via FindBestRotation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Kept using OpenNest.Api in Timing.cs and EditNestForm.cs alongside
remote's reorganized usings and namespace changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Design for OpenNest.Api project providing a stateless NestRequest/NestResponse
facade over the engine, IO, and timing layers. Includes CutParameters unification,
multi-plate loop, .nestquote persistence format, and .opnest → .nest rename.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6-task plan covering PhaseStepperControl, DensityBar, form rewrite,
color-coded flash & fade, Accept/Stop buttons, and caller changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase stepper, grouped panels, density sparkline bar,
color-coded flash & fade, and Accept/Stop buttons.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add null safety in CreateDrawing helper, default Name from class name,
clarify diameter-vs-radius conventions, octagon width definition,
arc direction for rounded rectangles, and MCP parameter mapping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Defines a parametric shape library with abstract ShapeDefinition base
class and concrete subclasses for common CNC shapes (Tier 1+2).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 tasks across 3 chunks: extract AccumulatingProgress, ShrinkFiller,
AngleCandidateBuilder, PairFiller, RemnantFiller, then rewire both
engines and NestEngineBase.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add plateNumber parameter to PairFiller.Fill signature.
Document strip direction to ShrinkAxis mapping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>