]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
PAL12470: Cannot use boolean operations on COMPOUNDs and COMPSOLIDs. Workaround OCCT...
authorjfa <jfa@opencascade.com>
Tue, 29 Aug 2006 14:57:56 +0000 (14:57 +0000)
committerjfa <jfa@opencascade.com>
Tue, 29 Aug 2006 14:57:56 +0000 (14:57 +0000)
src/GEOMImpl/GEOMImpl_BooleanDriver.cxx

index a0ae0bc0c9bed967b4a12661edac79dad8bccb1f..ca0812c39f40cff939d4a222462e06c3ad6e188e 100644 (file)
@@ -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 <Standard_Stream.hxx>
-
 #include <GEOMImpl_BooleanDriver.hxx>
 #include <GEOMImpl_IBoolean.hxx>
 #include <GEOMImpl_Types.hxx>
+#include <GEOMImpl_GlueDriver.hxx>
 #include <GEOM_Function.hxx>
 
+#include <BRep_Builder.hxx>
 #include <BRepAlgo.hxx>
 #include <BRepAlgoAPI_Common.hxx>
 #include <BRepAlgoAPI_Cut.hxx>
 #include <BRepAlgoAPI_Fuse.hxx>
 #include <BRepAlgoAPI_Section.hxx>
 #include <TopoDS_Shape.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <Precision.hxx>
 
 #include <Standard_ConstructionError.hxx>
 #include <StdFail_NotDone.hxx>
@@ -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);