Salome HOME
NPAL14856: Get The Normal of a Face.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_BooleanDriver.cxx
index ca0812c39f40cff939d4a222462e06c3ad6e188e..c419cd6d5f93adbc78297384662cad6e3a0c762f 100644 (file)
@@ -30,6 +30,7 @@
 #include <BRepAlgoAPI_Cut.hxx>
 #include <BRepAlgoAPI_Fuse.hxx>
 #include <BRepAlgoAPI_Section.hxx>
+#include <TopExp_Explorer.hxx>
 #include <TopoDS_Shape.hxx>
 #include <TopoDS_Compound.hxx>
 #include <TopoDS_Iterator.hxx>
@@ -127,15 +128,53 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const
           if (!BO.IsDone()) {
             StdFail_NotDone::Raise("Common operation can not be performed on the given shapes");
           }
-          if (isCompound)
-            B.Add(C, BO.Shape());
+          if (isCompound) {
+            TopoDS_Shape aStepResult = BO.Shape();
+
+            // check result of this step: if it is a compound (boolean operations
+            // allways return a compound), we add all sub-shapes of it.
+            // This allows to avoid adding empty compounds,
+            // resulting from COMMON on two non-intersecting shapes.
+            if (aStepResult.ShapeType() == TopAbs_COMPOUND) {
+              TopoDS_Iterator aCompIter (aStepResult);
+              for (; aCompIter.More(); aCompIter.Next()) {
+                // add shape in a result
+                B.Add(C, aCompIter.Value());
+              }
+            }
+            else {
+              // add shape in a result
+              B.Add(C, aStepResult);
+            }
+          }
           else
             aShape = BO.Shape();
         }
       }
 
-      if (isCompound)
-        aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion());
+      if (isCompound) {
+        /*
+        TopTools_ListOfShape listShapeC;
+        AddSimpleShapes(C, listShapeC);
+        TopTools_ListIteratorOfListOfShape itSubC (listShapeC);
+        bool isOnlySolids = true;
+        for (; itSubC.More(); itSubC.Next()) {
+          TopoDS_Shape aValueC = itSubC.Value();
+          if (aValueC.ShapeType() != TopAbs_SOLID) isOnlySolids = false;
+        }
+        if (isOnlySolids)
+          aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion());
+        else
+          aShape = C;
+        */
+
+        // As GlueFaces has been improved to keep all kind of shapes
+        TopExp_Explorer anExp (C, TopAbs_VERTEX);
+        if (anExp.More())
+          aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
+        else
+          aShape = C;
+      }
     }
 
     // perform CUT operation
@@ -163,33 +202,136 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const
           }
           aCut = BO.Shape();
         }
-        if (isCompound)
-          B.Add(C, aCut);
+        if (isCompound) {
+          // check result of this step: if it is a compound (boolean operations
+          // allways return a compound), we add all sub-shapes of it.
+          // This allows to avoid adding empty compounds,
+          // resulting from CUT of parts
+          if (aCut.ShapeType() == TopAbs_COMPOUND) {
+            TopoDS_Iterator aCompIter (aCut);
+            for (; aCompIter.More(); aCompIter.Next()) {
+              // add shape in a result
+              B.Add(C, aCompIter.Value());
+            }
+          }
+          else {
+            // add shape in a result
+            B.Add(C, aCut);
+          }
+        }
         else
           aShape = aCut;
       }
 
-      if (isCompound)
-        aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion());
+      if (isCompound) {
+        /*
+        TopTools_ListOfShape listShapeC;
+        AddSimpleShapes(C, listShapeC);
+        TopTools_ListIteratorOfListOfShape itSubC (listShapeC);
+        bool isOnlySolids = true;
+        for (; itSubC.More(); itSubC.Next()) {
+          TopoDS_Shape aValueC = itSubC.Value();
+          if (aValueC.ShapeType() != TopAbs_SOLID) isOnlySolids = false;
+        }
+        if (isOnlySolids)
+          aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion());
+        else
+          aShape = C;
+        */
+
+        // As GlueFaces has been improved to keep all kind of shapes
+        TopExp_Explorer anExp (C, TopAbs_VERTEX);
+        if (anExp.More())
+          aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
+        else
+          aShape = C;
+      }
     }
 
     // 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");
+      /* Fix for NPAL15379: refused
+      // Check arguments
+      TopTools_ListOfShape listShape1, listShape2;
+      AddSimpleShapes(aShape1, listShape1);
+      AddSimpleShapes(aShape2, listShape2);
+
+      Standard_Boolean isIntersect = Standard_False;
+
+      if (listShape1.Extent() > 1 && !isIntersect) {
+        // check intersections inside the first compound
+        TopTools_ListIteratorOfListOfShape it1 (listShape1);
+        for (; it1.More() && !isIntersect; it1.Next()) {
+          TopoDS_Shape aValue1 = it1.Value();
+          TopTools_ListIteratorOfListOfShape it2 (listShape1);
+          for (; it2.More() && !isIntersect; it2.Next()) {
+            TopoDS_Shape aValue2 = it2.Value();
+            if (aValue2 != aValue1) {
+              BRepAlgoAPI_Section BO (aValue1, aValue2);
+              if (BO.IsDone()) {
+                TopoDS_Shape aSect = BO.Shape();
+                TopExp_Explorer anExp (aSect, TopAbs_EDGE);
+                if (anExp.More()) {
+                  isIntersect = Standard_True;
+                }
+              }
+            }
+          }
         }
-        aShape = BO.Shape();
       }
+
+      if (listShape2.Extent() > 1 && !isIntersect) {
+        // check intersections inside the second compound
+        TopTools_ListIteratorOfListOfShape it1 (listShape2);
+        for (; it1.More() && !isIntersect; it1.Next()) {
+          TopoDS_Shape aValue1 = it1.Value();
+          TopTools_ListIteratorOfListOfShape it2 (listShape2);
+          for (; it2.More() && !isIntersect; it2.Next()) {
+            TopoDS_Shape aValue2 = it2.Value();
+            if (aValue2 != aValue1) {
+              BRepAlgoAPI_Section BO (aValue1, aValue2);
+              if (BO.IsDone()) {
+                TopoDS_Shape aSect = BO.Shape();
+                TopExp_Explorer anExp (aSect, TopAbs_EDGE);
+                if (anExp.More()) {
+                  isIntersect = Standard_True;
+                }
+              }
+            }
+          }
+        }
+      }
+
+      if (isIntersect) {
+        // have intersections inside compounds
+        // check intersections between compounds
+        TopTools_ListIteratorOfListOfShape it1 (listShape1);
+        for (; it1.More(); it1.Next()) {
+          TopoDS_Shape aValue1 = it1.Value();
+          TopTools_ListIteratorOfListOfShape it2 (listShape2);
+          for (; it2.More(); it2.Next()) {
+            TopoDS_Shape aValue2 = it2.Value();
+            if (aValue2 != aValue1) {
+              BRepAlgoAPI_Section BO (aValue1, aValue2);
+              if (BO.IsDone()) {
+                TopoDS_Shape aSect = BO.Shape();
+                TopExp_Explorer anExp (aSect, TopAbs_EDGE);
+                if (anExp.More()) {
+                  StdFail_NotDone::Raise("Bad argument for Fuse: compound with intersecting sub-shapes");
+                }
+              }
+            }
+          }
+        }
+      }
+      */
+
+      // Perform
+      BRepAlgoAPI_Fuse BO (aShape1, aShape2);
+      if (!BO.IsDone()) {
+        StdFail_NotDone::Raise("Fuse operation can not be performed on the given shapes");
+      }
+      aShape = BO.Shape();
     }
 
     // perform SECTION operation
@@ -211,19 +353,50 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const
         TopTools_ListIteratorOfListOfShape itSub2 (listShape2);
         for (; itSub2.More(); itSub2.Next()) {
           TopoDS_Shape aValue2 = itSub2.Value();
-          BRepAlgoAPI_Section BO (aValue1, aValue2);
+          BRepAlgoAPI_Section BO (aValue1, aValue2, Standard_False);
+          // Set approximation to have an attached 3D BSpline geometry to each edge,
+          // where analytic curve is not possible. Without this flag in some cases
+          // we obtain BSpline curve of degree 1 (C0), which is slowly
+          // processed by some algorithms (Partition for example).
+          BO.Approximation(Standard_True);
+          BO.Build();
           if (!BO.IsDone()) {
             StdFail_NotDone::Raise("Section operation can not be performed on the given shapes");
           }
-          if (isCompound)
-            B.Add(C, BO.Shape());
+          if (isCompound) {
+            TopoDS_Shape aStepResult = BO.Shape();
+
+            // check result of this step: if it is a compound (boolean operations
+            // allways return a compound), we add all sub-shapes of it.
+            // This allows to avoid adding empty compounds,
+            // resulting from SECTION on two non-intersecting shapes.
+            if (aStepResult.ShapeType() == TopAbs_COMPOUND) {
+              TopoDS_Iterator aCompIter (aStepResult);
+              for (; aCompIter.More(); aCompIter.Next()) {
+                // add shape in a result
+                B.Add(C, aCompIter.Value());
+              }
+            }
+            else {
+              // add shape in a result
+              B.Add(C, aStepResult);
+            }
+          }
           else
             aShape = BO.Shape();
         }
       }
 
-      if (isCompound)
-        aShape = C;
+      if (isCompound) {
+        //aShape = C;
+
+        // As GlueFaces has been improved to keep all kind of shapes
+        TopExp_Explorer anExp (C, TopAbs_VERTEX);
+        if (anExp.More())
+          aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
+        else
+          aShape = C;
+      }
     }
 
     // UNKNOWN operation