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_Solid
s
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_Solid
s from the Compound:
If there is a chance that there are zero or more than one TopoDS_Solid
s 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 ! */
}