TopoDS_Shape GetImage(const TopoDS_Shape& source, BOPAlgo_BOP& API)
{
const TopTools_ListOfShape& modified = API.Modified(source);
//
if (modified.Extent() == 1)
return modified.First();
//
if (modified.Extent())
{
TopoDS_Compound C;
BRep_Builder().MakeCompound(C);
for (TopTools_ListIteratorOfListOfShape lit(modified); lit.More(); lit.Next())
{
const TopoDS_Shape& image = lit.Value();
BRep_Builder().Add(C, image);
}
return C;
}
const TopTools_ListOfShape& generated = API.Generated(source);
//
if (generated.Extent() == 1)
return generated.First();
//
if (generated.Extent())
{
TopoDS_Compound C;
BRep_Builder().MakeCompound(C);
for (TopTools_ListIteratorOfListOfShape lit(generated); lit.More(); lit.Next())
{
const TopoDS_Shape& image = lit.Value();
BRep_Builder().Add(C, image);
}
return C;
}
// This check is placed after all other checks intentionally. The idea is
// that for edges we may have GENERATED faces from them, while the edges
// themselves are DELETED. Since our focus is on features (which are
// essentially just sets of faces), we prefer returning an image face
// rather than null shape for a deleted edge (like it happens in filleting).
if (API.IsDeleted(source))
return TopoDS_Shape();
return source;
}
TopoDS_Shape
BooleanCut(const TopoDS_Shape& object, const TopoDS_Shape&
tool, std::vector<TopoDS_Face>& mshNewFaces)
{
mshNewFaces.clear();
// Prepare the arguments
TopTools_ListOfShape BOP_args;
BOP_args.Append(object);
BOP_args.Append(tool);
// Prepare data structure (calculate interferences)
Handle(NCollection_BaseAllocator) Alloc = new NCollection_IncAllocator;
//
BOPAlgo_PaveFiller DSFiller(Alloc);
DSFiller.SetArguments(BOP_args);
DSFiller.SetRunParallel(0);
Standard_Real fFuzzyValue = 1.e-5;
DSFiller.SetFuzzyValue(fFuzzyValue);
DSFiller.Perform();
// Check data structure
bool hasErr = DSFiller.HasErrors();
if (hasErr)
{
std::cout << "Error: cannot cut" << std::endl;
return TopoDS_Shape();
}
// Run BOP
BOPAlgo_BOP BOP(Alloc);
BOP.AddArgument(object);
BOP.AddTool(tool);
BOP.SetRunParallel(0);
BOP.SetOperation(BOPAlgo_CUT);
BOP.PerformWithFiller(DSFiller);
hasErr = BOP.HasErrors();
if (hasErr)
{
std::cout << "Error: cannot cut the part model from the stock model" << std::endl;
return TopoDS_Shape();
}
std::vector<TopoDS_Shape> mshOldFaces;
for (TopExp_Explorer explorer(object, TopAbs_FACE); explorer.More(); explorer.Next())
{
TopoDS_Shape imageShape = GetImage(explorer.Current(), BOP);
TopAbs_ShapeEnum shapeType = imageShape.ShapeType();
if (shapeType == TopAbs_ShapeEnum::TopAbs_FACE)
mshOldFaces.push_back(imageShape);
}
TopoDS_Shape cutShape = BOP.Shape();
for (TopExp_Explorer explorer(cutShape, TopAbs_FACE); explorer.More(); explorer.Next())
{
bool bFound = false;
for (auto it : mshOldFaces)
{
if (it.IsSame(explorer.Current()) == true)
{
bFound = true;
break;
}
}
if (bFound == false)
{
TopoDS_Face newFace = TopoDS::Face(explorer.Current());
mshNewFaces.push_back(newFace);
}
}
return cutShape;
}
int main()
{
// Create the main shape (box)
TopoDS_Shape mainShape = BRepPrimAPI_MakeBox(10.0, 5.0, 3.0).Shape();
// Create the tool shape (box)
TopoDS_Shape toolShape = BRepPrimAPI_MakeBox(4.0, 2.0, 2.0).Shape();
std::vector<TopoDS_Face> mshNewFaces;
TopoDS_Shape cutShape = BooleanCut(mainShape, toolShape, mshNewFaces);
}