Link Search Menu Expand Document

Topology graph

The typical pipeline for a BREP you have just exported or received from an importer: validate its topology, compact it, dedup shared geometry, then query or export it for downstream analysis or ML training.

All six commands operate on an absolute BREP file path or, in the case of graph-query, on a BREPGraph SQLite file. Full parameter tables are in the Topology graph reference.


1. Validate — topology health record

graph-validate checks the shape without touching the file.

occtkit graph-validate bracket.brep
{
  "isValid": true,
  "errorCount": 0,
  "warningCount": 2,
  "healthRecord": {
    "isValid": true,
    "shapeType": "solid",
    "freeEdgeCount": 0,
    "nakedVertexCount": 0,
    "smallEdgeCount": 1,
    "smallFaceCount": 0,
    "selfIntersecting": false,
    "errors": []
  }
}

If isValid is false, examine the healthRecord.errors list. A shape with topology errors can still be loaded for measurement but compact and dedup on an invalid shape may produce further corruption — fix or heal before proceeding.


2. Compact — drop unreferenced nodes

graph-compact rebuilds the shape and removes nodes that nothing references — common after Boolean operations and healing. Pass a distinct output path to preserve the original.

occtkit graph-compact bracket.brep bracket_compact.brep
{
  "nodesBefore": 42,
  "nodesAfter": 38,
  "removed": {
    "vertices": 0,
    "edges": 2,
    "faces": 1
  },
  "output": "bracket_compact.brep"
}

3. Dedup — merge shared surface/curve geometry

graph-dedup detects geometrically identical surfaces and curves and merges them into single graph nodes. This reduces file size and produces a cleaner attributed adjacency graph (gAAG) for feature recognition and ML export.

occtkit graph-dedup bracket_compact.brep bracket_clean.brep
{
  "canonicalSurfaces": 8,
  "canonicalCurves": 12,
  "surfaceRewrites": 3,
  "curveRewrites": 5,
  "output": "bracket_clean.brep"
}

The three steps above chain naturally: validate → compact → dedup gives you a clean BREP ready for query or ML export.


4. Query a BREPGraph SQLite database

graph-query reads a BREPGraph SQLite file — produced by ScriptContext.addGraph(..., sqlite: true) inside a script — and emits a topology summary.

occtkit graph-query graph-0.sqlite
{
  "summary": {
    "solids": 1,
    "shells": 1,
    "faces": 6,
    "wires": 6,
    "edges": 12,
    "vertices": 8,
    "coedges": 24,
    "boundaryEdges": 0,
    "nonManifoldEdges": 0,
    "degenerateEdges": 0,
    "openShells": 0
  },
  "counts": {
    "freeEdges": 0,
    "openWires": 0,
    "facesWithHoles": 0
  },
  "valence": {
    "face":   { "max": 4, "mean": 3.5, "count": 8 },
    "vertex": { "max": 3, "mean": 3.0, "count": 8 }
  }
}

This command requires a SQLite file; it does not accept a BREP path directly.


5. ML export — full graph with UV and edge samples

graph-ml exports the full topology graph augmented with per-face UV grids (positions, normals, Gaussian and mean curvatures), per-edge curve samples, COO adjacency matrices, and an attributed face-adjacency block. Use --uv-samples and --edge-samples to tune sampling density (defaults: 16 and 32).

occtkit graph-ml bracket_clean.brep --uv-samples 12 --edge-samples 24
{
  "vertexPositions": [[0,0,0], [1,0,0]],
  "edgeBoundaryFlags": [false, false],
  "edgeManifoldFlags": [true, true],
  "faceAdjacentFaces": [[1,2], [0,3]],
  "faceToFace":   { "sources": [0,0,1], "targets": [1,2,0] },
  "faceToEdge":   { "sources": [0,0,1], "targets": [2,3,5] },
  "edgeToVertex": { "sources": [0,1,1], "targets": [0,1,2] },
  "faces": [
    {
      "index": 0, "uSamples": 12, "vSamples": 12,
      "positions": [[0,0,0]], "normals": [[0,0,1]],
      "gaussianCurvatures": [0.0], "meanCurvatures": [0.0]
    }
  ],
  "edges": [{ "index": 0, "samples": [[0,0,0],[0.1,0,0]] }],
  "faceAdjacency": [
    { "face1": 0, "face2": 1, "convexity": "convex",  "sharedEdgeCount": 1 },
    { "face1": 1, "face2": 3, "convexity": "concave", "sharedEdgeCount": 1 }
  ],
  "sampling": { "uvSamples": 12, "edgeSamples": 24 }
}

Face indices in faceAdjacency and faceAdjacentFaces follow shape.faces() order — the same face[N] scheme query-topology emits. Convexity is a property of the dihedral angle between two faces: "convex" (outward-pointing), "concave" (inward), or "smooth" (near-zero).


6. Local adjacency selection

graph-select answers focused neighbourhood questions without dumping the full graph. The --query flag selects the mode.

--query required secondary flag returns
face-neighbors --face N adjacent faces + convexity + shared-edge count + face plane info
edge-faces --edge M face indices on both sides, start/end vertices, boundary/manifold flags
vertex-edges --vertex K edge indices incident to the vertex
face-adjacency full attributed gAAG (faceCount + all adjacencies)
edges-class --class <kind> matching edge indices; kind = boundary | non-manifold | seam | degenerate

Face neighbours with convexity:

occtkit graph-select bracket_clean.brep --query face-neighbors --face 2
{
  "query": "face-neighbors",
  "face": 2,
  "isPlanar": true,
  "isVertical": false,
  "isHorizontal": true,
  "normal": [0, 1, 0],
  "neighbors": [
    { "face": 0, "convexity": "convex",  "sharedEdgeCount": 1 },
    { "face": 3, "convexity": "concave", "sharedEdgeCount": 1 }
  ]
}

Find all boundary edges:

occtkit graph-select bracket_clean.brep --query edges-class --class boundary
{
  "query": "edges-class",
  "class": "boundary",
  "edges": [7, 11, 14]
}

Face indices follow shape.faces() order; edge and vertex indices are TopologyGraph indices.


Reference