From 6dba78d6b9c40432927ef90f874cfc9da6ec2682 Mon Sep 17 00:00:00 2001 From: jfa Date: Tue, 29 Aug 2006 14:57:56 +0000 Subject: [PATCH] PAL12470: Cannot use boolean operations on COMPOUNDs and COMPSOLIDs. Workaround OCCT limitation, performing boolean operations on sub-shapes and then gathering results in a compound. --- src/GEOMImpl/GEOMImpl_BooleanDriver.cxx | 193 ++++++++++++++++++++---- 1 file changed, 161 insertions(+), 32 deletions(-) diff --git a/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx b/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx index a0ae0bc0c..ca0812c39 100644 --- a/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx @@ -1,36 +1,42 @@ // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// +// // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either +// License as published by the Free Software Foundation; either // version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// +// This library is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -#include - #include #include #include +#include #include +#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -54,6 +60,30 @@ GEOMImpl_BooleanDriver::GEOMImpl_BooleanDriver() { } +void AddSimpleShapes(TopoDS_Shape theShape, TopTools_ListOfShape& theList) +{ + if (theShape.ShapeType() != TopAbs_COMPOUND && + theShape.ShapeType() != TopAbs_COMPSOLID) { + theList.Append(theShape); + return; + } + + TopTools_MapOfShape mapShape; + TopoDS_Iterator It (theShape, Standard_True, Standard_True); + + for (; It.More(); It.Next()) { + TopoDS_Shape aShape_i = It.Value(); + if (mapShape.Add(aShape_i)) { + if (aShape_i.ShapeType() == TopAbs_COMPOUND || + aShape_i.ShapeType() == TopAbs_COMPSOLID) { + AddSimpleShapes(aShape_i, theList); + } else { + theList.Append(aShape_i); + } + } + } +} + //======================================================================= //function : Execute //purpose : @@ -73,38 +103,137 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const TopoDS_Shape aShape1 = aRefShape1->GetValue(); TopoDS_Shape aShape2 = aRefShape2->GetValue(); if (!aShape1.IsNull() && !aShape2.IsNull()) { + + // perform COMMON operation if (aType == BOOLEAN_COMMON) { - BRepAlgoAPI_Common BO (aShape1, aShape2); -// BO.Build(); - if (!BO.IsDone()) { - StdFail_NotDone::Raise("Requested boolean operation can not be performed on the given shapes"); + BRep_Builder B; + TopoDS_Compound C; + B.MakeCompound(C); + + TopTools_ListOfShape listShape1, listShape2; + AddSimpleShapes(aShape1, listShape1); + AddSimpleShapes(aShape2, listShape2); + + Standard_Boolean isCompound = + (listShape1.Extent() > 1 || listShape2.Extent() > 1); + + TopTools_ListIteratorOfListOfShape itSub1 (listShape1); + for (; itSub1.More(); itSub1.Next()) { + TopoDS_Shape aValue1 = itSub1.Value(); + TopTools_ListIteratorOfListOfShape itSub2 (listShape2); + for (; itSub2.More(); itSub2.Next()) { + TopoDS_Shape aValue2 = itSub2.Value(); + BRepAlgoAPI_Common BO (aValue1, aValue2); + if (!BO.IsDone()) { + StdFail_NotDone::Raise("Common operation can not be performed on the given shapes"); + } + if (isCompound) + B.Add(C, BO.Shape()); + else + aShape = BO.Shape(); + } } - aShape = BO.Shape(); - } else if (aType == BOOLEAN_CUT) { - BRepAlgoAPI_Cut BO (aShape1, aShape2); - if (!BO.IsDone()) { - StdFail_NotDone::Raise("Requested boolean operation can not be performed on the given shapes"); + + if (isCompound) + aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion()); + } + + // perform CUT operation + else if (aType == BOOLEAN_CUT) { + BRep_Builder B; + TopoDS_Compound C; + B.MakeCompound(C); + + TopTools_ListOfShape listShapes, listTools; + AddSimpleShapes(aShape1, listShapes); + AddSimpleShapes(aShape2, listTools); + + Standard_Boolean isCompound = (listShapes.Extent() > 1); + + TopTools_ListIteratorOfListOfShape itSub1 (listShapes); + for (; itSub1.More(); itSub1.Next()) { + TopoDS_Shape aCut = itSub1.Value(); + // tools + TopTools_ListIteratorOfListOfShape itSub2 (listTools); + for (; itSub2.More(); itSub2.Next()) { + TopoDS_Shape aTool = itSub2.Value(); + BRepAlgoAPI_Cut BO (aCut, aTool); + if (!BO.IsDone()) { + StdFail_NotDone::Raise("Cut operation can not be performed on the given shapes"); + } + aCut = BO.Shape(); + } + if (isCompound) + B.Add(C, aCut); + else + aShape = aCut; } - aShape = BO.Shape(); - } else if (aType == BOOLEAN_FUSE) { - BRepAlgoAPI_Fuse BO (aShape1, aShape2); - if (!BO.IsDone()) { - StdFail_NotDone::Raise("Requested boolean operation can not be performed on the given shapes"); + + if (isCompound) + aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion()); + } + + // perform FUSE operation + else if (aType == BOOLEAN_FUSE) { + // check shapes to provide special processing for compounds and compsolids + if (aShape1.ShapeType() == TopAbs_COMPOUND || + aShape1.ShapeType() == TopAbs_COMPSOLID || + aShape2.ShapeType() == TopAbs_COMPOUND || + aShape2.ShapeType() == TopAbs_COMPSOLID) { + // at least one of arguments is complex + StdFail_NotDone::Raise("Fuse operation aborted: one of arguments is a complex shape"); + } else { + // simple arguments + BRepAlgoAPI_Fuse BO (aShape1, aShape2); + if (!BO.IsDone()) { + StdFail_NotDone::Raise("Fuse operation can not be performed on the given shapes"); + } + aShape = BO.Shape(); } - aShape = BO.Shape(); - } else if (aType == BOOLEAN_SECTION) { - BRepAlgoAPI_Section BO (aShape1, aShape2); - if (!BO.IsDone()) { - StdFail_NotDone::Raise("Requested boolean operation can not be performed on the given shapes"); + } + + // perform SECTION operation + else if (aType == BOOLEAN_SECTION) { + BRep_Builder B; + TopoDS_Compound C; + B.MakeCompound(C); + + TopTools_ListOfShape listShape1, listShape2; + AddSimpleShapes(aShape1, listShape1); + AddSimpleShapes(aShape2, listShape2); + + Standard_Boolean isCompound = + (listShape1.Extent() > 1 || listShape2.Extent() > 1); + + TopTools_ListIteratorOfListOfShape itSub1 (listShape1); + for (; itSub1.More(); itSub1.Next()) { + TopoDS_Shape aValue1 = itSub1.Value(); + TopTools_ListIteratorOfListOfShape itSub2 (listShape2); + for (; itSub2.More(); itSub2.Next()) { + TopoDS_Shape aValue2 = itSub2.Value(); + BRepAlgoAPI_Section BO (aValue1, aValue2); + if (!BO.IsDone()) { + StdFail_NotDone::Raise("Section operation can not be performed on the given shapes"); + } + if (isCompound) + B.Add(C, BO.Shape()); + else + aShape = BO.Shape(); + } } - aShape = BO.Shape(); - } else { + + if (isCompound) + aShape = C; + } + + // UNKNOWN operation + else { } } if (aShape.IsNull()) return 0; if (!BRepAlgo::IsValid(aShape)) { - Standard_ConstructionError::Raise("Boolean aborted : non valid shape result"); + Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result"); } aFunction->SetValue(aShape);