← Technical articles

Article

BRepGraph in OCCT 8.0

A developer guide to BRepGraph topology storage, stable identity, explicit edge uses, assembly traversal, cache-aware editing, mesh data, and graph-native algorithms.

CascadeScope graph view showing a product, occurrence, solid, shell, faces, wires, coedges, edges, and vertices

OCCT 8.0 introduces BRepGraph, a graph layer for B-Rep storage, edits, cache checks, and assembly traversal. Each graph stores topology definitions, parent-owned references, owner-scoped geometry and mesh records, persistent layers, and runtime caches.

BRepGraph is built to answer common modeling questions directly:

  • Which faces use this edge?
  • Which wire owns this coedge-like edge use?
  • Which PCurve belongs to this edge on this face?
  • Which product occurrence gives this topology its current placement?
  • Which cached result is stale after this edit?

Shapes can be imported through aGraph.Shapes().Add(const TopoDS_Shape&, ...) and rebuilt through aGraph.Shapes().Shape(node). These APIs provide BRepGraph entry points for OCCT shape exchange.

Architecture

Architectural map

Architecture has six main parts:

PartWhat It OwnsStability
DefinitionsTopology, products, occurrences, generation counters, stable node UID counters.NodeId is graph-local; UID is stable.
ReferencesParent-owned use records such as face-in-shell, wire-in-face, vertex-in-edge, child-in-compound, occurrence-in-product.RefId is graph-local; RefUID is stable.
Path instancesDefId + Location + Orientation values produced by traversal and tool APIs.Short-lived, path-specific.
Geometry and mesh recordsOwner-scoped geometry and persistent mesh records addressed by local RepIds.Local to each graph and owner.
LayersPersistent graph services and metadata that move through CopyTo(...).Layer-defined, usually keyed by node/ref/item identity.
CachesRuntime services for data that can be rebuilt, such as derived state and display mesh.Runtime-only, checked for freshness, copied only when requested.

Each part has a clear owner. Definitions own topology state. References own parent-child use entries. Instances carry traversal path state. Geometry and mesh records belong to their owning topology item. Layers store persistent metadata. Caches store runtime data that can be rebuilt.

Topology definitions are stored as flat, per-kind vectors:

  • VertexDef
  • EdgeDef
  • CoEdgeDef
  • WireDef
  • FaceDef
  • ShellDef
  • SolidDef
  • CompoundDef
  • CompSolidDef
  • ProductDef
  • OccurrenceDef

Topology links are stored separately:

  • Reference records such as FaceRef, WireRef, ShellRef, SolidRef, ChildRef, and OccurrenceRef.
  • Relation tables such as FaceRelations::WireRefIds, WireRelations::CoEdgeIds, EdgeRelations::CoEdgeIds, and VertexRelations::EdgeIds.

Definitions describe graph nodes. Reference records describe parent-owned uses of child definitions, including orientation and, where a use path has placement, location. Relation tables store ids of those refs or coedges so traversal can move without rebuilding adjacency containers.

BRepGraph definition nodes, parent-owned references, and relation storage

An edge reverse relation stores coedges. Face and wire queries go through those coedges. This keeps edge models small and makes edge-face bindings direct.

TopoView exposes stored definitions, const relation containers, and basic *Of relation getters. It does not materialize higher-level query results such as shared-edge or adjacent-face vectors. Use iterators and explorers for traversal:

for (BRepGraph_DefsEdgeOfFace anEdgeIt(aGraph, theFace); anEdgeIt.More(); anEdgeIt.Next())
{
  const BRepGraph_EdgeId anEdge = anEdgeIt.CurrentId();
  for (BRepGraph_FacesOfEdge aFaceIt = aGraph.Topo().Edges().FacesOf(anEdge);
       aFaceIt.More();
       aFaceIt.Next())
  {
    const BRepGraph_FaceId anAdjacentFace = aFaceIt.CurrentId();
  }
}

Topo().Edges().WiresOf(edge) and Topo().Edges().FacesOf(edge) are lightweight iterator factories over a stored edge-to-coedge relation. They derive parent wire and face ids from coedge definitions and skip removed entries without allocating result vectors.

2. Identity is explicit

BRepGraph has several identity levels:

  • NodeId: graph-local (Kind, Index) address into a definition vector. It is fast and compact. Compaction may remap it.
  • UID: stable node identity (Kind, Counter). Counter 0 is invalid; valid counters increase per kind. UIDs survive removal and compaction.
  • RefId: graph-local (Kind, Index) address into a reference-entry vector. Its locality and remap rules match NodeId.
  • RefUID: stable reference identity (Kind, Counter).
  • ItemId / ItemUID: generic wrappers over nodes and refs. They cover definition nodes and reference entries.
  • RepId: graph-local id for owner-scoped geometry or mesh use records. Its topology owner provides freshness.

BRepGraph graph-local and stable identity model

Stable identity API lives on aGraph.UIDs():

const BRepGraph_UID aUid = aGraph.UIDs().Of(theEdge);
const BRepGraph_NodeId aNode = aGraph.UIDs().NodeIdFrom(aUid);

const BRepGraph_RefUID aRefUid = aGraph.UIDs().Of(theWireRef);
const BRepGraph_RefId aRef = aGraph.UIDs().RefIdFrom(aRefUid);

BRepGraph_VersionStamp is a freshness stamp. For nodes and refs it combines stable identity with OwnGen and graph generation. For RepId, it resolves an owning node and stamps that owner.

Clear() starts a new graph generation and clears graph content. UID counters in storage keep increasing, so stale external references remain separate from ids created after rebuild.

3. Geometry and mesh records are owner-scoped

BRepGraph stores geometry and mesh data as owner-scoped use records:

  • EdgeCurve3DRep: owned by one edge and stores its 3D curve plus parameter range.
  • EdgePolygon3DRep: owned by one edge.
  • CoEdgeCurve2DRep: owned by one coedge and stores its PCurve plus parameter range.
  • CoEdgePolygon2DRep: owned by one coedge.
  • CoEdgePolygonOnTriRep: owned by one coedge.
  • FaceSurfaceRep: owned by one face.
  • FaceTriangulationRep: owned by one face.

A definition node stores its owned use-record id. Each use record stores a parent id and geometry handle. This id is a local RepId into one use-record vector.

Algorithms can still merge equal geometry handles by scanning graph data.

BRepGraph_Tool is a primary read entry point for these records. Raw id-based queries return geometry in a definition frame. Usage-based queries accept BRepGraphInc::Instance<T> values and apply location and orientation carried by that use path.

4. PCurves belong to coedges

An edge-face use is explicit through CoEdgeDef. A coedge stores:

  • ParentWireId
  • ChildEdgeId
  • FaceId
  • parity orientation relative to its child edge
  • owned 2D curve and polygon use ids

Wires contain ordered CoEdgeId lists through WireRelations::CoEdgeIds.

Coedge-owned two-dimensional geometry and its edge and face relations

Direct access looks like this:

const BRepGraph_CoEdgeId aCoEdge =
  BRepGraph_Tool::Edge::FindCoEdgeId(aGraph, theEdge, theFace);

if (aCoEdge.IsValid())
{
  const occ::handle<Geom2d_Curve> aPCurve =
    aGraph.Topo().CoEdges().Curve2D(aCoEdge);
}

FindCoEdgeId(...), FindPCurveCoEdgeId(...), and seam-pair lookup live in BRepGraph_Tool::Edge / BRepGraph_Tool::CoEdge. They are semantic lookup helpers rather than raw topology field accessors, and they iterate existing coedge relations without building temporary containers.

For seam edges, this tool finds a paired coedge by looking for another coedge with matching edge and face ids but opposite parity orientation.

Core orientation is parity-only: TopAbs_FORWARD or TopAbs_REVERSED. Supplemental orientation data such as TopAbs_INTERNAL and TopAbs_EXTERNAL is stored by BRepGraph_LayerTopoSupplement for shape reconstruction.

5. Mutation is scoped and cache-aware

BRepGraph mutation goes through aGraph.Editor().

Field edits use BRepGraph_MutGuard<T>, a move-only guard for one item. It blocks nested edits to that item, marks it dirty when setters change it, and notifies its graph when destroyed.

{
  BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
    aGraph.Editor().Edges().Mut(theEdge);

  aGraph.Editor().Edges().SetTolerance(aMut, 0.01);
  aGraph.Editor().Edges().SetParamRange(aMut, 0.0, 42.0);
}

On immediate node mutation, BRepGraph:

  1. Increments node OwnGen.
  2. Increments node SubtreeGen.
  3. Sends node change events to subscribed layers.
  4. Propagates SubtreeGen upward through relation tables.
  5. Marks dependent rebuilt shapes and runtime cache entries stale through freshness checks.

BRepGraph_DeferredScope batches invalidation for larger edit loops. Edits still commit normally, and thread locking is handled outside this scope. Nested scopes are allowed; only an outermost scope flushes deferred invalidation and commits its mutation batch.

#include <BRepGraph_DeferredScope.hxx>

{
  BRepGraph_DeferredScope aScope(aGraph);

  for (BRepGraph_EdgeIterator anIt(aGraph); anIt.More(); anIt.Next())
  {
    auto aMut = aGraph.Editor().Edges().Mut(anIt.CurrentId());
    aGraph.Editor().Edges().SetTolerance(aMut, 0.01);
  }
}

Freshness uses these fields:

StateMeaning
UIDStable node identity.
RefUIDStable reference identity.
OwnGenChanged when an item itself changes.
SubtreeGenChanged when an item or something below it changes.
LastPropWaveInternal revisit guard for upward propagation.
Graph generationRebuild/clear freshness marker.

Derived booleans such as edge degeneracy, same-parameter, same-range, wire closedness, and shell closedness are computed on demand and backed by cache services.

BRepGraph_CacheDerivedState stores those derived edge, wire, and shell properties. Its getters compute missing values and return fresh results, so callers can read each property directly.

6. Assembly structure is built in

BRepGraph has first-class assembly nodes:

  • ProductDef: reusable part or assembly definition.
  • OccurrenceDef: use of a child topology root or child product.
  • OccurrenceRef: parent product, child occurrence, and local placement.

Products carry no placement. Occurrence references carry placement. Compound child references can also carry TopLoc_Location, so topology reached through a compound path can be located. Traversal APIs return BRepGraphInc::Instance<T> values: a definition id plus location and orientation for that path.

Storage and use paths are separate. A FaceDef or EdgeDef is a reusable node record. A face or edge reached through BRepGraph_ChildExplorer, BRepGraph_ParentExplorer, or a compound/product path is a path-specific instance with composed placement and orientation.

BRepGraph product and occurrence assembly structure

Shapes().Add(shape) creates an automatic product wrapper by default for an unparented add. Lower-level editor APIs are direct: Products().Add(...) creates product structure, and document roots are managed through a root-product list.

Traversal is product/occurrence aware. BRepGraph_ChildExplorer and BRepGraph_ParentExplorer understand nested product/occurrence chains and can walk from an assembly root down to topology descendants, or from a topology node back up to assembly context.

Entity model

Core definition records contain identity, mutation generation, topology-specific fields, and ids for owned geometry or mesh records:

Core BRepGraph definition record hierarchy

Reference entries are separate:

  • ShellRef: solid to shell, with parity orientation.
  • FaceRef: shell to face, with parity orientation.
  • WireRef: face to wire, with parity orientation.
  • VertexRef: edge to vertex, with parity orientation.
  • SolidRef: compsolid to solid, with parity orientation.
  • ChildRef: compound to mixed child node, with parity orientation and local location.
  • OccurrenceRef: product to occurrence, with local location.

Traversal exposes path-specific topology through BRepGraphInc::Instance<T> (DefId, Location, Orientation). This is a graph-native counterpart to a located and oriented TopoDS_Shape value.

Relation tables hold ordered children and reverse links:

  • Face to wire refs.
  • Wire to ordered coedges.
  • Edge to coedges using that edge.
  • Vertex to edges sharing that vertex.
  • Shell to face refs.
  • Solid to shell refs.
  • Compound to child refs.
  • CompSolid to solid refs.
  • Product to occurrence refs.
  • Occurrence to parent occurrence refs.

Build pipeline

Public ingestion API is BRepGraph::ShapesView.

BRepGraph aGraph;

BRepGraph::ShapesView::Options anOptions;
anOptions.CreateAutoProduct = true;
anOptions.Parallel = true;

const BRepGraph::ShapesView::Result aResult =
  aGraph.Shapes().Add(theShape, anOptions);

if (!aResult.IsOk())
{
  // Handle failed import.
}

Builder pipeline performs these steps:

  1. Traverse hierarchy and collect contexts.
  2. Extract face-local geometry, optionally in parallel.
  3. Register definitions, references, owner-scoped geometry uses, relations, and original-shape bindings.
  4. Allocate node and ref UIDs.
  5. Optionally wrap a topology root in an automatic product or occurrence.
  6. Rebuild relation and UID reverse indexes as needed.

ShapesView::Options also supports Flatten and TrackAddedNodes. History-aware ingestion is exposed through AddWithHistory(...), which imports an OCCT algorithm result and absorbs BRepTools_History into a graph history layer.

Shape reconstruction happens through aGraph.Shapes().Shape(node). ShapesView caches rebuilt shapes and marks them stale through generation and freshness state after mutations.

API

BRepGraph exposes grouped views:

ViewAccessorPurpose
TopoViewTopo()Read definitions, const relation storage, basic *Of relation iterators, owner-scoped use-record access, counts, products, and occurrences.
UIDsViewUIDs()Stable node/ref/item identity, reverse lookup, graph GUID, generation, and version stamps.
RefsViewRefs()Reference-entry storage and parent-owned IdsOf(...) ref lists.
ShapesViewShapes()TopoDS_Shape ingestion, reconstruction, original-shape lookup, and history ingestion.
EditorViewEditor()Construction, structural edits, field mutation, removal, supplement editing, and deferred invalidation.
MeshViewMesh()Persistent, runtime-cache, and effective mesh access.
LayerRegistryLayerRegistry()Persistent metadata/services with lifecycle callbacks.
CacheRegistryCacheRegistry()Runtime graph-local cache services.

Generic definition/ref queries are grouped under Gen():

if (aGraph.Topo().Gen().IsActive(theNode))
{
  const BRepGraphInc::BaseDef* aDef =
    aGraph.Topo().Gen().TopoEntity(theNode);
}

if (aGraph.Refs().Gen().IsActive(theRef))
{
  const BRepGraph_NodeId aChild =
    aGraph.Refs().Gen().ChildNode(theRef);
}

Refs().Gen().RefAtStep(parent, step) is a structural lookup over stored parent-owned reference arrays. It does not replace traversal; use typed iterators or explorers for query requests.

Geometry access is available through typed topology/tool APIs:

const gp_Pnt aPoint =
  BRepGraph_Tool::Vertex::Pnt(aGraph, theVertex);

const occ::handle<Geom_Curve> aCurve =
  BRepGraph_Tool::Edge::Curve(aGraph, theEdge);

const occ::handle<Geom2d_Curve> aPCurve =
  BRepGraph_Tool::CoEdge::PCurve(aGraph , theCoEdge);

const occ::handle<Geom_Surface> aSurface =
  BRepGraph_Tool::Face::Surface(aGraph, theFace);

When you already have a located and oriented usage from traversal, use usage-aware overloads:

const BRepGraphInc::FaceInstance aFaceUsage = anExplorer.Current();
const GeomAdaptor_TransformedSurface aSurf =
  BRepGraph_Tool::Face::SurfaceAdaptor(aGraph, aFaceUsage);

Mutation goes through a graph editor:

const BRepGraph_VertexId aV1 =
  aGraph.Editor().Vertices().Add(gp_Pnt(0.0, 0.0, 0.0), 1.0e-7);

const BRepGraph_VertexId aV2 =
  aGraph.Editor().Vertices().Add(gp_Pnt(10.0, 0.0, 0.0), 1.0e-7);

const BRepGraph_EdgeId anEdge =
  aGraph.Editor().Edges().Add(aV1, aV2, aCurve, 0.0, 10.0, 1.0e-7);

Traversal in practice

BRepGraph has several traversal families. Pick one matching your question. Flat iterators return definition ids. Recursive explorers return path-specific instances with accumulated location and orientation.

Flat per-kind scan.

#include <BRepGraph_Iterator.hxx>

uint32_t countEdges(const BRepGraph& theGraph)
{
  uint32_t aCount = 0;
  for (BRepGraph_EdgeIterator anIt(theGraph); anIt.More(); anIt.Next())
  {
    ++aCount;
  }
  return aCount;
}

Flat iterators skip removed nodes and are good for per-kind passes.

Single-level children with refs.

#include <BRepGraph_DefsIterator.hxx>
#include <BRepGraph_RefsIterator.hxx>

for (BRepGraph_DefsWireOfFace anIt(theGraph, theFace); anIt.More(); anIt.Next())
{
  const BRepGraph_WireId aWire = anIt.CurrentId();
}

for (BRepGraph_RefsWireOfFace anIt(theGraph, theFace); anIt.More(); anIt.Next())
{
  const BRepGraph_WireRefId aWireRef = anIt.CurrentId();
  const BRepGraphInc::WireRef& aRef = theGraph.Refs().Wires().Entry(aWireRef);
  const BRepGraph_WireId aWire = aRef.ChildWireId;
  const BRepGraphInc::ParityOrientation anOri = aRef.Orientation;
}

Ordered wire traversal.

for (BRepGraph_DefsCoEdgeOfWire anIt(theGraph, theWire); anIt.More(); anIt.Next())
{
  const BRepGraph_CoEdgeId aCoEdge = anIt.CurrentId();
  const BRepGraphInc::CoEdgeDef& aDef =
    theGraph.Topo().CoEdges().Definition(aCoEdge);
  const BRepGraph_EdgeId anEdge = aDef.ChildEdgeId;
}

Coedges are ordered wire members. An edge relation stores all coedges using an edge, so edge-to-face and edge-to-wire questions are answered through coedges.

Recursive descent and ascent.

#include <BRepGraph_ChildExplorer.hxx>
#include <BRepGraph_ParentExplorer.hxx>

for (BRepGraph_ChildExplorer anExp(theGraph,
                                   theProduct,
                                   BRepGraph_NodeId::Kind::Edge);
     anExp.More();
     anExp.Next())
{
  const BRepGraphInc::NodeInstance anEdgeInstance = anExp.Current();
  const BRepGraph_NodeId anEdgeNode = anEdgeInstance.DefId;
  const TopLoc_Location aLoc = anEdgeInstance.Location;
}

for (BRepGraph_ParentExplorer anExp(theGraph,
                                    theEdge,
                                    BRepGraph_NodeId::Kind::Face);
     anExp.More();
     anExp.Next())
{
  const BRepGraph_FaceId aFace =
    BRepGraph_FaceId::FromNodeId(anExp.Current().DefId);
}

BRepGraph_RelatedIterator handles neighbor queries such as adjacent faces, boundary edges, and incident vertices without doing a full recursive traversal.

Mesh architecture

Mesh data has two storage paths: persistent mesh records and runtime mesh cache.

Persistent mesh belongs to a B-Rep model:

  • FaceTriangulationRep is owned by a face.
  • EdgePolygon3DRep is owned by an edge.
  • CoEdgePolygon2DRep is owned by a coedge.
  • CoEdgePolygonOnTriRep is owned by a coedge.

Persistent mesh is read through aGraph.Mesh().Persistent() and written through topology editor operations such as Editor().Faces().SetPersistentTriangulation(...), Editor().Edges().SetPersistentPolygon3D(...), and Editor().CoEdges().SetPersistentPolygon2D(...). It follows configured graph-copy mesh policy. Use it for imported mesh, user-created mesh, and cached mesh moved into a B-Rep model.

Runtime mesh cache lives in BRepGraph_CacheMesh, registered through CacheRegistry(). Use it for display mesh or algorithm-generated mesh that can be rebuilt. It has slots, drivers, recipe hashes, slot generations, and per-entry freshness stamps.

MeshView keeps these paths visible:

Mesh ViewMeaning
Mesh().Cache()Reads fresh runtime cache entries only.
Mesh().Persistent()Reads definition-owned persistent mesh use records only.
Mesh().Effective()Reads an active cache slot first, then falls back to persistent mesh.
Mesh().Editor()Mutates runtime cache entries; PromoteToPersistent() copies fresh default-slot cache entries into persistent reps.
Mesh().Poly()Counts persistent polygon/triangulation use-record slots and active entries.

Use Mesh().Effective() for rendering and general mesh queries. Use cache and persistent views when callers need to know where data came from.

BRepGraph_CacheMesh::Ensure(...) asks a registered driver for a slot to rebuild missing or stale data. Needs(...) checks identical freshness rules without running that driver. Face cache entries bind to face subtree generation and slot recipe state. Edge entries bind to edge generation and slot recipe state. Coedge entries have separate checks: coedge topology for polygon-on-surface data, face topology for polygon-on-triangulation data, and face mesh generation for cached polygon-on-triangulation content.

Clearing a cached face triangulation leaves polygon-on-surface data valid. Polygon-on-triangulation becomes stale after face mesh generation changes.

Runtime mesh cache is copied only when requested. BRepGraph_Copy and BRepGraph_Compact copy fresh runtime cache entries that can be remapped when callers choose CachePolicy::CopyFresh. With default cache policy, cache entries are dropped or cleared while persistent mesh follows configured mesh policy.

Graph algorithms in OCCT 8.0

Graph-native algorithms include:

AlgorithmClassWhat it does
CopyBRepGraph_CopyCopies a whole graph or rooted subgraph into a target graph. Runtime caches are dropped by default. Fresh caches that can be remapped can be copied with CachePolicy::CopyFresh.
TransformBRepGraph_TransformApplies transformations either by transforming geometry or by using occurrence/root placement policy, depending on options.
CompactBRepGraph_CompactRebuilds dense active storage, remaps graph-local ids, preserves node/ref UIDs, and can optionally copy fresh runtime caches.
DeduplicateBRepGraph_DeduplicateMerges equal geometry/topology according to its options.
ValidateBRepGraph_ValidateChecks graph structure, relation symmetry, UID lookup, removed-node isolation, wire connectivity, and assembly consistency depending on validation mode.

BRepGraph also provides a base for graph-native healing, sewing, same-parameter, and data-exchange work. Those higher-level tools should be described by their APIs as they land.

Extensibility

BRepGraph has two extension mechanisms with different storage rules.

Layers are persistent graph services. A BRepGraph_Layer stores metadata keyed by nodes, refs, or item UIDs, subscribes to mutation events, and implements CopyTo(const BRepGraph_CopyRemap&) so its data can move during copy and compaction.

Useful layer examples include:

Caches are runtime graph-local services. A BRepGraph_Cache stores data that can be rebuilt, such as derived topology state, display mesh, bounds, UV bounds, or algorithm results. Cache entries are checked against OwnGen, SubtreeGen, ref freshness, item freshness, and cache-specific state such as mesh slot recipe/generation.

Each cache service decides how fresh data is copied through CopyFreshTo(...). BRepGraph_Copy and BRepGraph_Compact preserve fresh runtime cache data when callers select CachePolicy::CopyFresh.

BRepGraph_CacheMesh provides a mesh runtime cache. Persistent face, coedge, and edge mesh use records are exposed through Mesh().Persistent() and Mesh().Effective().

Use this split:

  • Data that moves with graph identity belongs in a layer.
  • Data that can be rebuilt from graph state belongs in a cache.
  • Geometry and mesh belonging to a B-Rep model belong in owner-scoped use records.

Performance

BRepGraph performance comes from structure:

  • Dense per-kind vectors for topology definitions.
  • Relation tables for common adjacency questions.
  • Owner-scoped coedges for direct edge-face PCurve lookup.
  • One allocator-backed storage per graph.
  • Mutation generation counters for lazy cache freshness.
  • Deferred invalidation for batch edit loops.
  • Separate persistent and runtime mesh paths, so display mesh can be rebuilt without rewriting B-Rep model data.
  • Product/occurrence traversal without going through XCAF labels first.

Keep query paths allocation-free where possible. TopoView should expose stored fields, const relation containers, counts, and lightweight iterator factories. Semantic queries belong in BRepGraph_Tool, and traversal queries should use iterators or explorers instead of returning freshly built containers.

When a loop repeatedly checks ids, cache a relevant Nb() once and use its typed IsValid(nb) check inside that loop. Use uint32_t for graph counts and stored id/count values; use size_t only for local container indexes or APIs that require it. For temporary id/UID sets, prefer NCollection_FlatMap / NCollection_FlatDataMap; keep allocator-backed NCollection_Map only where this allocator behavior is intentional.

Performance numbers depend on a model, build options, and measured algorithm. Benchmark numbers should name each test, hardware, build type, and branch.

Getting started

A minimal example:

#include <BRepGraph.hxx>
#include <BRepGraph_Iterator.hxx>
#include <BRepGraph_ShapesView.hxx>
#include <BRepGraph_Tool.hxx>
#include <BRepPrimAPI_MakeBox.hxx>

BRepGraph aGraph;

BRepGraph::ShapesView::Options anOptions;
anOptions.CreateAutoProduct = true;
anOptions.Parallel = true;

const BRepGraph::ShapesView::Result aResult =
  aGraph.Shapes().Add(BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape(), anOptions);

if (!aResult.IsOk())
{
  return 1;
}

const uint32_t aNbFaces =
  aGraph.Topo().Faces().NbActive();

for (BRepGraph_FaceIterator anIt(aGraph); anIt.More(); anIt.Next())
{
  const occ::handle<Geom_Surface> aSurface =
    BRepGraph_Tool::Face::Surface(aGraph, anIt.CurrentId());
}

const TopoDS_Shape aFaceShape =
  aGraph.Shapes().Shape(BRepGraph_FaceId::Start());

For adjacency:

#include <BRepGraph_ReverseIterator.hxx>

const BRepGraph_EdgeId anEdge = BRepGraph_EdgeId::Start();
const uint32_t aFaceUseCount = aGraph.Topo().Edges().NbFaces(anEdge);

for (BRepGraph_FacesOfEdge aFaceIt = aGraph.Topo().Edges().FacesOf(anEdge);
     aFaceIt.More();
     aFaceIt.Next())
{
  const BRepGraph_FaceId aFace = aFaceIt.CurrentId();
}

For stable identity:

const BRepGraph_UID aUid = aGraph.UIDs().Of(BRepGraph_EdgeId::Start());
const BRepGraph_NodeId aBack = aGraph.UIDs().NodeIdFrom(aUid);

For reconstruction:

const TopoDS_Shape aShape = aGraph.Shapes().Shape(aResult.TopologyRoot);

Visualizing a graph

Raw graph storage is hard to read by hand. CascadeScope can load CAD data, build a graph, and show geometry next to graph nodes, references, layers, and selection context. It provides a direct way to inspect how products, occurrences, topology nodes, coedges, and relation tables appear in real models.

Status and scope

BRepGraph was introduced in OCCT 8.0 and continues to evolve. Its graph model includes:

  • definition nodes plus separate reference entries,
  • CoEdgeDef as an edge-face use node,
  • owner-scoped geometry and mesh use records,
  • stable node/ref/item UID identity,
  • mutation generation and cache freshness,
  • layers for persistent metadata,
  • runtime cache services for data that can be rebuilt,
  • product/occurrence assembly traversal.

These examples cover OCCT 8.0-era API. Check current BRepGraph reference and headers shipped with your exact OCCT version.

Technical discussion

Need to evaluate this for an application?

Use technical support for a bounded question or custom development for implementation and integration work.