← back to pin list

2c. The vector front-end — built, measured, and where it resumes

kerfmaster pin list · Big capabilities

recordd10States what the code does today. Auditable against the code — this is the only type that can go stale.

Content last changed 2026-08-02 — computed from the item itself, not typed.

Contract — Intake stage

This contract describes the code as it runs today.

takes customer-filetrue-size

makes raw-geometryhealed-geometry

fails if read() proceeding without a stated real-world size (it raises ScaleUnknown, deliberately); a fit-induced kink; deviation quoted without splitting out the format's own inherent error.

Contract last changed 2026-08-06 — computed, not typed. Dated separately from the text above, so neither date can speak for the other.

1 open question blocks this pin

⚠ Known defects

This item's subject has a known defect in the code. Recorded and deliberately NOT fixed — recording a defect is not a licence to fix it. Source: cadmaster/defects.jsoncadmaster/KNOWN_DEFECTS.md, not this page — the text below is generated from the register so the two can never disagree.

Status 2026-08-01 (commit f714939): the front-end described in item 2a is built, measured, joined to the pipeline, and delivered as a board. Real production G-code now comes out of an Illustrator file. Item 14b (scale) is the one thing still blocking production use, and it blocks it in code: vec_pipeline.read() raises ScaleUnknown if no finished size is stated.

What exists

The board is a different board from the DXF one, deliberately

A DXF is healed from facets; an .ai is fitted from true curves. The measurements that decide pass/fail are different measurements, so build_vec_board.py is a separate program from build_board.py rather than the same one with a branch. Its output goes to viewer/<label>/, a subdirectory: the site root belongs to the DXF board and is never overwritten. Live at https://cadmaster.aristide.mycloudally.com/eagle/.

The gray base layer is the true Bézier sampled straight from the file, not our fit redrawn — a board that draws our own output twice would compare our work against itself and always look perfect.

Report deviation split three ways — house rule

Raw deviation from the true Bézier, the format's own inherent error at that radius, and what our fit adds. Only the third is ours. On EAGLES at a declared 12″: raw 1.667 thou, format floor 2.126 thou on the 6″ outer ring, fit adds 0.000. Quoting the raw figure alone is wrong in both directions — it blames us for the customer's file, and it hides how much headroom is left.

Measured — the numbers to beat

EAGLES.ai: 23 closed paths, 69 Bézier + 259 line segs, 0 fills, 1 clip path dropped, no live text → 358 arcs + 259 lines from the fitter; 346 arcs + 257 lines in 19 closed contours through the pipeline once the four specks are excluded. The circle comes back as ONE arc. Worst deviation from the true Bézier 0.05664 pt (1.667 thou at 12″), which is the file's own approximation error. Worst fit-induced kink 0.007878° — 28 arc-seconds.

Posted at a declared 12″ on 1/8″ steel: 19 boundaries, 16 slugs, 13 slug tabs, 3 under the drop-through, 19 M98 pierces. PART SIZE reads 12 × 12 — the declared artwork size recovered independently through the geometry, which is a stronger check on the scaling than the code that does it.

MVT-ICONtest.ai (the independent control): 88 arcs + 15 lines, worst kink 0.031°, deviation 0.98 thou at an assumed 12″ width, circle → one arc. So the fit is not tuned to the eagle.

For contrast, commit 6767f3e (3-point arc fit) produced a worst fit-induced kink of 113.5178° — a fail by our own standard.

Why it was wrong, so it does not come back

  1. Fitting an arc through three points constrains position, not direction. The arc lands on the curve and then leaves in the wrong direction, so consecutive arcs meet at a corner that is not in the source. Fixed by constraining direction: one arc where the curve's own end tangents allow it, otherwise a biarc, whose joint is tangent-continuous by construction rather than by check.
  2. The expensive one — zero derivatives. An Illustrator "corner" handle is written with the control point sitting exactly on its anchor, which makes the first derivative there exactly zero. The tangent function fell back to the segment chord, which on EAGLES was up to 107° out. That bad tangent went into the fitter and into the checker, so the checker agreed with the code and both were wrong together. The direction is well defined, just carried by the second derivative: with c1 == p0 the curve leaves along c2 - p0; with c2 == p3 it arrives along p3 - c1.
  3. Two smaller leaks, both the same mistake in miniature — checking position where direction is what matters. A cubic flattened to a straight line took the chord's direction rather than the curve's (worth 9.5°); and merge(), fusing arcs, averaged their centres, and moving a centre tilts the end tangents (0.0155°). Both are now gated on direction as well as distance, and merge fits a least-squares circle through all members instead of averaging.
  4. Arc extents taken from endpoints — found by wiring this in, and it was a safety bug. A full circle carried as ONE arc has both endpoints in the same place, so the sweep came out zero and the arc measured as a single point. The slug-tab table is keyed on longest dimension, so a 5″ round slug measured 0.0000, fell under the 0.75″ drop-through, and was assigned no retention tab at all — a loose disc in front of the head. DXF never hit it because the healer splits circles into two semicircles; our own one-arc-circle feature is what exposed it. Same root cause understated PART SIZE and put the origin inside the geometry. Fixed in 625c35c, control in test_emit_extents.py, and the novi job is byte-identical before and after.
  5. The picture measuring itself. The board drew arcs at a fixed 2° step, which sags r(1−cos 1°)0.9 thou on a 6″ radius, over half the entire deviation the board was reporting, invented by the drawing rather than present in the geometry. Now stepped by chord sag (0.0002″); residual 0.1985 thou, which is the sag budget and nothing else. Same class of error as the deviation() ruler bug below — the instrument reporting its own resolution as the result. test_vec_board.py fails on the old sampler and passes on the new one.

Two facts about the format worth keeping

A cubic Bézier cannot be a circle. Illustrator's is out by 0.02725% of the radius (handles at κ = 4/3(√2−1)). Demanding a tighter fit than that makes the fitter chop a perfectly good circle into eight arcs chasing the file's own error — which is exactly what the first run did. bezier_floor() allows each candidate arc the error the format inherently has, scaled θ6 with a 1.3 safety factor, so it collapses to nothing on shallow spans and still rejects a genuine ellipse by orders of magnitude.

The ruler was part of the error. deviation() used to polygonise each fitted arc before measuring, so it reported its own resolution as the fit's error — Illustrator's circle read 0.0372% of radius where theory says 0.02725%. Measured against the arc itself it now lands on 0.02725% exactly, and the whole EAGLES run got ten times faster (67s → 6.6s).

Not done — where this resumes

  1. Arc economy. 346 arcs on EAGLES through the pipeline, where the old broken fit used 237, because a biarc spends two arcs on a span the 3-point fit covered with one. The untried lever is fitting a single tangent-matched arc across several consecutive Béziers (greedy span growth) before falling back to per-segment biarcs. Correctness first — a wordy program that is right beats a short one with corners in it — but this is the obvious next optimisation, and it starts with a measurement of how much is actually on the table.
  2. SVG reader. Same front-end shape, plus SVG's native A arc command, which we would preserve exactly the way a DXF bulge is preserved. Not written.
  3. Cut order. The eagle posts 7 rapids over a piece already cut and still tab-held. That is item 4f's search problem arriving from the vector side, not a new fault.
  4. Scale — the blocker. Every thou figure above is at a declared 12″ width, which is an input and not a measurement. Until item 14b is settled, no .ai file can be sized, and therefore none can be cut.

Source defects it already finds

EAGLES contains four stray paths between 0.29 and 1.07 pt long — anchors someone left behind, far too small to cut. Any path under 0.5% of the art's diagonal (a scale-free gate, since the real size is unknown at read time) is excluded from the G-code and listed, never dropped silently; on the board they show as gray with no colour over them, ringed orange.

QC also flags one duplicate/overlapping pair in the angel's wing — a 0.028″ hairpin whose walls sit within 6 thou, under the 7-thou kerf, so at 12″ the laser would simply remove the spike. It is a source defect (same class as item 12/13) and it is scale-dependent: at a larger declared size the feature becomes cuttable and the flag clears itself. One more reason 14b needs an answer.

Built and pinned 2026-08-01. Commits 6767f3e (extraction + first fit), 7c7597d (tangent-matched fit, tangent bug, exact ruler, control suite), bedc7e0 (the pipeline seam), 625c35c (arc-aware extents), f714939 (the vector board), 9418f93 (risk.detail + write_risk_report — the operator stand-by list, ranked worst first).