0027804: Two breps cause intersections to loop for too long/infinitely
authormsv <msv@opencascade.com>
Fri, 26 Aug 2016 14:33:46 +0000 (17:33 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 8 Sep 2016 08:22:40 +0000 (11:22 +0300)
In ProjLib_ComputeApprox algorithm, compute correct parametric tolerance from the input 3D tolerance using surface resolution, in order to pass it to low-level 2D algorithm Approx_FitAndDivide2d (instantiation of the generic class Approx_ComputeCLine). Earlier 3D tolerance was used as parametric tolerance directly, which was a problem for surfaces with too small radius of curvature.

Also, eliminate redundant creation of the object of type AppParCurves_MultiCurve on each iteration in the method Approx_ComputeCLine::Compute.

The post treatment of the Edge/Edge intersections has been improved. Namely:
a. Making the procedure of sharing Edge/Edge intersection vertices consistent with intersection algorithm by enlarging bounding box of each vertex on half of Precision::Confusion();
b. Algorithm of computation of vertex tolerance (in order to cover tangent zone between Edges) has been changed for Line/Circle cases.

Test cases for issue CR27804
Adjusting test cases according to their new behavior.

Mark the test boolean/volumemaker/A8 as unstable between different versions of MSVS (2010 and 2013).

src/Approx/Approx_ComputeCLine.gxx
src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx
src/ProjLib/ProjLib_ComputeApprox.cxx
tests/boolean/volumemaker/A8
tests/bugs/moddata_3/bug27804_1 [new file with mode: 0644]
tests/bugs/moddata_3/bug27804_2 [new file with mode: 0644]

index e41e346..f2fc63c 100644 (file)
@@ -228,16 +228,14 @@ Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
 
   for (deg = mydegremin; deg <= mydegremax; deg++) {
 
-    AppParCurves_MultiCurve mySCU(deg+1);
     AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints);
     mydone = LSquare.IsDone();
     if (mydone) {
       LSquare.Error(Fv, TheTol3d, TheTol2d);
       if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
-       mySCU = LSquare.Value();
        // Stockage de la multicurve approximee.
        tolreached = Standard_True;
-       myMultiCurves.Append(mySCU);
+        myMultiCurves.Append(LSquare.Value());
        myfirstparam.Append(Ufirst);
        mylastparam.Append(Ulast);
        Tolers3d.Append(TheTol3d);
index 593b4cd..9940d80 100644 (file)
@@ -412,15 +412,22 @@ void BOPAlgo_PaveFiller::PerformEE()
     const IntTools_SequenceOfCommonPrts& aCPrts = anEdgeEdge.CommonParts();
     aNbCPrts = aCPrts.Length();
     //
-    Standard_Boolean bLineLine = Standard_False;
+    Standard_Boolean bAnalytical = Standard_False;
     if (aNbCPrts) {
       const TopoDS_Edge& aOE1 = *(TopoDS_Edge*)&myDS->Shape(nE1);
       const TopoDS_Edge& aOE2 = *(TopoDS_Edge*)&myDS->Shape(nE2);
       //
       BRepAdaptor_Curve aBAC1(aOE1), aBAC2(aOE2);
       //
-      bLineLine = (aBAC1.GetType() == GeomAbs_Line &&
-                   aBAC2.GetType() == GeomAbs_Line);
+      GeomAbs_CurveType aType1 = aBAC1.GetType();
+      GeomAbs_CurveType aType2 = aBAC2.GetType();
+      //
+      bAnalytical = (((aType1 == GeomAbs_Line) &&
+                      (aType2 == GeomAbs_Line ||
+                       aType2 == GeomAbs_Circle)) ||
+                     ((aType2 == GeomAbs_Line) &&
+                      (aType1 == GeomAbs_Line ||
+                       aType1 == GeomAbs_Circle)));
     }
     //
     for (i=1; i<=aNbCPrts; ++i) {
@@ -483,10 +490,11 @@ void BOPAlgo_PaveFiller::PerformEE()
           //
           BOPTools_AlgoTools::MakeNewVertex(aE1, aT1, aE2, aT2, aVnew);
           Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
-          if (bLineLine) {
+          if (bAnalytical) {
             // increase tolerance for Line/Line intersection, but do not update 
             // the vertex till its intersection with some other shape
-            Standard_Real aTolMin = (aCR1.Last() - aCR1.First()) / 2.;
+            Standard_Real aTolMin = (BRepAdaptor_Curve(aE1).GetType() == GeomAbs_Line) ?
+              (aCR1.Last() - aCR1.First()) / 2. : (aCR2.Last() - aCR2.First()) / 2.;
             if (aTolMin > aTolVnew) {
               aTolVnew = aTolMin;
             }
@@ -780,6 +788,7 @@ void BOPAlgo_PaveFiller::TreatNewVertices
                             Bnd_Box> aTreeFiller(aBBTree);
   BOPAlgo_VectorOfTNV aVTNV;
   //
+  Standard_Real aTolAdd = Precision::Confusion() / 2.;
   aNbV = theMVCPB.Extent();
   for (i=1; i<=aNbV; ++i) {
     const TopoDS_Vertex& aV = *((TopoDS_Vertex*)&theMVCPB.FindKey(i));
@@ -787,7 +796,7 @@ void BOPAlgo_PaveFiller::TreatNewVertices
     //
     aTol = theMVCPB.FindFromIndex(i).Tolerance();
     aBox.Add(BRep_Tool::Pnt(aV));
-    aBox.SetGap(aTol);
+    aBox.SetGap(aTol + aTolAdd);
     //
     aTreeFiller.Add(i, aBox);
     //
index 75966fe..b93d337 100644 (file)
@@ -894,6 +894,40 @@ class ProjLib_Function : public AppCont_Function
 };
 
 //=======================================================================
+//function : ComputeTolU
+//purpose  : 
+//=======================================================================
+
+static Standard_Real ComputeTolU(const Handle(Adaptor3d_HSurface)& theSurf,
+                                 const Standard_Real theTolerance)
+{
+  Standard_Real aTolU = theSurf->UResolution(theTolerance);
+  if (theSurf->IsUPeriodic())
+  {
+    aTolU = Min(aTolU, 0.01*theSurf->UPeriod());
+  }
+
+  return aTolU;
+}
+
+//=======================================================================
+//function : ComputeTolV
+//purpose  : 
+//=======================================================================
+
+static Standard_Real ComputeTolV(const Handle(Adaptor3d_HSurface)& theSurf,
+                                 const Standard_Real theTolerance)
+{
+  Standard_Real aTolV = theSurf->VResolution(theTolerance);
+  if (theSurf->IsVPeriodic())
+  {
+    aTolV = Min(aTolV, 0.01*theSurf->VPeriod());
+  }
+
+  return aTolV;
+}
+
+//=======================================================================
 //function : ProjLib_ComputeApprox
 //purpose  : 
 //=======================================================================
@@ -1031,8 +1065,13 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
       Deg2 = 12; 
     }
 //-------------
-    Approx_FitAndDivide2d Fit(F,Deg1,Deg2,myTolerance,myTolerance,
-                             Standard_True);
+    const Standard_Real aTolU = ComputeTolU(S, myTolerance);
+    const Standard_Real aTolV = ComputeTolV(S, myTolerance);
+    const Standard_Real aTol2d = Max(Sqrt(aTolU*aTolU + aTolV*aTolV), Precision::PConfusion());
+
+    Approx_FitAndDivide2d Fit(F, Deg1, Deg2, myTolerance, aTol2d, Standard_True);
+
+    Standard_Real aNewTol2d = 0;
     if(Fit.IsAllApproximated()) {
       Standard_Integer i;
       Standard_Integer NbCurves = Fit.NbMultiCurves();
@@ -1040,11 +1079,10 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
     // on essaie de rendre la courbe au moins C1
       Convert_CompBezierCurves2dToBSplineCurve2d Conv;
 
-      myTolerance = 0;
       Standard_Real Tol3d,Tol2d;
       for (i = 1; i <= NbCurves; i++) {
              Fit.Error(i,Tol3d, Tol2d);
-             myTolerance = Max(myTolerance, Tol2d);
+              aNewTol2d = Max(aNewTol2d, Tol2d);
              AppParCurves_MultiCurve MC = Fit.Value( i);       //Charge la Ieme Curve
              TColgp_Array1OfPnt2d Poles2d( 1, MC.Degree() + 1);//Recupere les poles
              MC.Curve(1, Poles2d);
@@ -1095,10 +1133,19 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
       if(NbCurves != 0) {
              Standard_Real Tol3d,Tol2d;
              Fit.Error(NbCurves,Tol3d, Tol2d);
-             myTolerance = Tol2d;
+              aNewTol2d = Tol2d;
       }
     }
 
+    // restore tolerance 3d from 2d
+
+    //Here we consider that 
+    //   aTolU(new)/aTolV(new) = aTolU(old)/aTolV(old)
+    //(it is assumption indeed).
+    //Then,
+    //  Tol3D(new)/Tol3D(old) = Tol2D(new)/Tol2D(old).
+    myTolerance *= (aNewTol2d / aTol2d);
+
     //Return curve home
     Standard_Real UFirst = F.FirstParameter();
     gp_Pnt P3d = C->Value( UFirst );
index 1add28e..e7477a8 100644 (file)
@@ -1,7 +1,7 @@
 # test script on make volume operation
 # plane sphere
 
-puts "TODO OCC26020 Windows: Faulty shapes in variables faulty_1 to faulty_"
+puts "TODO ?OCC26020 Windows: 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"
 
diff --git a/tests/bugs/moddata_3/bug27804_1 b/tests/bugs/moddata_3/bug27804_1
new file mode 100644 (file)
index 0000000..a6d611e
--- /dev/null
@@ -0,0 +1,37 @@
+puts "============"
+puts "OCC27804"
+puts "============"
+puts ""
+################################################################
+## Two breps cause intersections to loop for too long/infinitely
+################################################################
+
+# The main idea of the test is performance meter. 
+
+restore [locate_data_file bug27804_il1.brep] b1
+restore [locate_data_file bug27804_il2.brep] b2
+
+bsection result b1 b2
+
+checkprops result -l 0.000335043
+checkshape result 
+
+regexp {nb alone Vertices : ([-0-9.+eE]+)} [checksection result] full nbv
+if { $nbv != 0 } { puts "Error : Section is incorrect" }
+
+set nbshapes_expected "
+Number of shapes in shape
+ VERTEX    : 1
+ EDGE      : 1
+ WIRE      : 0
+ FACE      : 0
+ SHELL     : 0
+ SOLID     : 0
+ COMPSOLID : 0
+ COMPOUND  : 1
+ SHAPE     : 3
+"
+
+checknbshapes result -ref ${nbshapes_expected} -t -m "Section curve"
+
+checkview -display result -3d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/moddata_3/bug27804_2 b/tests/bugs/moddata_3/bug27804_2
new file mode 100644 (file)
index 0000000..bb9540e
--- /dev/null
@@ -0,0 +1,30 @@
+puts "============"
+puts "OCC27804"
+puts "============"
+puts ""
+################################################################
+## Two breps cause intersections to loop for too long/infinitely
+################################################################
+
+# The main idea of the test is performance meter. 
+
+
+restore [locate_data_file bug27804_il1.brep] b1
+restore [locate_data_file bug27804_il2.brep] b2
+
+explode b2 e
+
+#should create pcurve
+bhaspc b2_1 b1 do
+
+mk2dcurve c2d b2_1 b1
+
+if { [regexp "2d curve" [whatis c2d]] != 1 } {
+    puts "Faulty: No 2D curves detected"
+}
+
+v2d
+donly c2d
+2dfit
+
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file