bug(compose): cone apex lost — output is a truncated cylinder with hallucinated hole (synth_cone coverage 0.503, methodology_cone 0.367) #74
Labels
No labels
blocked:needs-decision
blocked:preflight
bug
in-progress
in-progress
lint-cleanup
needs-decompose
quickfix
triage-approved
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Mark/pc2cad#74
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Three coupled bugs surfaced together in the Sep-18 visual-regression sweep on samples/synth/synth_cone.ply (and the same shape on samples/methodology_cone.ply) — fixed in commit
4f2d3a5on main:1.
_synthesize_curved_only(pc2cad_compose.py) — the apex was lost.The cone primitive's inlier range
(t_min, t_max)was treated as the cone's actual extent, withr_bottom = abs(t_min) * tan(angle). When the fitter'st_minwas small but non-zero (the typical noisy-data RANSAC output, e.g.t_min=0.0081for synth_cone), the synth produced a frustum with two non-zero radii — the apex was rendered as a small ring instead of a single vertex.Fix: the apex radius is exactly 0; the base radius is at the FAR end of the inlier range (
max(|t_min|, |t_max|) * tan(angle)); the build123dConeis positioned so the apex vertex lands on the fit's apex point.2.
synthesize_body(pc2cad_compose.py) — no branch for a cone-dominant cluster.With synth_cone the cluster has 1 plane (base) + 2 cones (redundant lateral-surface fits). The previous code fell through to the planar-extrusion-then-SUBTRACT-curved path and produced a frustum-with-hole shape.
Fix: when the cluster contains cone primitives, the best-cone (most inliers) is emitted as the body. Coincident planes are redundant — the cone primitive already includes its base circle.
3.
synthesize_with_fallback(pc2cad_compose.py) — unit mismatch in validation.pts(rawpcd.points, in input units — mm) was compared against the synthesized solid (model units — m). Every distance comparison was off by ~1000×, validation reported coverage=0.000 against the correct cone, and the orchestrator fell through to the legacy path (which doesn't recognise cones and re-emitted the broken frustum-with-hole).Fix: rescale
ptsbyunits_scale_factorfromfit_result.reportbefore validation.4.
apply_plane_axial_holes(pc2cad.py) —plane_cone≠ hole.Stopped emitting
'hole'features forplane_coneintersections. The cone's base circle is the cone's base, not a hole — flagging it as a hole produced the 'hallucinated hole near the top' symptom called out in the issue.Coverage status (not fully meeting the ≥0.85 acceptance):
The synth cone is now well-shaped (clean
Coneprimitive with apex vertex, no hole, no frustum) and well-positioned for clean fits, but the cone RANSAC itself is non-deterministic and produces fits with apex offsets of ~5-10 mm from origin on these samples. The synth faithfully reflects the fit's parameters — when the fit's apex is at(3.5, -3.4, 85.7)instead of(0, 0, 80), the synth cone is positioned accordingly. Coverage at 1 mm tolerance is 0.61 (with fine tessellation, mesh_tol=0.05) on synth_cone; 0.37 on methodology_cone (where the fit lands further off-center).The cone-RANSAC accuracy is a separate bug — fixing it requires a more robust axis estimation than the current PCA-on-inliers seed. The synth code is now correct and ready for that improvement.
Verified:
--engine composenow emits aConeprimitive for synth_cone (was: 55-face polygon extrusion). STEP has 6 faces, 1 apex vertex.report.featuresno longer contains a'hole'withsource: plane_cone.report.trimmed_holesis empty.