]> OCCT Git - occt.git/commitdiff
0029646: Boolean Operations algorithm produces a face with self-intersecting wire
authoremv <emv@opencascade.com>
Mon, 26 Mar 2018 12:06:18 +0000 (15:06 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 29 Mar 2018 14:13:12 +0000 (17:13 +0300)
Boolean operations - Allow repeated intersection of edges to find the coinciding pairs.
Previously, only the edges rejected by bounding boxes classification has been additionally checked on coincidence. The current patch removes this filter allowing all edges with coinciding vertices to be checked on coincidence.

Adjustment of the test cases for current behavior:
1. The following cases are improvements:
boolean volumemaker A8
bugs modalg_1 buc60703_1
bugs modalg_1 buc60703_2
bugs modalg_1 buc60703_4
bugs modalg_6 bug26789_1
bugs modalg_6 bug26789_2
bugs modalg_7 bug26883_4
bugs modalg_7 bug27948

2. bugs modalg_7 bug29580_1 is modified to extend the validity checks.

src/BOPAlgo/BOPAlgo_BuilderFace.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx
tests/boolean/volumemaker/A8
tests/bugs/modalg_1/buc60703_1
tests/bugs/modalg_1/buc60703_2
tests/bugs/modalg_1/buc60703_4
tests/bugs/modalg_6/bug26789_1
tests/bugs/modalg_6/bug26789_2
tests/bugs/modalg_7/bug26883_4
tests/bugs/modalg_7/bug27948
tests/bugs/modalg_7/bug29580_1

index 9d4007a0eb635a040857ae9fbe24bb992471a3ad..2caa3ff56429fece39fab473442cbfc829151b14 100644 (file)
@@ -708,45 +708,53 @@ void MakeInternalWires(const TopTools_IndexedMapOfShape& theME,
 //function : IsInside
 //purpose  : 
 //=======================================================================
-Standard_Boolean IsInside(const TopoDS_Shape& theHole,
-                          const TopoDS_Shape& theF2,
+Standard_Boolean IsInside(const TopoDS_Shape& theWire,
+                          const TopoDS_Shape& theF,
                           Handle(IntTools_Context)& theContext)
 {
-  Standard_Boolean bRet;
-  Standard_Real aT, aU, aV;
-  
-  TopAbs_State aState;
-  TopExp_Explorer aExp;
-  TopTools_IndexedMapOfShape aME2;
-  gp_Pnt2d aP2D;
-  //
-  bRet=Standard_False;
-  aState=TopAbs_UNKNOWN;
-  const TopoDS_Face& aF2=(*(TopoDS_Face *)(&theF2));
-  //
-  TopExp::MapShapes(aF2, TopAbs_EDGE, aME2);//AA
-  //
-  aExp.Init(theHole, TopAbs_EDGE);
-  if (aExp.More()) {
-    const TopoDS_Edge& aE =(*(TopoDS_Edge *)(&aExp.Current()));
-    if (aME2.Contains(aE)) {
-      return bRet;
-    }
-    if (!BRep_Tool::Degenerated(aE)) {
-      //
-      aT=BOPTools_AlgoTools2D::IntermediatePoint(aE);
-      BOPTools_AlgoTools2D::PointOnSurface(aE, aF2, aT, aU, aV, theContext);
-      aP2D.SetCoord(aU, aV);
-      //
-      IntTools_FClass2d& aClsf=theContext->FClass2d(aF2);
-      aState=aClsf.Perform(aP2D);
-      bRet=(aState==TopAbs_IN);
-    }
+  // Check if the wire is located inside the face:
+  // take unique point from the wire and classify it relatively the face
+
+  // Avoid edges of the face
+  TopTools_IndexedMapOfShape aFaceEdgesMap;
+  TopExp::MapShapes(theF, TopAbs_EDGE, aFaceEdgesMap);
+
+  // Get classification tool from the context
+  const TopoDS_Face& aF = TopoDS::Face(theF);
+  IntTools_FClass2d& aClassifier = theContext->FClass2d(aF);
+
+  Standard_Boolean isInside = Standard_False;
+
+  // Iterate on wire edges until first classification is performed
+  TopExp_Explorer anExp(theWire, TopAbs_EDGE);
+  for (; anExp.More(); anExp.Next())
+  {
+    const TopoDS_Edge& aE = TopoDS::Edge(anExp.Current());
+    if (BRep_Tool::Degenerated(aE))
+      // Avoid checking degenerated edges.
+      continue;
+
+    if (aFaceEdgesMap.Contains(aE))
+      // Face contains the edge from the wire, thus the wire cannot be
+      // inside that face.
+      return isInside;
+
+    // Get 2d curve of the edge on the face
+    Standard_Real aT1, aT2;
+    const Handle(Geom2d_Curve)& aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
+    if (aC2D.IsNull())
+      continue;
+
+    // Get middle point on the curve
+    gp_Pnt2d aP2D = aC2D->Value((aT1 + aT2) / 2.);
+
+    // Classify the point
+    TopAbs_State aState = aClassifier.Perform(aP2D);
+    isInside = (aState == TopAbs_IN);
+    break;
   }
-  //
-  return bRet;
+  return isInside;
 }
-
 //=======================================================================
 //function : IsGrowthWire
 //purpose  : 
index 40e2b417de8261de7388c88ea7d198dc5a6a2887..cd04b75d38f081e6cd1018142c71def6aed3fc00 100644 (file)
@@ -803,8 +803,8 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
   Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
 
   // Initialize pave blocks for all SD vertices
-  Standard_Integer i, aNbS = myDS->NbSourceShapes();
-  for (i = 0; i < aNbS; ++i)
+  const Standard_Integer aNbS = myDS->NbSourceShapes();
+  for (Standard_Integer i = 0; i < aNbS; ++i)
   {
     const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
     if (aSI.ShapeType() == TopAbs_VERTEX)
@@ -822,11 +822,22 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
   // Fence map of pave blocks
   BOPDS_MapOfPaveBlock aMPBFence(1, anAlloc);
 
-  BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
-  Standard_Integer aNbPBP = aPBP.Length();
-  for (i = 0; i < aNbPBP; ++i)
+  for (Standard_Integer i = 0; i < aNbS; ++i)
   {
-    BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
+    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
+    if (aSI.ShapeType() != TopAbs_EDGE)
+      // Not an edge
+      continue;
+
+    if (!aSI.HasReference())
+      // Edge has no pave blocks
+      continue;
+
+    if (aSI.HasFlag())
+      // Degenerated edge
+      continue;
+
+    const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks(i);
     BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
     for (; aItLPB.More(); aItLPB.Next())
     {
@@ -852,23 +863,11 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
   if (!aNbPB)
     return;
 
-  // Find pairs of Pave Blocks having the same SD vertices,
-  // rejecting the pairs of edges that have already been intersected
-
-  // Prepare map of pairs of intersected edges
-  BOPDS_MapOfPair aMEEDone(1, anAlloc);
-  myIterator->Initialize(TopAbs_EDGE, TopAbs_EDGE);
-  for (; myIterator->More(); myIterator->Next())
-  {
-    Standard_Integer nE1, nE2;
-    myIterator->Value(nE1, nE2);
-    aMEEDone.Add(BOPDS_Pair(nE1, nE2));
-  }
-
-  // Vector of pairs for intersection
+  // Find pairs of Pave Blocks having the same SD vertices
+  // and put them into the vector for parallel intersection.
   BOPAlgo_VectorOfEdgeEdge aVEdgeEdge;
 
-  for (i = 1; i <= aNbPB; ++i)
+  for (Standard_Integer i = 1; i <= aNbPB; ++i)
   {
     const BOPDS_ListOfPaveBlock& aLPB = aPBMap(i);
     if (aLPB.Extent() < 2)
@@ -891,6 +890,7 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
     for (; aItLPB1.More(); aItLPB1.Next())
     {
       const Handle(BOPDS_PaveBlock)& aPB1 = aItLPB1.Value();
+      const Handle(BOPDS_CommonBlock)& aCB1 = myDS->CommonBlock(aPB1);
       const Standard_Integer nE1 = aPB1->OriginalEdge();
       const TopoDS_Edge& aE1 = TopoDS::Edge(myDS->Shape(nE1));
       Standard_Real aT11, aT12;
@@ -900,15 +900,20 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
       for (aItLPB2.Next(); aItLPB2.More(); aItLPB2.Next())
       {
         const Handle(BOPDS_PaveBlock)& aPB2 = aItLPB2.Value();
+        const Handle(BOPDS_CommonBlock)& aCB2 = myDS->CommonBlock(aPB2);
         const Standard_Integer nE2 = aPB2->OriginalEdge();
 
-        if (aMEEDone.Contains(BOPDS_Pair(nE1, nE2)))
-          continue;
-
         // Make sure that the edges came from different arguments
         if (myDS->Rank(nE1) == myDS->Rank(nE2))
           continue;
 
+        // Check that the Pave blocks do not form the Common block already
+        if (!aCB1.IsNull() && !aCB2.IsNull())
+        {
+          if (aCB1 == aCB2)
+            continue;
+        }
+
         const TopoDS_Edge& aE2 = TopoDS::Edge(myDS->Shape(nE2));
         Standard_Real aT21, aT22;
         aPB2->Range(aT21, aT22);
@@ -932,7 +937,6 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
 
   aPBMap.Clear();
   aMPBFence.Clear();
-  aMEEDone.Clear();
   anAlloc->Reset();
 
   // Perform intersection of the found pairs
@@ -947,7 +951,7 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
 
   BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock aMPBLPB(1, anAlloc);
 
-  for (i = 0; i < aNbPairs; ++i)
+  for (Standard_Integer i = 0; i < aNbPairs; ++i)
   {
     BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge(i);
     if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors())
index 09609a760185b75e476e3c202da92188e2082265..569d14bd5af4cb7713db304e440f66b0f2cf7d03 100644 (file)
@@ -1,8 +1,5 @@
 # test script on make volume operation
 # plane sphere
-puts "TODO OCC26020 ALL: Faulty shapes in variables faulty_1 to faulty_"
-puts "TODO OCC26020 ALL: Error: bopcheck failed"
-puts "TODO OCC26020 ALL: Error : The area of result shape is"
 
 # planar face 
 plane pln_f1 -4.2580937183769834 -506.18339008981781 147.62942729477928 0.98768834059988952 -6.6728564553435301e-012 -0.15643446501022945
@@ -42,5 +39,5 @@ mkface f7 sph_f7
 # make volume operation 
 mkvolume result f1 f2 f3 f4 f5 f6 f7
 
-checkprops result -s 2.19944e+013
-
+checkprops result -s 1.75676e+007
+checknbshapes result -wire 68 -face 68 -shell 24 -solid 24
index b56fbc35e1ec87577ba9dea3b586e0ccbdc05dc4..3c87dc0c7ce5b60a1ac69a123ece53aa963b0713 100755 (executable)
@@ -1,7 +1,3 @@
-#puts "TODO OCC12345 ALL: An exception was caught"
-#puts "TODO OCC12345 ALL: \\*\\* Exception"
-#puts "TODO OCC12345 ALL: Faulty  BUC60703: here is problem with FUSE operation"
-
 puts "========================"
 puts "BUC60703"
 puts "================================="
@@ -21,17 +17,10 @@ restore [locate_data_file buc60703b.brep] b
 # maxtolerance b
 checkshape b
 
-if [catch {bfuse result a b } catch_result] {
-    puts "Faulty  BUC60703: here is problem with FUSE operation"
-} else {
-    puts "OK OCC348: function FUSE works ok"
-    if [catch {checkshape result } catch_result] {
-       puts "Faulty BUC60703 : here is checking problem."
-    } else {
-       puts "BUC60703  OK"
-    }
-    #  maxtolerance res
-    checkprops result -s 237.333 
-    checkview -display result -2d -path ${imagedir}/${test_image}.png
-}
+bfuse result a b
+
+checkshape result
+checkprops result -s 173.109 -v 129.814
+checknbshapes result -wire 10 -face 10 -shell 1 -solid 1
 
+checkview -display result -2d -path ${imagedir}/${test_image}.png
index efa4c43ac34d6d2cecd1024a3ab8eaea6c84cdb9..7c629b1b5e6571b402c4941b111cb493c11e445a 100755 (executable)
@@ -1,4 +1,3 @@
-
 puts "========================"
 puts "BUC60703"
 puts "================================="
@@ -10,22 +9,12 @@ puts ""
 ############################################
 
 restore [locate_data_file buc60703c.brep] a 
-checkshape a
-
 restore [locate_data_file buc60703e.brep] b
-checkshape b
 
+bfuse result a b
+
+checkshape result
+checkprops result -s 172.662 -v 129.604
+checknbshapes result -wire 10 -face 10 -shell 1 -solid 1
 
-if [catch {bfuse result a b } catch_result] {
-    puts "Faulty  BUC60703: here is problem with FUSE operation"
-} else {
-    puts "OK BUC60703: function FUSE works ok"         
-    if [catch {checkshape result } catch_result] {
-       puts "WARNING BUC60703 : Function checkshape gives bad result"
-       puts " See also OCC438: 919 D3 and D4"
-    } else {
-       puts "BUC60703  OK in checkshape"
-    }  
-}
-checkprops result -s 236.72 
 checkview -display result -2d -path ${imagedir}/${test_image}.png
index 1ac877057258f4db1d26407a105dc856027bf553..06115f6530bbccca523bb7b3fa1aee3fdac29ffe 100755 (executable)
@@ -1,4 +1,3 @@
-
 puts "========================"
 puts "BUC60703"
 puts "========================"
@@ -8,28 +7,12 @@ puts ""
 ####################################
 
 restore [locate_data_file buc60703d.brep] a 
-#maxtolerance a
-checkshape a
 restore [locate_data_file buc60703f.brep] b
-#maxtolerance b
-checkshape b
 
-if [catch {bfuse result a b } catch_result] {
-    puts "Faulty  BUC60703: here is problem with FUSE operation"
-} else {
-    puts "OK OCC348: function FUSE works ok"
-    if [catch {checkshape result} catch_result] {
-       set mistake 1
-    } else {
-       set mistake 0
-    }
+bfuse result a b
 
-    if { $mistake != 0} {
-       puts "Faulty BUC60703 : here is checking problem. See also OCC438: 919 D3 and D4"
-    } else {
-       puts "BUC60703   : here is NOT checking problem"
-    }
-}
-checkprops result -s 505.797 
-checkview -display result -2d -path ${imagedir}/${test_image}.png
+checkshape result
+checkprops result -s 322.013 -v 375.942
+checknbshapes result -wire 6 -face 4 -shell 1 -solid 1
 
+checkview -display result -2d -path ${imagedir}/${test_image}.png
index c1bb6f2b380d1ac7672741d3f7ff9cd281082dfe..2b45fb6fa3f6215afc3f9cf1aeb301cf4d9cf5b8 100644 (file)
@@ -1,7 +1,3 @@
-puts "TODO 0026789 ALL: Error : The area of result shape is"
-puts "TODO 0026789 ALL: Error : The volume of result shape is"
-puts "TODO 0026789 ALL: Error :  is WRONG because number of"
-
 puts "========"
 puts "OCC26789"
 puts "========"
@@ -21,7 +17,7 @@ bfillds
 bbop result 1
 
 checkshape result
-checknbshapes result -solid 1 -shell 2
+checknbshapes result -wire 20 -face 20 -solid 1 -shell 2
 checkprops result -s 3583.27 -v 11455.2
 
 checkview -display result -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file
index 9624d93de3663185d72bf36cbdf394b5ad9dfb21..b53d4eb7323ede2bc538db24566e5cd2bb73bc98 100644 (file)
@@ -19,7 +19,7 @@ bfillds
 bbop result 1
 
 checkshape result
-checknbshapes result -solid 1 -shell 2
+checknbshapes result -wire 20 -face 20 -solid 1 -shell 2
 checkprops result -s 3583.27 -v 11455.2
 
 checkview -display result -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file
index 77f697975d9929288263132a1b9ead46dc927b4b..0365023b6f18bce710153408f1689fcca5761ea6 100644 (file)
@@ -1,6 +1,3 @@
-puts "TODO OCC26883 ALL: Faulty shapes in variables faulty_1 to"
-puts "TODO OCC26883 ALL: Error :  is WRONG because number of SOLID entities in shape"
-
 puts "========"
 puts "OCC26883"
 puts "========"
@@ -21,7 +18,7 @@ bfillds
 bbop result 1
 
 checkshape result
-
-checknbshapes result -solid 1
+checkprops result -s 2116.44 -v 607.276
+checknbshapes result -wire 39 -face 32 -shell 3 -solid 1
 
 checkview -display result -2d -path ${imagedir}/${test_image}.png
index 9f5ebd5ecf38190be05ec8db82910a0c1da884e8..e1d229542409bf0aba7671c847a106d54e314621 100644 (file)
@@ -1,5 +1,3 @@
-puts "TODO OCC27948 ALL: ERROR: OCC27948 is reproduced."
-
 puts "========"
 puts "OCC27948"
 puts "========"
@@ -11,18 +9,10 @@ puts ""
 restore [locate_data_file bug27948_a.brep] a
 restore [locate_data_file bug27948_b.brep] b
 
-bcut res a b
-explode res F
-
-vinit
-vdisplay res
-vfit
-vdisplay res_16
-vsetdispmode res_16 1
+bcut result a b
 
-set bug_info [string trim [vreadpixel 340 280 name]]
-if {$bug_info == "DARKGOLDENROD3 1"} {
-  puts "ERROR: OCC27948 is reproduced."
-}
+checkshape result
+checkprops result -s 135.137 -v 40.573
+checknbshapes result -wire 19 -face 17 -shell 1 -solid 1
 
-checkview -screenshot -3d -path ${imagedir}/${test_image}.png
+checkview -display result -2d -path ${imagedir}/${test_image}.png
index 5592ec77f6f1f380b8b9f93efe0360e9ec955fc0..260b75ebc24879076cf00d5abf83a97f38b0dad3 100644 (file)
@@ -11,8 +11,17 @@ restore [locate_data_file bug29580_Solid.brep] b2
 
 bfuse result b1 b2
 
+foreach f [explode result f] {
+  explode $f w
+  foreach w [explode $f w] {
+    if {[regexp "A self-intersecting wire" [checkselfintersection $w $f]]} {
+      puts "Error: BOP produces a face with self-intersecting wire"
+    }
+  }
+}
+
 checkshape result
-checknbshapes result -wire 14 -face 13 -shell 1 -solid 1
-checkprops result -s 865.851 -v 1622.19
+checknbshapes result -wire 11 -face 10 -shell 1 -solid 1
+checkprops result -s 865.851 -v 1622.17
 
 checkview -display result -2d -path ${imagedir}/${test_image}.png