Explore your shape using OPEN CASCADE

Explore your shape using OPEN CASCADE

In Open CASCADE, there are different APIs which can be used to explore your given shape. There are some other techniques which are the basics of exploring shapes. In this article, you will go through different techniques and APIs which I tried to explore the shapes. So, let’s start the journey.

Here in this article, we are looking for 6 APIs.

🖲️TopExp_Explorer
🖲️TopOpeBRepTool_ShapeExplorer
🖲️TopoDS_Iterator
🖲️TopTools_IndexedMapOfShape
🖲️TopTools_IndexedDataMapOfShapeListOfShape
🖲️ShapeAnalysis_ShapeContents

TopExp_Explorer

This is the most famous way to explore the shape. Probably you may hear of this API prior to this article 😀.

Here the shapes are explored from top to bottom hierarchy. Hence all the sub-shapes in the given shape will be counted through exploration.

Example: If you want to explore all the edges of a particular shape, you will define this as follows.

for (TopExp_Explorer exp(theShape, TopAbs_EDGE); exp.More(); exp.Next())
{
    const TopoDS_Edge& edge = TopoDS::Edge(exp.Current());
    // do calculation
}

Before exploring the edges of the shape, it will look at the “Face” level. Here it will explore face by face and explore the edges of each face. Because of that approach, common edges will be counted in multiple times.


Based on that, the edge count of the above box will be 24.

Probably you may not use the “ToAvoid” parameter in this API. The usage of this parameter is to avoid considering the shape type while exploring the shapes.

for (TopExp_Explorer exp(theShape, TopAbs_EDGE, TopAbs_FACE); exp.More(); exp.Next())
{
    const TopoDS_Edge& edge = TopoDS::Edge(exp.Current());
    // do calculation
}

In the above example, you will get all the edges which do not belong to faces. Which means free edges of the shape.

If you want to count the number of sub-shapes of the given type, you can simply define an integer outside the for loop and increment one by one during the exploration.

int a=0;
for (TopExp_Explorer exp(theShape, TopAbs_EDGE); exp.More(); exp.Next(), a++)
{
    const TopoDS_Edge& edge = TopoDS::Edge(exp.Current());
    // do calculation
}

TopOpeBRepTool_ShapeExplorer 

The next method is to use TopOpeBRepTool_ShapeExplorer instead of TopExp_Explorer and use the “Index” function inside that.

for (TopOpeBRepTool_ShapeExplorer exp(theShape, TopAbs_EDGE, TopAbs_FACE); exp.More(); exp.Next(), a++)
{
    int indexOfEdge = exp.Index();
    const TopoDS_Edge& edge = TopoDS::Edge(exp.Current());
    // do calculation
}


TopoDS_Iterator 

TopoDS_Iterator uses to explore the shape up to the immediate next shape type. For example, if you are exploring a face, using TopoDS_Iterator, you will get wires of that shape. If you are exploring a wire, you will get edges of that shape.


There are two other variables which we can define in this API. To iterate all the sub-shapes, you have to use a recursive function or any other form of use.

The “TopoDS_Iterator” can be used as same as “TopoDS_Explorer”. The example is as follows.

int a = 0;
TopoDS_Shape subShape;
for (TopoDS_Iterator itr(theShape); itr.More(); itr.Next(), a++)
{
    TopoDS_Shape subShape = itr.Value();
    // do calculation
}

TopTools_IndexedMapOfShape

If you want to map the sub-shapes with an index, you can simply use this API. Here the sub-shapes are mapped with an index.

TopTools_IndexedMapOfShape map;
TopExp::MapShapes(theShape, TopAbs_EDGE, map);
for (int count = 1; count <= map.Extent(); count++)
{
    // do calculation
}

Here the main advantage is each shape will count only once. If we explore a box using the “TopTools_IndexedMapOfShape” to get edges, you will get 12 edges.

TopTools_IndexedDataMapOfShapeListOfShape


When you need to get the shapes and sub-shape connection, you can use this method. For example, when you need to check what are the faces that are connected to each edge of a particular shape, you can use this API as follows. In this map, the key is an edge and the value is a list of faces.

You can follow the given example to extract data from the shape map and shape list.

// Create shape map
TopTools_IndexedDataMapOfShapeListOfShape shapeMap;
TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, shapeMap);

// Shape map iterator
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr;
for (itr.Initialize(shapeMap); itr.More(); itr.Next())
{
    const TopoDS_Shape& keyShape = itr.Key();     // key shape (Edge)
    TopAbs_ShapeEnum shapeType = keyShape.ShapeType();
    TopTools_ListOfShape shapeList = itr.Value(); // values (Faces)

    // Shape list iterator
    TopTools_ListIteratorOfListOfShape itrList;
    for (itrList.Initialize(shapeList); itrList.More(); itrList.Next())
    {
        shapeType = itrList.Value().ShapeType();
        const TopoDS_Shape& shape = itrList.Value(); // value (Face)
    }
}

ShapeAnalysis_ShapeContents

If you want to get only the shapes’ count, you can use this API directly. Here you can get different sub-shape counts as you want. Carefully select the parameters you want to get.


ShapeAnalysis_ShapeContents content;
content.Perform(theShape);
content.NbEdges(); // get number of edges


Select the parameter you want to get from the bellow list.


You may think why there are different methods to get edge count. Let me describe one sub-shape; edge.

NbEdges — This parameter will return the same number of edges which we can get from “TopExp_Explorer”. Here all the edges with duplication will return.

NbSharedEdges — This parameter will return the same number of edges which we can get from “TopTools_IndexedMapOfShape”. Here common edge count is omitted.

NbFreeEdges — This parameter will return the free edges in the given shape. Free edges mean edges that will not belong to any face or a wire.

NbFreeSharedEdges — Edges count, which is not belong to any face will return from this parameter. Both NbFreeEdges and NbFreeSharedEdges are the same.

What do we miss?

There are other shape counts we need to get from a given shape which do not include in the ShapeAnalysis_ShapeContents. Some of them are the number of non-manifold edges and the number of degenerated edges.

New release!

To fill the gap, I have created a new class called “geom_ShapeContent” which is based on “ShapeAnalysis_ShapeContenets”. Here I included functions to get the number of non-manifold edges and degenerated edges.

int myNbDegeneratedEdges = 0;
TopTools_IndexedMapOfShape mapDegeneratedEdge;
TopExp::MapShapes(myShape, TopAbs_EDGE, mapDegeneratedEdge);
for (int count = 1; count <= mapDegeneratedEdge.Extent(); count++)
{
    if (BRep_Tool::Degenerated(TopoDS::Edge(mapDegeneratedEdge(count))))
    	myNbDegeneratedEdges++;
}

TopTools_IndexedDataMapOfShapeListOfShape shapeListNonManifoldEdges;
TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, shapeListNonManifoldEdges);
const int nEdges = shapeListNonManifoldEdges.Extent();
for (int eCount = 1; eCount <= nEdges; eCount++)
{
    const TopoDS_Edge& edge = TopoDS::Edge(shapeListNonManifoldEdges.FindKey(eCount));
    //
    if (BRep_Tool::Degenerated(edge))
        continue;
    
    const int nOwningFaces = shapeListNonManifoldEdges.FindFromIndex(eCount).Extent();
    if (nOwningFaces > 2)
        myNbNonManifoldEdges++;
}

You can check that using this GitHub repository. Feel free to comment with your suggestions regarding API.

Hope to see you on a new topic!


Post a Comment

Previous Post Next Post