OpenCASCADE

How to create a Box TopoDS_Solid in OpenCASCADE

Also see How to create a Cube TopoDS_Solid in OpenCASCADE and How to create a Cylinder TopoDS_Solid in OpenCASCADE

Using my OCCUtils library, you can easily create a box of user-defined dimensions:

#include <occutils/Primitive.hxx>
#include <vector>

using namespace OCCUtils;

TopoDS_Solid myCube = Primitive::MakeBox(5.0 /* X size */, 7.0 /* Y size */, 9.0 /* Z size */);

You can also center this box on one or more axes (if not centered in any axis, one of the corners is going to be on thre origin point):

#include <occutils/Primitive.hxx>
#include <vector>

using namespace OCCUtils;

/*
 * Make a box that is centered on the X- and Y axes
 */
TopoDS_Solid myCube = Primitive::MakeBox(5.0, 7.0, 9.0
    Primitive::CenterX | Primitive::CenterY);

Also you can use a specific point of origin as the third argument (gp_Pnt).

If you want to do it manually without OCCUtils, have a look at the OCC class BRepPrimAPI_MakeBox which you can use like this:

BRepPrimAPI_MakeBox box(origin, xSize, ySize, zSize);
box.Build();
TopoDS_Solid mySolid = box.Solid();

In this case, you have to center the object manually by computing the correct point of origin. In OCCUtils this is done using

// Compute offsets based on centering
if(center & CenterX) {
    origin.SetX(origin.X() - xSize / 2.0);
}
if(center & CenterY) {
    origin.SetY(origin.Y() - ySize / 2.0);
}
if(center & CenterZ) {
    origin.SetZ(origin.Z() - zSize / 2.0);
}

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to create a Cube TopoDS_Solid in OpenCASCADE

Also see How to create a Box TopoDS_Solid in OpenCASCADE and How to create a Cylinder TopoDS_Solid in OpenCASCADE

Using my OCCUtils library, you can easily create a cube of user-defined dimensions:

#include <occutils/Primitive.hxx>

using namespace OCCUtils;

TopoDS_Solid myCube = Primitive::MakeCube(5.0 /* mm side length */);

You can also center this cube on one or more axes (if not centered in any axis, one of the corners is going to be on thre origin point):

#include <occutils/Primitive.hxx>

using namespace OCCUtils;

/*
 * Make a cube that is centered on the X- and Y axes
 */
TopoDS_Solid myCube = Primitive::MakeCube(5.0 /* mm side length */,
    Primitive::CenterX | Primitive::CenterY);

Also you can use a specific point of origin as the third argument (gp_Pnt).

If you want to do it manually without OCCUtils, have a look at the OCC class BRepPrimAPI_MakeBox which you can use like this:

BRepPrimAPI_MakeBox box(origin, size, size, size);
box.Build();
TopoDS_Solid mySolid = box.Solid();

In this case, you have to center the object manually by computing the correct point of origin. In OCCUtils this is done using

// Compute offsets based on centering
if(center & CenterX) {
    origin.SetX(origin.X() - xSize / 2.0);
}
if(center & CenterY) {
    origin.SetY(origin.Y() - ySize / 2.0);
}
if(center & CenterZ) {
    origin.SetZ(origin.Z() - zSize / 2.0);
}

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to create TopTools_ListOfShape of two or more shapes in OpenCASCADE

TopTools_ListOfShape is just another name for NCollection_List<TopoDS_Shape>.

Using my OCCUtils library this is really easy:

#include <TopTools_ListOfShape.hxx>
#include <occutils/ListUtils.hxx>

using namespace OCCUtils;

/* ... */

TopoDS_Solid solid1 = /* ... */;
TopoDS_Solid solid2 = /* ... */;

TopTools_ListOfShape shapes = ListUtils::ToOCCList({solid1, solid2});

ListUtils::ToOCCList() takes almost anything as an argument, a std::initializer_list (this is the bracket syntax from the example above) but also any type of STL container like a std::vector or a std::list, and converts it into a NCollection_List<T>:

#include <TopTools_ListOfShape.hxx>
#include <occutils/ListUtils.hxx>
#include <vector>

using namespace OCCUtils;

/* ... */

TopoDS_Solid solid1 = /* ... */;
TopoDS_Solid solid2 = /* ... */;

std::vector<TopoDS_Shape> shapeVector({solid1, solid2});

TopTools_ListOfShape shapes = ListUtils::ToOCCList(shapeVector);

In case you don’t want to use OCCUtils, this is how you can create a TopTools_ListOfShape manually:

TopTools_ListOfShape list;
list.Append(shape1);
list.Append(shape2);

Since NCollection_List and therefore also TopTools_ListOfShape is a linked list internally, you can also use list.Prepend(shape); to add a shape to the front of the list without any performance penalty.

In case you want to create the list from a std::vector or any similar STL container, use this snippet:

std::vector<TopoDS_Shape>& shapeVector = /* ... */;

TopTools_ListOfShape list;
for(const TopoDS_Shape& shape : shapeVector) {
    list.Append(arg);
}

After creating the container, you can iterate it using the C++11 range-based for-loop:

TopTools_ListOfShape myShapes = /* ... */;

// Iterate myShapes
for(const TopoDS_Shape& shape : myShapes) {
    /* ... */
}

See How to iterate TopTools_ListOfShape in OpenCASCADE and How to iterate NCollection_List in OpenCASCADE for more details on that.

Posted by Uli Köhler in C/C++, OpenCASCADE

How to iterate TopTools_ListOfShape in OpenCASCADE

TopTools_ListOfShape is a NCollection_List<T> and hence supports iteration using the C++11 foreach loop (also called range-based for loop):
TopTools_ListOfShape myShapes = /* ... */;

// Iterate myShapes
for(const TopoDS_Shape& shape : myShapes) {
    /* ... */
}

Remember to compile with at least --std=c++11 or equivalent for your compiler to allow using the range-based for loop.

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to iterate NCollection_List in OpenCASCADE

NCollection_List<T> supports iteration using the C++11 foreach loop (also called range-based for loop):
NCollection_List<T> myList = /* ... */;

// Iterate myList
for(const T& value : myList) {
    /* ... */
}

Remember to compile with at least --std=c++11 or equivalent for your compiler to allow using the range-based for loop.

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to iterate all edges in TopoDS_Face using OpenCASCADE

You can use the OCCUtils library to iterate all TopoDS_Face instances in a TopoDS_Solid

#include <occutils/ShapeComponents.hxx>

using namespace OCCUtils;

TopoDS_Shape myShape = /* ... */;

auto edges = ShapeComponents::AllEdgesWithin(myShape);

// Iterate all solids
for(const TopoDS_Edge& edge : edges) {
    /* ... */
}

Alternatively, you can use this raw OpenCASCADE source code without OCCUtils:

#include <TopTools_IndexedMapOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopExp.hxx>

TopoDS_Shape myShape = /* ... */;

TopTools_IndexedMapOfShape faces;
TopExp::MapShapes (myShape, TopAbs_EDGE, faces);

for (int i = 1; i <= faces.Extent (); i++) {
    TopoDS_Edge face = TopoDS::Edge(edges(i));
    /* ... */
}

If you have the choice, I recommend using OCCUtils since it makes your code much more readable than using the raw OpenCASCADE API.

Posted by Uli Köhler in C/C++, OpenCASCADE

How to iterate all faces in TopoDS_Solid using OpenCASCADE

You can use the OCCUtils library to iterate all TopoDS_Face instances in a TopoDS_Solid

#include <occutils/ShapeComponents.hxx>

using namespace OCCUtils;

TopoDS_Shape myShape = /* ... */;

auto faces = ShapeComponents::AllFacesWithin(myShape);

// Iterate all solids
for(const TopoDS_Face& face : faces) {
    /* ... */
}

Alternatively, you can use this source code without OCCUtils:

#include <TopTools_IndexedMapOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopExp.hxx>

TopoDS_Shape myShape = /* ... */;

TopTools_IndexedMapOfShape faces;
TopExp::MapShapes (myShape, TopAbs_FACE, faces);

for (int i = 1; i <= faces.Extent (); i++) {
    TopoDS_Face face = TopoDS::Face(faces(i));
    /* ... */
}

If you have the choice, I recommend using OCCUtils since it makes your code much more readable than using the raw OpenCASCADE API.

Posted by Uli Köhler in C/C++, OpenCASCADE

How to get TopoDS_Solid(s) from TopoDS_Shape in OpenCASCADE

There are two important cases if you want to get a TopoDS_Solid object from a TopoDS_Shape:

A: The TopoDS_Shape is a solid

You can check if that is the case using

#include <TopoDS_Shape.hxx>

TopoDS_Shape myShape = /* ... */

bool isSolid = myShape.ShapeType() == TopAbs_SOLID;

Alternatively, you can use the Shape::IsSolid() function from OCCUtils:

#include <occutils/Shape.hxx>

using namespace OCCUtils;

TopoDS_Shape myShape = /* ... */;

if(Shape::IsSolid(myShape)) {
    /* ... */
}

If it’s a solid, you can convert it to a TopoDS_Solid directly using:

TopoDS::Solid(myShape);

Full example:

#include <TopoDS_Shape.hxx>
#include <TopoDS.hxx>
#include <occutils/Shape.hxx>

using namespace OCCUtils;

TopoDS_Shape myShape = /* ... */;

if (Shape::IsSolid(myShape)) {
    TopoDS_Solid solid = TopoDS::Solid(myShape);
    /* ... */
}

B: The shape is not itself a TopoDS_Solid but contains one or more TopoDS_Solids

This is often the case for TopoDS_Compounds. Use Shape::IsCompound() from OCCUtils to check if your TopoDS_Shape is actually a TopoDS_Compound.

#include <occutils/Shape.hxx>
using namespace OCCUtils;

TopoDS_Shape myShape = /* ... */;
if(Shape::IsCompound(myShape)) { /* ... */ }

Using OCCUtils, you have now several options to get the TopoDS_Solids from the Compound:

If there is a chance that there are zero or more than one TopoDS_Solids in your compound:

Use ShapeComponents::AllSolidsWithin() from OCCUtils to get a std::vector<TopoDS_Solid> of all solids within the TopoDS_Compound:

#include <occutils/Shape.hxx>
#include <occutils/ShapeComponents.hxx>

using namespace OCCUtils;

TopoDS_Shape myShape = /* ... */;

auto solids = ShapeComponents::AllSolidsWithin(myShape);

// Iterate all solids
for(const TopoDS_Solid& solid : solids) {
    /* ... */
}

If you are sure the compound only contains one solid (also works if it’s a solid itself):

Use ShapeComponents::TryGetSingleSolid(shape) which returns a std::optional<TopoDS_Solid> (no value if there is no solid or there are multiple solids in shape) or ShapeComponents::GetSingleSolid(shape) which throws an exception if there is no solid or there are multiple solids in the shape.

Example:

#include <occutils/ShapeComponents.hxx>
#include <iostream> // cerr, endl

using namespace std;
using namespace OCCUtils;

TopoDS_Shape myShape = /* ... */;

auto solidOpt = ShapeComponents::TryGetSingleSolid(myShape);

if(solidOpt.has_value()) {
    TopoDS_Solid solid = solidOpt.value();
} else {
    cerr << "No solid or multiple solids in shape!" << endl;
}

If you want to use pure OpenCASCADE without OCCUtils:

Use this snippet to directly iterate the TopoDS_Solid instances in the shape

TopTools_IndexedMapOfShape solidShapes;
TopExp::MapShapes (myShape, TopAbs_SOLID, solidShapes);

for (int i = 1; i <= solidShapes.Extent (); i++) {
    TopoDS_Solid solid = TopoDS::Solid(solidShapes(i));
    /* Do what you need with the solid here ! */
}

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to compute surface area of TopoDS_Face in OpenCASCADE

In order to compute the surface area of a TopoDS_Face, in OpenCASCADE, simply use BRepGProp::SurfaceProperties and call .Mass() on the resulting GProp_GProps object:

GProp_GProps gprops;
BRepGProp::SurfaceProperties(face, gprops); // Stores results in gprops
double area = gprops.Mass();

Alternatively, you can use my OCCUtils library which also also providers a lot of other utility functions:

#include <occutils/Surface.hxx>
using namespace OCCUtils;

double Surface::Area(const TopoDS_Shape& face);

Example:

#include <occutils/Surface.hxx>

using namespace OCCUtils;

// ...
double area = Surface::Area(myFace);
// ...

 

Posted by Uli Köhler in C/C++, OpenCASCADE