cam: the rotary radial sampler casts seam-straddling footprints 0.164° (1.6 cells) off their row — 36 near-axis pinholes in the panther's body

Open Beginner friendly
#1,096 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
three.js, typescript

Research direction

Read src/engine/cnc/rotary/radialField.ts, especially the footprint loop around line 250, and the existing retry pass to see how wrapped row angles are calculated. Add the red-first seam-straddling mesh spec described in the issue, then make the footprint loop cast each row at its wrapped index angle. Run the spec and the stated rotary readiness checks; done means the rotated fields agree cell for cell and the panther pinholes drop from 36 to 0.

Written by the indexing model from the issue text.

Description

fabrication ready

Found while writing #1094's fields (review session 0f, 2026-11-08). Scripts and the before/after sampler copy: /mnt/house/casemaker/1094-analysis/ (pin1094.mts, radialFieldFixed.ts).

1. Stamping fact

Panther readiness job (/mnt/house/casemaker/1086-panther/job-with-mesh.json), field 629 × 1978 at 0.1 mm, R 31.4663, covered 753,185. At (X 65.04, θ 180.08°) the field holds r = 0.265 while the exact ray from the axis hits the body at r = 11.545 (interior hit: u 0.162, v 0.829, det −2.4e-2; identical with the sampler's own 1e-9 tolerance). 36 pinholes (a covered cell ≥ 5 mm below all four neighbours), all at θ 178.4–182.3°, all recast to the body radius. One-line fix (below): pinholes 0, covered 753,104 (−81 hairline duplicates); 364,076 cells change, 394 by > 1 mm.

2. Mechanism

src/engine/cnc/rotary/radialField.ts:250: the footprint raster casts row jj at ang = (jj · pitch) / radius − seam where jj is the UNWRAPPED row index (negative when the triangle's first vertex has a negative atan2), and records the hit at j = ((jj % ny) + ny) % ny. The grid does not close: ny = ceil(2πR / pitch) gives ny · pitch = 197.8 mm against a circumference of 197.71 mm, so a negative jj is cast 2π − ny·pitch/R = 0.164° = 1.6 cells away from row j's true angle j · pitch / R. Every triangle whose first vertex lies in (−180°, 0] is written 1.6 cells off; those in (0, 180°] are not. At the boundary (θ ≈ 180°) far hits fall into the crack; a near-axis triangle (footprint 165–192°) still covers the cell, so the body reads 0.27 mm where it is 11.5 — the pinholes that drove #1094's 11 mm gouges. The retry pass does not see them: it looks at UNcovered cells only.

3. Picture

/mnt/house/casemaker/1094-analysis/1094-section-x64.94.png — the blue spike from the body to the axis at θ 180° is one of the 36.

4. Cost

None: one expression.

5. The change, named

radialField.ts footprint loop: cast each row at the WRAPPED row's own angle — const ang = (j * pitch) / radius - seam; (the retry pass already does). Must not change: the unwrapped footprint bounds jLo..jHi (they still pick the rows), the record rule (farthest hit, clipped to the rod), the retry, minVertexR. Alternative considered and not taken: forcing ny · pitch = 2πR would make the arc pitch differ from the X pitch, which every consumer assumes square.

6. Acceptance

  • Red-first spec: a mesh whose triangles straddle φ = ±180° (one triangle with vertices at 179.9° and −179.9°) sampled against the same mesh rotated 180° about X (position.y = πR): the two fields must agree cell for cell after the row shift; today they differ by 1.6 cells over half the map.
  • Panther: pinholes 36 → 0 at (X 65.04, θ 180.08°) r 0.265 → ≈ 11.5; covered 753,185 → 753,104; the cells changed by > 1 mm (394) are all within 2 cells of a seam-straddling triangle's edge.
  • The flat heightfield sampler untouched; every flat card unchanged to the digit; set B 14/14; the rotary readiness job's exact-stamp cut-into re-read and stated (expected: the pinhole class of gouges gone even before #1094's clamp lands — state the number, the clamp is still #1094's).
Dominant language
TypeScript
Stars
2
Forks
0
PR merge metrics
No merged PRs in 30d

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from SlyWombat/CaseMaker

All issues in SlyWombat/CaseMaker

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.