0030082: Intersection algorithm returns curve with big tolerance value
authornbv <nbv@opencascade.com>
Thu, 23 Aug 2018 13:37:59 +0000 (16:37 +0300)
committerbugmaster <bugmaster@opencascade.com>
Sat, 1 Sep 2018 08:06:55 +0000 (11:06 +0300)
The fix inserts new points at the end of the WLine in case when the direction of the intersection curve is significantly changed.

src/IntPatch/IntPatch_ImpImpIntersection_4.gxx
tests/bugs/modalg_7/bug30082_1 [new file with mode: 0644]
tests/bugs/modalg_7/bug30082_2 [new file with mode: 0644]

index 4281066..4cd4f83 100644 (file)
@@ -3376,6 +3376,90 @@ static IntPatch_ImpImpIntersection::IntStatus
             if (aPf.IsSame(aPl, Precision::Confusion()))
               isGood = Standard_False;
           }
+          else if (aWLine[i]->NbPnts() > 2)
+          {
+            // Sometimes points of the WLine are distributed
+            // linearly and uniformly. However, such position
+            // of the points does not always describe the real intersection
+            // curve. I.e. real tangents at the ends of the intersection
+            // curve can significantly deviate from this "line" direction.
+            // Here we are processing this case by inserting additional points
+            // to the beginning/end of the WLine to make it more precise.
+            // See description to the issue #30082.
+
+            const Standard_Real aSqTol3D = aTol3D*aTol3D;
+            for (Standard_Integer j = 0; j < 2; j++)
+            {
+              // If j == 0 ==> add point at begin of WLine.
+              // If j == 1 ==> add point at end of WLine.
+
+              for (;;)
+              {
+                if (aWLine[i]->NbPnts() >= aNbMaxPoints)
+                {
+                  break;
+                }
+
+                // Take 1st and 2nd point to compute the "line" direction.
+                // For our convenience, we make 2nd point be the ends of the WLine
+                // because it will be used for computation of the normals 
+                // to the surfaces.
+                const Standard_Integer anIdx1 = j ? aWLine[i]->NbPnts() - 1 : 2;
+                const Standard_Integer anIdx2 = j ? aWLine[i]->NbPnts() : 1;
+
+                const gp_Pnt &aP1 = aWLine[i]->Point(anIdx1).Value();
+                const gp_Pnt &aP2 = aWLine[i]->Point(anIdx2).Value();
+
+                const gp_Vec aDir(aP1, aP2);
+
+                if (aDir.SquareMagnitude() < aSqTol3D)
+                {
+                  break;
+                }
+
+                // Compute tangent in first/last point of the WLine.
+                // We do not take into account the flag "isReversed"
+                // because strict direction of the tangent is not
+                // important here (we are interested in the tangent
+                // line itself and nothing to fear if its direction
+                // is reversed).
+                const gp_Vec aN1 = aQuad1.Normale(aP2);
+                const gp_Vec aN2 = aQuad2.Normale(aP2);
+                const gp_Vec aTg(aN1.Crossed(aN2));
+
+                if (aTg.SquareMagnitude() < Precision::SquareConfusion())
+                {
+                  // Tangent zone
+                  break;
+                }
+
+                // Check of the bending
+                Standard_Real anAngle = aDir.Angle(aTg);
+
+                if (anAngle > M_PI_2)
+                  anAngle -= M_PI;
+
+                if (Abs(anAngle) > 0.25) // ~ 14deg.
+                {
+                  const Standard_Integer aNbPntsPrev = aWLine[i]->NbPnts();
+                  SeekAdditionalPoints(aQuad1, aQuad2, aWLine[i]->Curve(),
+                                       anEquationCoeffs, i, 3, anIdx1, anIdx2,
+                                       aTol2D, aPeriod, isReversed);
+
+                  if (aWLine[i]->NbPnts() == aNbPntsPrev)
+                  {
+                    // No points have been added. ==> Exit from a loop.
+                    break;
+                  }
+                }
+                else
+                {
+                  // Good result has been achieved. ==> Exit from a loop.
+                  break;
+                }
+              } // for (;;)
+            }
+          }
 
           if (isGood)
           {
@@ -3383,8 +3467,8 @@ static IntPatch_ImpImpIntersection::IntStatus
             isAddedIntoWL[i] = Standard_True;
             SeekAdditionalPoints(aQuad1, aQuad2, aWLine[i]->Curve(),
                                  anEquationCoeffs, i, aNbPoints, 1,
-              aWLine[i]->NbPnts(), aTol2D, aPeriod,
-              isReversed);
+                                 aWLine[i]->NbPnts(), aTol2D, aPeriod,
+                                 isReversed);
 
             aWLine[i]->ComputeVertexParameters(aTol3D);
             theSlin.Append(aWLine[i]);
diff --git a/tests/bugs/modalg_7/bug30082_1 b/tests/bugs/modalg_7/bug30082_1
new file mode 100644 (file)
index 0000000..59f6890
--- /dev/null
@@ -0,0 +1,27 @@
+puts "========"
+puts "0030082: Intersection algorithm returns curve with big tolerance value"
+puts "========"
+puts ""
+
+foreach a [directory c_*] { unset $a }
+
+brestore [locate_data_file bug27928_b1.brep] b1
+brestore [locate_data_file bug27928_b2.brep] b2
+explode b1 f
+explode b2 f
+
+if { [regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} [bopcurves b1_1 b2_2 -2d] full Toler NbCurv ] } {
+  # Before the fix, the tolerance was 0.0010828835451753697
+  checkreal Tolerance $Toler 6.5e-7 0.0 0.1
+
+  if {$NbCurv != 1} {
+    puts "Error: 1 curve is expected but $NbCurv curves are found."
+  }
+} else {
+  puts "Error: Intersection result is empty"
+}
+
+smallview
+don c_*
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_7/bug30082_2 b/tests/bugs/modalg_7/bug30082_2
new file mode 100644 (file)
index 0000000..ddfc67c
--- /dev/null
@@ -0,0 +1,67 @@
+puts "========"
+puts "0030082: Intersection algorithm returns curve with big tolerance value"
+puts "========"
+puts ""
+
+foreach a [directory res*] {unset $a}
+
+set aTol 1.0e-4
+set GoodNbCurves 4
+
+cylinder s1 -106.471129473161 -64.3442185874231 -19.25 1 0 0 0 0 -1 0.25
+cylinder s2 -124.971129473161 -67.0942185874231 -20.5 0 0 1 1 0 -0 3
+intersect res s1 s2 $aTol
+
+set che [whatis res]
+set ind [string first "3d curve" $che]
+if {${ind} >= 0} {
+  #Only variable "res" exists
+  renamevar res res_1
+}
+
+bclearobjects
+bcleartools
+
+set ic 1
+set AllowRepeat 1
+while { $AllowRepeat != 0 } {
+  set che [whatis res_$ic]
+  set ind [string first "3d curve" $che]
+  if {${ind} < 0} {
+    set AllowRepeat 0
+  } else {
+    bounds res_$ic U1 U2
+    
+    if {[dval U2-U1] < 1.0e-9} {
+      puts "Error: Wrong curve's range!"
+    }
+    
+    xdistcs res_$ic s1 U1 U2 100 $aTol
+    xdistcs res_$ic s2 U1 U2 100 $aTol
+    
+    mkedge ee res_$ic
+    baddobjects ee
+    incr ic
+  }
+}
+
+incr ic -1
+
+if { $ic != $GoodNbCurves } {
+  puts "Error: $GoodNbCurves curves are expected but $ic ones are found"
+}
+
+bfillds
+bbuild result
+
+smallview
+don result
+fit
+
+# Check gaps between edges in ce
+checksection result -r 0
+checkmaxtol result -min_tol 2.0e-7
+
+checknbshapes result -edge 4 -vertex 3
+
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png