Salome HOME
Implement 'make dist' and 'make distcheck' steps support
[modules/geom.git] / src / GEOMImpl / GEOMImpl_BooleanDriver.cxx
index 2a7c71386758c32e2ab14d51bccfc24e2f975b73..39d625d5460c172e043c58f744d06d0d68079f57 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>
@@ -37,6 +38,9 @@
 #include <TopTools_ListOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <Precision.hxx>
+#include <BRepCheck_Analyzer.hxx>
+#include <ShapeFix_ShapeTolerance.hxx>
+#include <ShapeFix_Shape.hxx>
 
 #include <Standard_ConstructionError.hxx>
 #include <StdFail_NotDone.hxx>
@@ -152,6 +156,7 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const
       }
 
       if (isCompound) {
+        /*
         TopTools_ListOfShape listShapeC;
         AddSimpleShapes(C, listShapeC);
         TopTools_ListIteratorOfListOfShape itSubC (listShapeC);
@@ -164,6 +169,14 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const
           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;
       }
     }
 
@@ -214,6 +227,7 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const
       }
 
       if (isCompound) {
+        /*
         TopTools_ListOfShape listShapeC;
         AddSimpleShapes(C, listShapeC);
         TopTools_ListIteratorOfListOfShape itSubC (listShapeC);
@@ -226,11 +240,96 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const
           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) {
+      /* 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;
+                }
+              }
+            }
+          }
+        }
+      }
+
+      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");
@@ -291,8 +390,16 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const
         }
       }
 
-      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
@@ -301,9 +408,24 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute(TFunction_Logbook& log) const
   }
 
   if (aShape.IsNull()) return 0;
-  if (!BRepAlgo::IsValid(aShape)) {
-    Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result");
+
+  // 08.07.2008 skl for bug 19761 from Mantis
+  BRepCheck_Analyzer ana (aShape, Standard_True);
+  ana.Init(aShape);
+  if (!ana.IsValid()) {
+    ShapeFix_ShapeTolerance aSFT;
+    aSFT.LimitTolerance(aShape, Precision::Confusion(),
+                        Precision::Confusion(), TopAbs_SHAPE);
+    Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape);
+    aSfs->Perform();
+    aShape = aSfs->Shape();
+    ana.Init(aShape);
+    if (!ana.IsValid())
+      Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result");
   }
+  //if (!BRepAlgo::IsValid(aShape)) {
+  //  Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result");
+  //}
 
   aFunction->SetValue(aShape);