diff --git a/src/Mod/Part/App/FCBRepAlgoAPI_BooleanOperation.cpp b/src/Mod/Part/App/FCBRepAlgoAPI_BooleanOperation.cpp index 76de7f5be3..b49317ab71 100644 --- a/src/Mod/Part/App/FCBRepAlgoAPI_BooleanOperation.cpp +++ b/src/Mod/Part/App/FCBRepAlgoAPI_BooleanOperation.cpp @@ -81,72 +81,93 @@ void FCBRepAlgoAPIHelper::setAutoFuzzy(BRepAlgoAPI_BuilderAlgo* op) { op->SetFuzzyValue(Part::FuzzyHelper::getBooleanFuzzy() * sqrt(bounds.SquareExtent()) * Precision::Confusion()); } - -void FCBRepAlgoAPI_BooleanOperation::RecursiveAddArguments(const TopoDS_Shape& theArgument) { - TopoDS_Iterator it(theArgument); - for (; it.More(); it.Next()) { - if (it.Value().ShapeType() == TopAbs_COMPOUND) { - RecursiveAddArguments(it.Value()); - } else { - if (myArguments.IsEmpty()) { - myArguments.Append(it.Value()); - } else { - myTools.Append(it.Value()); - } - } - } -} - void FCBRepAlgoAPI_BooleanOperation::Build() { if (myOperation == BOPAlgo_CUT && myArguments.Size() == 1 && myTools.Size() == 1 && myTools.First().ShapeType() == TopAbs_COMPOUND) { + // cut argument and compound tool TopTools_ListOfShape myOriginalArguments = myArguments; TopTools_ListOfShape myOriginalTools = myTools; - TopTools_ListOfShape currentTools; - TopTools_ListOfShape currentArguments; - myArguments = currentArguments; - myTools = currentTools; - RecursiveAddArguments(myOriginalTools.First()); - if (!myTools.IsEmpty()) { - myOperation = BOPAlgo_FUSE; // fuse tools together - Build(); - myOperation = BOPAlgo_CUT; // restore - myArguments = myOriginalArguments; - if (IsDone()) { - myTools.Append(myShape); - Build(); // cut with fused tools - } - myTools = myOriginalTools; //restore - } else { // there was less than 2 shapes in the compound - myArguments = myOriginalArguments; - myTools = myOriginalTools; //restore - Build(); - } - } else if (myOperation==BOPAlgo_CUT && myArguments.Size()==1 && myArguments.First().ShapeType() == TopAbs_COMPOUND) { - TopTools_ListOfShape myOriginalArguments = myArguments; - myShape = RecursiveCutCompound(myOriginalArguments.First()); + RecursiveCutFusedTools(myOriginalArguments, myOriginalTools.First()); myArguments = myOriginalArguments; + myTools = myOriginalTools; + + } else if (myOperation==BOPAlgo_CUT && myArguments.Size()==1 && myArguments.First().ShapeType() == TopAbs_COMPOUND) { + // cut compound argument + TopTools_ListOfShape myOriginalArguments = myArguments; + RecursiveCutCompound(myOriginalArguments.First()); + myArguments = myOriginalArguments; + } else { BRepAlgoAPI_BooleanOperation::Build(); } } -TopoDS_Shape FCBRepAlgoAPI_BooleanOperation::RecursiveCutCompound(const TopoDS_Shape& theArgument) { +void FCBRepAlgoAPI_BooleanOperation::RecursiveAddTools(const TopoDS_Shape& theTool) { + TopoDS_Iterator it(theTool); + for (; it.More(); it.Next()) { + if (it.Value().ShapeType() == TopAbs_COMPOUND) { + RecursiveAddTools(it.Value()); + } else { + myTools.Append(it.Value()); + } + } +} + +void FCBRepAlgoAPI_BooleanOperation::RecursiveCutFusedTools(const TopTools_ListOfShape& theOriginalArguments, const TopoDS_Shape& theTool) +{ + // get a list of shapes in the tool compound + myTools.Clear(); + RecursiveAddTools(theTool); + + // if tool consists of two or more shapes, fuse them together + if (myTools.Size() >= 2) { + myArguments.Clear(); + myArguments.Append(myTools.First()); + myTools.RemoveFirst(); + myOperation = BOPAlgo_FUSE; + Build(); + + // restore original state + myOperation = BOPAlgo_CUT; + myArguments = theOriginalArguments; + + if (!IsDone()) { + myShape = {}; + return; + } + + // use fused shape as new tool + // if the original tools didn't all touch, the fused shape will be a compound + // which we convert into a list of shapes so we don't attempt to fuse them again + myTools.Clear(); + RecursiveAddTools(myShape); + } + + // do the cut + Build(); +} + +void FCBRepAlgoAPI_BooleanOperation::RecursiveCutCompound(const TopoDS_Shape& theArgument) { BRep_Builder builder; TopoDS_Compound comp; builder.MakeCompound(comp); + + // iterate through shapes in argument compound and cut each one with the tool TopoDS_Iterator it(theArgument); for (; it.More(); it.Next()) { - TopTools_ListOfShape currentArguments; - currentArguments.Append(it.Value()); - myArguments = currentArguments; + myArguments.Clear(); + myArguments.Append(it.Value()); Build(); - if (IsDone()) { - builder.Add(comp, myShape); - } else { - return {}; + + if (!IsDone()) { + myShape = {}; + return; } + + builder.Add(comp, myShape); } - return comp; + + // result is a compound of individual cuts + myShape = comp; } diff --git a/src/Mod/Part/App/FCBRepAlgoAPI_BooleanOperation.h b/src/Mod/Part/App/FCBRepAlgoAPI_BooleanOperation.h index d86a5f0910..b009d98e2e 100644 --- a/src/Mod/Part/App/FCBRepAlgoAPI_BooleanOperation.h +++ b/src/Mod/Part/App/FCBRepAlgoAPI_BooleanOperation.h @@ -60,9 +60,10 @@ protected: //! @name Constructors const TopoDS_Shape& theS2, BOPAlgo_Operation theOperation); - private: - Standard_EXPORT TopoDS_Shape RecursiveCutCompound(const TopoDS_Shape& theArgument); - Standard_EXPORT void RecursiveAddArguments(const TopoDS_Shape& theArgument); + Standard_EXPORT void RecursiveAddTools(const TopoDS_Shape& theTool); + Standard_EXPORT void RecursiveCutFusedTools(const TopTools_ListOfShape& theOriginalArguments, + const TopoDS_Shape& theTool); + Standard_EXPORT void RecursiveCutCompound(const TopoDS_Shape& theArgument); }; #endif