CAD Exchanger SDK
B-Rep Topology


Topological entities are used to define trimming of the geometrical entities (see B-Rep Geometry) and connectivity between the entities.

Topological entities are eventually owned by the body (ModelData_Body) and are added to B-Rep representation (ModelData_BRepRepresentation). For the list of supported body types refer to Body types.

Some topological entities refer to geometrical entities (e.g. edge refers to curve and face refers to surface), whereas some only refer to child topological entities (e.g. wires refers to edges it consists of).

Shape types

All topological entities subclass the ModelData_Shape class.

CAD Exchanger API follows the ISO 10303-42 specification and supports the shape types defined below. The shape type is returned returned by ModelData_Shape::Type() as ModelData_ShapeType enumeration.

The shape can be casted to a particular subclass type using the respective Cast() method defined in the subclass, for instance:

ModelData_Shape aShape = ...;
if (aShape.Type() == ModelData_ST_Vertex) {
const ModelData_Vertex& aVertex = ModelData_Vertex::Cast (aShape);
Type C++ class Example
Vertex ModelData_Vertex
Edge ModelData_Edge
Wire ModelData_Wire
Face ModelData_Face
Shell ModelData_Shell
Solid ModelData_Solid


Each shape can have either forward or reversed orientation as returned by the Orientation() method. Meaning of orientation depends on the shape type:

  • For vertex, orientation has a meaning only in context of a parent edge where forward vertex corresponds to smaller parameter on the edge curve and reversed vertex to greater parameter.
  • For edge, orientation specifies whether edge direction is aligned or is opposite to underlying curve orientation.
  • For face, orientation specifies whether face normal is aligned or is opposite to underlying surface normal.
  • For wire, shell, solid, or body, orientation simply specifies whether subshapes should be considered with their own or opposite orientations. For instance, a reversed wire would be similar to a forward wire consisting of original edges taken with opposite orientations.
  • For body list, orientation does not apply.

A shape with the opposite orientation can be returned with the Reversed() method. A shape with a specified orientation can be returned with the Oriented() method. Both methods create a shallow copy of the original shape, which shares a subshape graph but has a distinct orientation flag.

Equality and similarity relationships

Two shapes are considered equal if they share the same definition (i.e. geometry and subshape graph) and have equal orientations. The method IsEqual() and operator==() can be used to check equality.

Two shapes are considered equal if they share the same definition (i.e. geometry and subshape graph). Orientations are not required to be equal. The method IsSame() can be used to check this relationship. Obviously, the 'IsSame' relationship is less strict than 'IsEqual'.

The following code snippet demonstrates both relationships:

ModelData_Shape aShape1 = ...;
//shapes with equal orientations are IsSame() and are equal
ModelData_Shape aShape2 = aShape1;
assert (aShape2 == aShape1);
assert (aShape2.IsSame (aShape1));
//shapes with opposite orientations are IsSame() but are not equal
ModelData_Shape aShape3 = aShape1.Reversed();
assert (aShape3.IsSame (aShape1));
assert (aShape3 != aShape1);

For example, a closed shell contains pairs of IsSame() edges but with opposite orientations.


Exploration of direct children

To retrive direct children of a shape, ModelData_Shape::Iterator should be used as follows:

ModelData_Wire aWire = ...;
ModelData_Shape::Iterator i (aWire);
while (i.HasNext()) {
const ModelData_Shape& aChild = i.Next(); //edge
ModelData_Type aType = aChild.Type();
assert (aType == ModelData_ST_Edge);

Exploration of particular types

To retrive children of a particular type, ModelData_Shape::Iterator should be used by specifying a type of interest as follows:

ModelData_Solid aSolid = ...;
ModelData_Shape::Iterator i (aWire, ModelData_ST_Edge); //iterate over edges in the solid
while (i.HasNext()) {
const ModelData_Edge& aChild = ModelData_Edge::Cast (i.Next()); //edge

When using the latter approach exploration is done traversing the graph of subshapes in a depth-first manner. Each subshape will be found as many times as it is registered in the parent subshape. For instance, a seam-edge will be encountered twice, with forward and reversed orientations.

The order of returned subshapes is deterministic and corresponds to the order in which the subshapes were added during construction.

Resulting orientation

Orientation of a returned subshape is product of own subshape orientation (stored inside a subshape) and of its parent. Thus, if the subshape and its parent both have the same orientation then the returned subshape will have forward orientation, if they have opposite orientations then the returned subshape will have reversed orientation.

When exploring nested subshapes the same rule applies at each level of the hierarchy:

Resulting_orientation = parent_orientation * subshape_orientation * subsubshape_orientation * ...

For instance, when exploring a forward face, which has a wire with reversed orientation, with an edge having forward orientation, exploring that edge will return an edge with reversed orientation.

Storing shapes in associative containers

Shapes can be stored in associative containers (such as std::unordered_map or std::unordered_set) as keys. Hash and equality functors required for such containers can be selected depending on desired behavior, whether the container must ensure uniquness defined in terms of equality or similarity relationships:

Refer to Equality and similarity relationships for relationship definitions.

The following code snippet demonstrates usage of both approaches:

typedef std::unordered_map<ModelData_Shape,
ModelData_OrientedShapeEqual> OrientedShapeMap;
typedef std::unordered_set<ModelData_Shape,
ModelData_UnorientedShapeEqual> UnorientedShapeSet;
/* Returns true if the shell is open, i.e. has edges belonging to single face only.*/
static bool HasFreeBoundaries (const ModelData_Shell& theShell)
UnorientedShapeSet aSet;
ModelData_Shape::Iterator i (theShell, ModelData_ST_Edge);
while (i.HasNext()) {
const auto& aShape = i.Next();
auto r = aSet.insert (aShape);
if (!r.second) { //if the same edge was already encountered then remove it
aSet.erase (r.first);
return !aSet.empty();


Refer to Model Explorer.