Add detect_mesh_features: crease-ring feature outlines (#108) - #113
Merged
Conversation
Wraps OCCTSwiftMesh v1.7.0's Mesh.creaseEdges(minAngleDegrees:) to find dihedral-fold-edge feature outlines (doors, panels, window returns, recesses) on raw scan meshes where recognize_features (BREP/AAG) has no face/edge structure to work against. Welds the mesh (mandatory precondition, mirroring MeshCurvatureTools), chains fold edges into closed rings and open paths largest-first, and reports each ring's containingZones when segment_mesh_zones has already run for the body. Optional render: the surface as a neutral translucent mesh plus one categorically-colored edges-only wireframe ViewportBody per ring, composited with a legend. Repins OCCTSwiftMesh 1.6.0 -> 1.7.0. Tool count 72 -> 73; test count 133 -> 141 (8 new cases: closed-ring detection, zone interplay, a flat zero-crease body, an unweldable soup, the maxRings cap, determinism, render output, and a dispatch-level argument guard). 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. 141/141 green.
One cosmetic nit, foldable into the landing-train rebase: the neutral surface body takes its normals from Lands second in the train: rebase over fit_primitives (#112), counts 73 -> 74, then v1.26.0. |
… to 74; fold in both review nits Union-resolves the parallel-development conflicts (registrations, dispatch, docs sections, count lines), reconciles tool count to 74 and test count to 146, keeps serverVersion 1.26.0, lists both new tools in the reference index row. Review nits: fit_primitives' empty-report message no longer blames minSupportTriangles when maxPrimitives emptied the list; detect_mesh_features' render backdrop shades with computed vertex normals instead of a constant fallback (welded meshes carry no normals). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… merge The conflict blocks split both tools' Tool() registration and dispatch case mid-expression; rebuilt as two complete registrations and two complete cases. 74 tools, 146 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
detect_mesh_features: crease-ring feature outlines (doors, panels, window returns, recesses) on raw scan meshes, wrappingOCCTSwiftMesh.Mesh.creaseEdges(minAngleDegrees:)(OCCTSwiftMesh#28, v1.7.0) — the mesh-domain complement torecognize_features, which needs BREP/AAG topology a scanned/STL body doesn't have.MeshCurvatureTools) ->creaseEdges. Detection, stats, and render all live on the same welded mesh, so there's no triangle/vertex-index correspondence problem to guard.ringsarray, largest-first; junction-aware chaining (upstream) splits Y/T intersections cleanly; unchained leftovers are counted, never dropped.segment_mesh_zoneshas already run for the body (matchingMeshSignature, welded triangle-count-survival guard), each ring reportscontainingZones— majority-first zone ids incident to the ring's vertices. Omitted with a warning when the zone table is stale or the guard fails; omitted silently when no zones exist at all.ViewportBodyper ring (no mesh triangles, soOffscreenRendererdraws its wireframe unconditionally) in a categorical color, composited with a legend.OCCTSwiftMesh1.6.0 -> 1.7.0 (verifiedPackage.resolvedpins1.7.0underOCCTMCP_FORCE_REMOTE_DEPS=1).Server.swiftschema + dispatch, dispatch-levelminAngleDegreesguard per the Add align_bodies: GOM-style point-to-plane ICP registration (#104) #106 convention);serverVersion->1.26.0.detect_mesh_featuressection indocs/reference/mesh-analysis.md(args, welded-internally note, junction semantics, zone interplay, therecognize_featuresdistinction), Phase 3 backlog updated to mark detect_mesh_features: crease-ring feature outlines (blocked on OCCTSwiftMesh#28) #108/OCCTSwiftMesh#28 shipped, README tool table + tool-count references (72 -> 73) across README/CLAUDE.md/docs/guides/getting-started.md/docs/reference/README.md.Coordination note
A sibling PR (
fit_primitives, #107, also OCCTSwiftMesh v1.7.0) is landing in parallel. Per the pre-assigned coordination plan, this branch is standalone-testable against currentmainat 73 tools; oncefit_primitiveslands first, a follow-up rebase on this PR (or a fresh PR) will bump the tool count to 74. ThePackage.swiftrepin comment's leading clause was written to be textually identical between both branches so that rebase conflict is trivial to resolve.Test plan
OCCTMCP_FORCE_REMOTE_DEPS=1 swift package resolve— confirmsPackage.resolvedpinsocctswiftmeshat1.7.0OCCTMCP_FORCE_REMOTE_DEPS=1 swift build— greenswift build -c release— greenswift test— 141/141 passing (133 baseline + 8 newMeshFeatureToolsTestscases: closed-ring detection on a round two-tier-cylinder fixture with ~90° fold angles / largest-first / stable ids, zone-interplaycontainingZonescorrectness, a genuinely flat zero-crease body, an unweldable far-apart-triangle soup, themaxRingstruncation warning, call-to-call determinism (byte-identical JSON), non-trivial PNG render output, and a dispatch-level invalid-minAngleDegreesguard)PingTests.toolCountupdated 72 -> 73;IntegrationTests' expected-tool-names list includesdetect_mesh_featuresFixture design note
The originally-planned square "mesa" (raised platform) fixture turned out to be a poor choice for exercising closed rings: a rectangular mesa's own vertical corners are themselves additional 90° creases (adjacent walls meeting at 90°), which turns every corner into a degree-3 junction and fragments what should be one clean ring into several short open paths. Switched to a round two-tier-cylinder fixture (no corners), matching OCCTSwiftMesh's own
docs/algorithms/crease-detection.mdtest-fixture guidance (coarseCappedCylinderMesh). Documented in the fixture's own doc comment and inCLAUDE.md'sMeshFeatureTools.swiftbullet.🤖 Generated with Claude Code