Inspection
A four-step workflow for interrogating an existing body without modifying it: confirm it is topologically sound, measure its physical properties (including a tight bounding box for curved geometry), find faces or edges of interest by type, then detect pockets and holes automatically.
All four tools run on both the Swift occtmcp-server and the Node server.
The part used as the running example throughout this page is a 60 × 40 × 10 mm plate with two Ø8 mm through-holes (body id "part"). The interactive model below is that exact body exported via export_scene → glTF; the tool calls that follow use the same body.
🖱️ Drag to orbit · scroll to zoom · auto-rotating. (Model exported via export_scene → glTF.)
1. Validate geometry
Before doing any measurement, confirm the body is valid. An invalid shell or degenerate edge will silently corrupt downstream metric results.
See validate_geometry.
// tool call arguments
{ "bodyId": "part" }
// example result
{ "bodyId": "part", "valid": true, "issues": [] }
If valid is false, the issues array lists the violations (open shells, bad orientation, degenerate edges). Fix them with heal_shape before proceeding, then re-validate.
2. Compute metrics
Retrieve volume, surface area, center of mass, and bounding box in one call.
See compute_metrics.
Default bounding box (Bnd_Box)
// tool call arguments
{
"bodyId": "part",
"metrics": ["volume", "surfaceArea", "centerOfMass", "boundingBox"]
}
// example result
{
"volume": 22994.7,
"surfaceArea": 7101.6,
"centerOfMass": [30.0, 20.0, 5.0],
"boundingBox": { "min": [0.0, 0.0, 0.0], "max": [60.0, 40.0, 10.0] }
}
Tight bounding box for curved geometry
boundingBox uses OCCT’s Bnd_Box, which encloses the control-point hull of B-spline surfaces rather than the actual surface. For a cylindrical housing this can add several millimetres to each axis. Request boundingBoxOptimal instead — it calls BRepBndLib::AddOptimal, which samples the exact surface and returns the tight envelope.
boundingBoxOptimal is intentionally excluded from the default-all set; you must list it explicitly:
// tool call arguments
{
"bodyId": "part",
"metrics": ["boundingBox", "boundingBoxOptimal"]
}
// example result
{
"boundingBox": { "min": [0.0, 0.0, 0.0], "max": [60.0, 40.0, 10.0] },
"boundingBoxOptimal": { "min": [0.0, 0.0, 0.0], "max": [60.0, 40.0, 10.0] }
}
The difference is small on planar solids; on bodies with large-radius fillets or blended surfaces the Bnd_Box over-report can exceed 1–2 % of the overall extent. Use boundingBoxOptimal whenever the bbox drives a fit-check or clearance decision.
3. Query topology
Find faces or edges of a specific geometric type and get their stable index-based IDs.
See query_topology.
Planar faces (e.g. datum planes, mounting pads)
// tool call arguments
{
"bodyId": "part",
"entity": "face",
"filter": { "surfaceType": "plane" },
"limit": 20
}
// example result
[
{ "id": "face[0]", "surfaceType": "plane", "area": 2299.5, "centroid": [30.0, 20.0, 10.0] },
{ "id": "face[1]", "surfaceType": "plane", "area": 2299.5, "centroid": [30.0, 20.0, 0.0] },
{ "id": "face[2]", "surfaceType": "plane", "area": 400.0, "centroid": [30.0, 0.0, 5.0] },
{ "id": "face[3]", "surfaceType": "plane", "area": 400.0, "centroid": [30.0, 40.0, 5.0] },
{ "id": "face[4]", "surfaceType": "plane", "area": 600.0, "centroid": [ 0.0, 20.0, 5.0] },
{ "id": "face[5]", "surfaceType": "plane", "area": 600.0, "centroid": [60.0, 20.0, 5.0] }
]
Cylindrical faces (e.g. bore walls, pin seats)
// tool call arguments
{
"bodyId": "part",
"entity": "face",
"filter": { "surfaceType": "cylinder" }
}
// example result
[
{ "id": "face[6]", "surfaceType": "cylinder", "area": 251.3, "centroid": [15.0, 20.0, 5.0] },
{ "id": "face[7]", "surfaceType": "cylinder", "area": 251.3, "centroid": [45.0, 20.0, 5.0] }
]
The returned IDs (face[N], edge[N], vertex[N]) are stable across calls on the same BREP and can be passed directly to select_topology (Swift only) to mint a selectionId for remap and annotation workflows.
4. Recognize features
Detect pockets and holes via OCCTSwift’s Attributed Adjacency Graph (AAG) heuristics.
See recognize_features.
// tool call arguments
{ "bodyId": "part", "kinds": ["pocket", "hole"] }
// example result
{
"features": [
{ "kind": "hole", "faces": ["face[6]"], "diameter": 8.0, "depth": 10.0 },
{ "kind": "hole", "faces": ["face[7]"], "diameter": 8.0, "depth": 10.0 }
]
}
The face IDs in each feature’s faces array correspond directly to the IDs returned by query_topology, so you can cross-reference feature membership with surface type or area.
For the full graph-level pipeline — a labelled TopologyGraph written for downstream reconstruction — see feature_recognize in the Topology graph family.
What next?
- Measure minimum clearance between two bodies or certify surface deviation against a reference mesh → Measurement & verification
- Pick specific faces or edges as stable
selectionIds and carry them through a mutation → Selection & remap (Swift only) - Repair an invalid or imported body before inspecting → Healing