How to fuse TopoDS_Shapes in OpenCASCADE (boolean OR)
The OCCUtils library provides an easy way to fuse two shapes in OpenCASCADE.
First, let’s generate a box and a cylinder using OCCUtil’s primitive generation functions:
#include <occutils/Primitive.hxx>
using namespace OCCUtils;
TopoDS_Shape solid1 = Primitive::MakeBox(18 /* X */, 8 /* Y */, 14 /* Z */,
Primitive::CenterX | Primitive::CenterY);
TopoDS_Shape solid2 = Primitive::MakeCylinder(5 /* d */, 35 /* L */,
Primitivs::Orientation::Z,
Primitive::CenterD);
Now we can fuse the primitives using this snippet:
#include <occutils/Boolean.hxx>
using namespace OCCUtils;
TopoDS_Shape fused = Boolean::Fuse({solid1, solid2});
Boolean::Fuse()
can take a number of different argument types. In this example, we’are using a std::initializer_list
(this is the curly-bracket syntax) - but it can also take a TopTools_ListOfShape
or a std::vector<TopoDS_Shape>
(and also most other STL- or non-STL containers).
If you want to perform a fuse without using OCCUtils, you might be tempted to use this syntax:
BRepAlgoAPI_Fuse fuse(solid1, solid2);
fuse.Build();
TopoDS_Shape result = fuse.Shape();
However, the BRepAlgoAPI_Fuse(TopoDS, TopoDS)
constructor is deprecated and should therefore not be used. Instead, the following syntax should be used:
// Configure fuse
BRepAlgoAPI_Fuse fuse;
fuse.SetArguments(arguments);
fuse.SetTools(tools);
// Run fuse
fuse.Build();
TopoDS_Shape shape = fuse.Shape(); // Raises NotDone if not done.
where arguments
and tools
are two TopTools_ListOfShape
instances. For other boolean algorithms like BRepAlgoAPI_Cut
(boolean difference) the two have distinct meanings, but for BRepAlgoAPI_Fuse
it’s just important that both arguments
and tools
have at least one element each!
You can use ListUtils::SplitIntoHeadAndTail
from OCCUtils to generate a std::pair
of lists (arguments
and tools
), with arguments having one element and tools having the rest like this:
auto toolsAndArgs = ListUtils::SplitIntoHeadAndTail(shapes, 1);
auto tools = toolsAndArgs.first;
auto arguments = toolsAndArgs.second;
However, if you use ListUtils::SplitIntoHeadAndTail()
, you can just use Boolean::Fuse()
right away.