bug(fitter): methodology_flange has no bolt holes — output is a solid disc with no central bore (coverage 0.890) #76

Open
opened 2026-09-19 01:46:17 +00:00 by Mark · 1 comment
Owner

Summary

The compose engine's feature-hole detector fails on
samples/methodology_flange.ply. The output is a solid disc
with no bolt holes and no central bore — the defining features of
a flange are missing.

Coverage: 0.890 at 1mm tolerance (passes the gate, but the
visual is geometrically wrong — the gate alone doesn't catch this).

Reproduction

cd /home/b/Projects/pc2cad
.venv/bin/python pc2cad_cli.py samples/methodology_flange.ply \
    --out /tmp/methodology_flange.step --engine compose --deterministic-ransac --seed 42
.venv/bin/python tests/render_compare.py samples/methodology_flange.ply /tmp/methodology_flange.step \
    --out-dir /tmp/render --tolerance 1.0
# coverage: 0.890 (4452/5000 within 1.0 mm)

Input (methodology_flange)

A disc-shaped flange with a bolt-hole circle (multiple small holes
around the perimeter) and a central bore. Some noise; the holes are
visible as gaps in the pointcloud.

Expected

Reconstruction captures the flange's defining features:

  • Multiple bolt holes in the bolt-hole circle
  • Central bore

render_compare reports the holes are present in the output STEP.

Actual

Output is a plain solid cylinder/disc. No bolt holes. No central bore.
The cover passes the coverage gate because the disc wraps the input
loosely, but the geometric match is wrong.

Side-by-side: docs/visual-bug-evidence-2026-09-18/methodology_flange_side_by_side.png

Report findings

features list contains a single plane-based profile; no holes,
no capped cylinders, no bolt-hole pattern. The feature-hole
detector (_find_feature_cylinders) is not picking up the holes
on this fixture, even though the same detector finds the holes
on strategy_plate_with_hole (coverage 0.965, single hole found).

Acceptance

samples/methodology_flange.ply reconstruction contains the
bolt-hole pattern (multiple cylinders in the bolt-circle) and
the central bore. render_compare reports coverage ≥0.85 and
the STEP contains the expected hole features.

Refs: visual-regression sweep 2026-09-18, post-#70 close-out sweep.

## Summary The compose engine's feature-hole detector fails on `samples/methodology_flange.ply`. The output is a **solid disc** with no bolt holes and no central bore — the defining features of a flange are missing. Coverage: **0.890** at 1mm tolerance (passes the gate, but the visual is geometrically wrong — the gate alone doesn't catch this). ## Reproduction ```bash cd /home/b/Projects/pc2cad .venv/bin/python pc2cad_cli.py samples/methodology_flange.ply \ --out /tmp/methodology_flange.step --engine compose --deterministic-ransac --seed 42 .venv/bin/python tests/render_compare.py samples/methodology_flange.ply /tmp/methodology_flange.step \ --out-dir /tmp/render --tolerance 1.0 # coverage: 0.890 (4452/5000 within 1.0 mm) ``` ## Input (methodology_flange) A disc-shaped flange with a bolt-hole circle (multiple small holes around the perimeter) and a central bore. Some noise; the holes are visible as gaps in the pointcloud. ## Expected Reconstruction captures the flange's defining features: - Multiple bolt holes in the bolt-hole circle - Central bore `render_compare` reports the holes are present in the output STEP. ## Actual Output is a plain solid cylinder/disc. No bolt holes. No central bore. The cover passes the coverage gate because the disc wraps the input loosely, but the geometric match is wrong. Side-by-side: `docs/visual-bug-evidence-2026-09-18/methodology_flange_side_by_side.png` ## Report findings `features` list contains a single plane-based profile; no holes, no capped cylinders, no bolt-hole pattern. The feature-hole detector (`_find_feature_cylinders`) is not picking up the holes on this fixture, even though the same detector finds the holes on `strategy_plate_with_hole` (coverage 0.965, single hole found). ## Acceptance `samples/methodology_flange.ply` reconstruction contains the bolt-hole pattern (multiple cylinders in the bolt-circle) and the central bore. `render_compare` reports coverage ≥0.85 and the STEP contains the expected hole features. Refs: visual-regression sweep 2026-09-18, post-#70 close-out sweep.
Author
Owner

triage-runner partial fix landed (refs #76)

Shipped in commit becf5af on main.

What is fixed:

  • The compose engine now runs the body-aware _find_feature_cylinders sweep on the synthesized solid's bbox (previously it returned features=[] always, so only the body+features from fit_primitives cylinders were subtracted — and the flange's bolt holes and bore are missed by cylinder RANSAC because each bolt hole has only ~40 inliers).
  • _find_feature_cylinders had two coupled bugs preventing the central bore from being detected on methodology_flange:
    1. The sweep took candidates[0] (the strongest histogram peak) and gave up if it failed a downstream check. The body-outline peak at r=half_body_radius was the strongest candidate on the flange and got rejected, but the next strongest (the bore at r=10mm) was silently dropped. Now the sweep iterates all candidates per axis.
    2. The axial-extent check required inliers to span ≥50% of the body height. The flange is one-sided scanned (visible top face only — no bottom), so the bore's annulus spans only the upper 9mm of a 20mm body (45%). Relaxed the floor to 25%, which still rejects chamfered-edge rings (1-2mm axial extent) while accepting half-scans of thin parts.

Result:

  • methodology_flange STEP now has features=1 (the central bore) where it was features=0 before.
  • Coverage via render_compare.py at 1mm tolerance: 0.911 (up from 0.890).
  • STEP has 1 solid, 58 faces (was 6 solids, 62 faces — the multiple solids were an artifact of the body+features composition failing without subtraction).
  • test_plate_hole_detected_and_exported and the other 94 unit tests still pass — no regressions.

Still missing (known gap, documented in _try_axis docstring):

  • The 4-bolt-circle at 28mm pitch radius is not detected. Each bolt hole has ~40 inliers in the bolt annulus, which is too sparse for the 1.4× uniform-density histogram threshold to surface, and the dense plate-face coverage fills the azimuthal gaps between bolt holes in any sector count. A dedicated RANSAC at the body centroid (fitting circles at the body center with a search radius spanning the cap-to-outline band) is the planned replacement; tracked as a follow-up.

Acceptance status:

  • Coverage ≥0.85: ✓ (0.911)
  • STEP contains central bore: ✓
  • STEP contains bolt-circle pattern: ✗ (known gap)

This is partial progress; please verify the bore appears in the rendered output and either accept this or open a follow-up for the bolt-circle detector.

## triage-runner partial fix landed (refs #76) **Shipped in commit becf5af on main.** **What is fixed:** - The compose engine now runs the body-aware `_find_feature_cylinders` sweep on the synthesized solid's bbox (previously it returned `features=[]` always, so only the body+features from `fit_primitives` cylinders were subtracted — and the flange's bolt holes and bore are missed by cylinder RANSAC because each bolt hole has only ~40 inliers). - `_find_feature_cylinders` had two coupled bugs preventing the central bore from being detected on `methodology_flange`: 1. The sweep took `candidates[0]` (the strongest histogram peak) and gave up if it failed a downstream check. The body-outline peak at r=half_body_radius was the strongest candidate on the flange and got rejected, but the next strongest (the bore at r=10mm) was silently dropped. Now the sweep iterates all candidates per axis. 2. The axial-extent check required inliers to span ≥50% of the body height. The flange is one-sided scanned (visible top face only — no bottom), so the bore's annulus spans only the upper 9mm of a 20mm body (45%). Relaxed the floor to 25%, which still rejects chamfered-edge rings (1-2mm axial extent) while accepting half-scans of thin parts. **Result:** - `methodology_flange` STEP now has `features=1` (the central bore) where it was `features=0` before. - Coverage via `render_compare.py` at 1mm tolerance: **0.911** (up from 0.890). - STEP has 1 solid, 58 faces (was 6 solids, 62 faces — the multiple solids were an artifact of the body+features composition failing without subtraction). - `test_plate_hole_detected_and_exported` and the other 94 unit tests still pass — no regressions. **Still missing (known gap, documented in `_try_axis` docstring):** - The 4-bolt-circle at 28mm pitch radius is **not** detected. Each bolt hole has ~40 inliers in the bolt annulus, which is too sparse for the 1.4× uniform-density histogram threshold to surface, and the dense plate-face coverage fills the azimuthal gaps between bolt holes in any sector count. A dedicated RANSAC at the body centroid (fitting circles at the body center with a search radius spanning the cap-to-outline band) is the planned replacement; tracked as a follow-up. **Acceptance status:** - Coverage ≥0.85: ✓ (0.911) - STEP contains central bore: ✓ - STEP contains bolt-circle pattern: ✗ (known gap) This is partial progress; please verify the bore appears in the rendered output and either accept this or open a follow-up for the bolt-circle detector.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Mark/pc2cad#76
No description provided.