fit_primitives: RANSAC primitive report over a mesh (#107) - #112
Merged
Conversation
Wraps OCCTSwiftMesh v1.7.0's Mesh.segmentedRANSAC(_:) / segmentedAutoSelect( dihedral:ransac:) (OCCTSwiftMesh#27/#32): Schnabel-style global-inlier primitive extraction, distinct from segment_mesh_zones' edge-adjacent-only region growing, so one primitive can span regions the dihedral grower keeps separate (e.g. a cylinder interrupted by a boss). Optional zoneId scopes the fit to one zone via the same resolution path zone_continuity_sweep uses; strategy "auto" runs the dihedral-vs-RANSAC bake-off and reports which won. uncoveredFraction and a maxPrimitives cap are computed and reported separately, never conflated. Repins OCCTSwiftMesh to >=1.7.0. Tool count 72 -> 73, serverVersion -> 1.25.0, test count 133 -> 138. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collaborator
Author
Review: approvedVerified against the brief and the v1.7.0 upstream surface; no blocking findings.
One wording nit, fine to fold into the landing train: when Lands first in the train as v1.25.0, per the coordination plan; the detect_mesh_features PR rebases over it. |
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fit_primitives, wrapping OCCTSwiftMesh v1.7.0'sMesh.segmentedRANSAC(_:)/Mesh.segmentedAutoSelect(dihedral:ransac:)(OCCTSwiftMesh#27/fix(deps): floor + lock the crash-fixed Viewport cohort #32): Schnabel-style global-inlier primitive extraction over a body's (or one zone's) mesh.OCCTSwiftMeshfrom>=1.6.0to>=1.7.0.segment_mesh_zones vs. fit_primitives.
segment_mesh_zones' dihedral region-growing only ever absorbs edge-ADJACENT neighbours, so a cylindrical barrel interrupted by a boss reads as two-or-more zones there even though it's one cylindrical surface. RANSAC instead claims GLOBAL inliers — every triangle within tolerance of a fitted candidate counts wherever it sits in the mesh — so it can unify a primitive the zone table keeps split. That's the reverse-engineering question ("does this same primitive recur elsewhere") a per-region zone fit can't answer.Zone scoping. Optional
zoneId(fromsegment_mesh_zones) scopes the fit to just that zone's triangles, resolved via the identical pathzone_continuity_sweepuses (re-mesh at the zone's own stored deflection,MeshSignaturestaleness check,subMesh).Strategy.
"ransac"(default) or"auto"(segmentedAutoSelect's dihedral-vs-RANSAC substantial-clean-coverage bake-off;strategyScoresreports both scores pluschosen).uncoveredFractionvs. amaxPrimitivescap — kept strictly separate. The tool always calls the upstream primitive with an unbounded region count, souncoveredFractionreflects only "no primitive, at any cap, ever claimed this triangle."maxPrimitivesis then applied against the already largest-first-sorted result, with its own separate warning naming the triangle count it trimmed — never folded intouncoveredFraction. PassingmaxPrimitivesstraight into the library's ownmaxRegionswould conflate the two (per the library's own docs), which is exactly the ambiguity this design avoids.Other changes in this PR:
PingTests,IntegrationTests, README, CLAUDE.md, docs/reference/README.md, docs/guides/getting-started.md all updated).serverVersion→1.25.0.docs/reference/mesh-analysis.md: newfit_primitivessection; also tidies the stale "Phase 3 backlog" list (removed the Slippage integration: zone kind/axis in segment_mesh_zones + sweep axis defaults (blocked on OCCTSwiftMesh#26) #109/slippage and fit_primitives: RANSAC primitive report (blocked on OCCTSwiftMesh#27) #107/fit_primitives entries, both already shipped — left detect_mesh_features: crease-ring feature outlines (blocked on OCCTSwiftMesh#28) #108/detect_mesh_featuresand chore: pin swift-sdk to fork branch shipping numberValue #29/find_correspondences extras: compound + provenance + bbox inference (closes the rest of #24) #30 as still pending).CLAUDE.md: newFitPrimitivesTools.swiftbullet + updatedOCCTSwiftMeshdependency bullet mirroring thePackage.swiftrepin comment.Test plan
OCCTMCP_FORCE_REMOTE_DEPS=1 swift build— clean, confirmsPackage.resolvedpinsOCCTSwiftMeshat1.7.0.OCCTMCP_FORCE_REMOTE_DEPS=1 swift build -c release— clean.OCCTMCP_FORCE_REMOTE_DEPS=1 swift test— 138/138 passed (133 baseline + 5 new), including:planeandsphereprimitives found, largest-support-first,supportFractionsane, byte-identical across two calls (determinism).zoneId-scoped fit on the open-tube fixture: the barrel zone fits ~onecylindercovering most of its own triangles.strategy: "auto"reportsstrategyScores(dihedral,ransac,chosen).strategystring errors, naming the valid values (the Add align_bodies: GOM-style point-to-plane ICP registration (#104) #106 guard convention).minSupportTrianglesset between a small feature's and a large feature's triangle counts: the large one is still found, the small one reports viauncoveredFraction, and the two never mix into one warning.Deviations from the brief
None of substance. One documentation decision made independently: while touching
docs/reference/mesh-analysis.md's "Phase 3 backlog" list (which I had to edit anyway to remove the now-shippedfit_primitivesentry), I also removed the#109/slippage entry since that's already integrated intosegment_mesh_zones/zone_continuity_sweepperCLAUDE.md— the list was already stale on that point before this PR. Left#108/detect_mesh_features(the sibling PR's tool) and#29/#30untouched.🤖 Generated with Claude Code