0031462: Modeling Algorithms - BOP result depends on the arguments order IR-2020-04-04
authoremv <emv@opencascade.com>
Mon, 30 Mar 2020 13:33:53 +0000 (16:33 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 1 Apr 2020 17:44:23 +0000 (20:44 +0300)
Eliminate numerical instability by ensuring that the tolerance of intersection entities is slightly grater than the actual distance to the shapes creating the entity.

src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx
src/BOPTools/BOPTools_AlgoTools.cxx
src/BOPTools/BOPTools_AlgoTools.hxx
src/BOPTools/BOPTools_AlgoTools_1.cxx
src/BOPTools/BOPTools_AlgoTools_2.cxx
tests/bugs/modalg_7/bug31462 [new file with mode: 0644]
tests/evolved/voluved/HMC008

index 13ec495..1c9975a 100644 (file)
@@ -225,6 +225,14 @@ void BOPAlgo_PaveFiller::IntersectVE
     const Handle(BOPDS_PaveBlock)& aPB = theVEPairs.FindKey(i);
     Standard_Integer nE = aPB->OriginalEdge();
     //
+    TColStd_MapOfInteger aMVPB;
+    const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks (nE);
+    for (BOPDS_ListOfPaveBlock::Iterator itPB (aLPB); itPB.More(); itPB.Next())
+    {
+      aMVPB.Add (itPB.Value()->Pave1().Index());
+      aMVPB.Add (itPB.Value()->Pave2().Index());
+    }
+
     const TColStd_ListOfInteger& aLV = theVEPairs(i);
     TColStd_ListIteratorOfListOfInteger aItLV(aLV);
     for (; aItLV.More(); aItLV.Next()) {
@@ -233,6 +241,9 @@ void BOPAlgo_PaveFiller::IntersectVE
       Standard_Integer nVSD = nV;
       myDS->HasShapeSD(nV, nVSD);
       //
+      if (aMVPB.Contains (nVSD))
+        continue;
+
       BOPDS_Pair aPair(nVSD, nE);
       TColStd_ListOfInteger* pLI = aDMVSD.ChangeSeek(aPair);
       if (pLI) {
@@ -287,7 +298,21 @@ void BOPAlgo_PaveFiller::IntersectVE
     Standard_Integer nVx = UpdateVertex(nV, aTolVNew);
     // 2. Create new pave and add it as extra pave to pave block
     //    for further splitting of the edge
-    const Handle(BOPDS_PaveBlock)& aPB = aVESolver.PaveBlock();
+    const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks (nE);
+    // Find the appropriate one
+    Handle(BOPDS_PaveBlock) aPB;
+    BOPDS_ListOfPaveBlock::Iterator itPB (aLPB);
+    for (; itPB.More(); itPB.Next())
+    {
+      aPB = itPB.Value();
+      Standard_Real aT1, aT2;
+      aPB->Range (aT1, aT2);
+      if (aT > aT1 && aT < aT2)
+        break;
+    }
+    if (!itPB.More())
+      continue;
+
     BOPDS_Pave aPave;
     aPave.SetIndex(nVx);
     aPave.SetParameter(aT);
index 5dc2772..044bbc8 100644 (file)
@@ -2414,7 +2414,7 @@ void BOPAlgo_PaveFiller::PutPaveOnCurve
     Standard_Integer nVUsed;
     Standard_Real aPTol, aDTol;
     //
-    aDTol = 1.e-12;
+    aDTol = BOPTools_AlgoTools::DTolerance();
     //
     GeomAdaptor_Curve aGAC(aIC.Curve());
     aPTol = aGAC.Resolution(Max(aTolR3D, aTolV));
@@ -2459,7 +2459,8 @@ void BOPAlgo_PaveFiller::PutPaveOnCurve
       aTolV = BRep_Tool::Tolerance(aV);
       gp_Pnt aP2 = BRep_Tool::Pnt(aV);
       Standard_Real aDist = aP1.Distance(aP2);
-      if (aDist > aTolV) {
+      if (aTolV < aDist + aDTol)
+      {
         BRep_Builder().UpdateVertex(aV, aDist + aDTol);
         //
         if (!aMVTol.IsBound(nV)) {
@@ -2831,7 +2832,7 @@ void BOPAlgo_PaveFiller::PutClosingPaveOnCurve(BOPDS_Curve& aNC)
 
   if (aDistVP > aTolV)
   {
-    Standard_Integer nVn = UpdateVertex(nV, aDistVP);
+    Standard_Integer nVn = UpdateVertex(nV, aDistVP + BOPTools_AlgoTools::DTolerance());
     if (nVn != nV)
     {
       aPave.SetIndex(nVn);
index dbbb975..0b299ee 100644 (file)
@@ -784,7 +784,7 @@ void UpdateVertices(const TopoDS_Edge& aE,
     aD2=aP3D.SquareDistance(aP3Dx);
     if (aD2>aTolV2) {
       aD=sqrt(aD2);
-      aBB.UpdateVertex(aV[j], aD);
+      aBB.UpdateVertex(aV[j], aD + BOPTools_AlgoTools::DTolerance());
     }
   }
 }
index a2724df..3a037f4 100644 (file)
@@ -1636,7 +1636,7 @@ void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
                                   TopoDS_Edge& theE)
 {
   BRep_Builder aBB;
-  Standard_Real aNeedTol = theTolR3D + 1e-12;
+  Standard_Real aNeedTol = theTolR3D + BOPTools_AlgoTools::DTolerance();
   //
   aBB.UpdateVertex(theV1, aNeedTol);
   aBB.UpdateVertex(theV2, aNeedTol);
index 77ad5e9..4b83f42 100644 (file)
@@ -61,6 +61,15 @@ public:
 
   DEFINE_STANDARD_ALLOC
 
+public: //! @name Constants
+
+  //! Additional tolerance (delta tolerance) is used in Boolean Operations
+  //! to ensure that the tolerance of new/old entities obtained
+  //! by intersection of two shapes is slightly bigger than the actual
+  //! distances to these shapes. It helps to avoid numerical instability
+  //! which may occur when comparing distances and tolerances.
+  static Standard_Real DTolerance() { return 1.e-12; }
+
 public: //! @name Intersection of the vertices
 
   //! Intersects the vertex <theV1> with the point <theP> with tolerance <theTolP>.
index 6b92221..78e1a5e 100644 (file)
@@ -823,7 +823,7 @@ void CorrectEdgeTolerance (const TopoDS_Edge& myShape,
     Standard_Boolean SameRange = TE->SameRange();
     Standard_Real First = myHCurve->FirstParameter();
     Standard_Real Last  = myHCurve->LastParameter();
-    Standard_Real Delta =1.e-12;
+    Standard_Real Delta = BOPTools_AlgoTools::DTolerance();
 
     Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &S.TShape());
     const TopLoc_Location& Floc = S.Location();
index 4fd77e5..d1b3063 100644 (file)
@@ -42,7 +42,7 @@ void BOPTools_AlgoTools::UpdateVertex
   (const TopoDS_Vertex& aVF,
    const TopoDS_Vertex& aNewVertex)
 {
-  Standard_Real aTolVF, aTolNewVertex, aDist, aDTol=1.e-12, aNewTol;
+  Standard_Real aTolVF, aTolNewVertex, aDist, aNewTol;
   //
   gp_Pnt aPVF=BRep_Tool::Pnt(aVF);
   gp_Pnt aPNewVertex=BRep_Tool::Pnt(aNewVertex);
@@ -54,7 +54,7 @@ void BOPTools_AlgoTools::UpdateVertex
 
   if (aNewTol>aTolVF) {
     BRep_Builder BB;
-    BB.UpdateVertex (aVF, aNewTol+aDTol);
+    BB.UpdateVertex (aVF, aNewTol + BOPTools_AlgoTools::DTolerance());
   }
 }
 
@@ -66,7 +66,7 @@ void BOPTools_AlgoTools::UpdateVertex (const TopoDS_Edge& aE,
                                        const Standard_Real  aT,
                                        const TopoDS_Vertex& aV)
 {
-  Standard_Real aTolV, aDist, aDTol=1.e-12, aFirst, aLast;
+  Standard_Real aTolV, aDist, aFirst, aLast;
   gp_Pnt  aPc; 
 
   gp_Pnt aPv=BRep_Tool::Pnt(aV);
@@ -77,7 +77,7 @@ void BOPTools_AlgoTools::UpdateVertex (const TopoDS_Edge& aE,
   aDist=aPv.Distance(aPc);
   if (aDist>aTolV) {
     BRep_Builder BB;
-    BB.UpdateVertex (aV, aDist+aDTol);
+    BB.UpdateVertex (aV, aDist + BOPTools_AlgoTools::DTolerance());
   }
 }
 //
@@ -89,7 +89,7 @@ void BOPTools_AlgoTools::UpdateVertex (const IntTools_Curve& aC,
                                        const Standard_Real  aT,
                                        const TopoDS_Vertex& aV)
 {
-  Standard_Real aTolV, aDist, aDTol=1.e-12;
+  Standard_Real aTolV, aDist;
   gp_Pnt  aPc; 
 
   gp_Pnt aPv=BRep_Tool::Pnt(aV);
@@ -100,7 +100,7 @@ void BOPTools_AlgoTools::UpdateVertex (const IntTools_Curve& aC,
   aDist=aPv.Distance(aPc);
   if (aDist>aTolV) {
     BRep_Builder BB;
-    BB.UpdateVertex (aV, aDist+aDTol);
+    BB.UpdateVertex (aV, aDist + BOPTools_AlgoTools::DTolerance());
   }
 }
 //=======================================================================
@@ -265,7 +265,7 @@ void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Edge& aE1,
                                        const TopoDS_Face& aF1,
                                        TopoDS_Vertex& aNewVertex)
 {
-  Standard_Real aTol1, aTol2, aMaxTol, delta=1.e-12; 
+  Standard_Real aTol1, aTol2, aMaxTol;
   gp_Pnt aPnt;
 
   PointOnEdge (aE1, aParm1, aPnt);
@@ -273,8 +273,7 @@ void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Edge& aE1,
   aTol1=BRep_Tool::Tolerance(aE1);
   aTol2=BRep_Tool::Tolerance(aF1);
   //
-  //aMaxTol=(aTol1>aTol2)? aTol1 : aTol2;
-  aMaxTol=aTol1+aTol2+delta;
+  aMaxTol = aTol1 + aTol2 + BOPTools_AlgoTools::DTolerance();
   //
   BRep_Builder aBB;
   aBB.MakeVertex (aNewVertex, aPnt, aMaxTol);
diff --git a/tests/bugs/modalg_7/bug31462 b/tests/bugs/modalg_7/bug31462
new file mode 100644 (file)
index 0000000..5588be6
--- /dev/null
@@ -0,0 +1,44 @@
+puts "========"
+puts "0031462: Modeling Algorithms - BOP result depends on the arguments order"
+puts "========"
+puts ""
+
+restore [locate_data_file bug31462_obj.brep] s1
+restore [locate_data_file bug31462_tools.brep] s2
+
+tcopy s1 obj
+tcopy s2 sx
+bclearobjects
+bcleartools
+baddobjects obj
+eval baddtools [explode sx]
+bfillds
+bsplit result1
+
+checkshape result1
+if {![regexp "This shape seems to be OK" [bopcheck result1]]} {
+  puts "Error: self-interfering result"
+}
+
+checknbshapes result1 -wire 19 -face 18 -shell 3 -solid 2
+checkprops result1 -s 103.955 -v 38.7982
+
+tcopy s1 obj
+tcopy s2 sx
+bclearobjects
+bcleartools
+baddobjects obj
+explode sx
+baddtools sx_4 sx_5 sx_6 sx_3 sx_2 sx_1
+bfillds
+bsplit result2
+
+checkshape result2
+if {![regexp "This shape seems to be OK" [bopcheck result2]]} {
+  puts "Error: self-interfering result"
+}
+
+checknbshapes result2 -ref [nbshapes result1]
+checkprops result2 -equal result1
+
+checkview -display result1 -2d -path ${imagedir}/${test_image}.png
index aa0f698..63c57b5 100644 (file)
@@ -4,13 +4,6 @@ puts "=========="
 
 cpulimit 100
 
-puts "TODO OCC30438 ALL: Error : The area of result shape is"
-puts "TODO OCC30438 ALL: Error : The volume of result shape is"
-puts "TODO OCC30438 ALL: Error :  is WRONG because number of SHELL"
-puts "TODO OCC30438 ALL: Error :  is WRONG because number of SOLID"
-puts "TODO OCC30438 ALL: Error: bopargcheck has found some faulties in result"
-
-
 restore [locate_data_file bug29523_cut_extrudewire07.brep] sw 
 restore [locate_data_file bug29523_cut_toolwire07.brep] tw
 
@@ -219,7 +212,7 @@ if {[regexp "Faulties" [bopargcheck result]]} {
 # the dimensions of the shape "result" are about 1.0e+5.
 # So, this tolerance seems to be OK.
 
-checkmaxtol result -ref 18.634531507134731
+checkmaxtol result -ref 1.7319951447770465
 
 smallview
 don result sw tw