0031552: Bad performance of intersection of cylindrical surfaces
authorifv <ifv@opencascade.com>
Thu, 7 May 2020 11:46:06 +0000 (14:46 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 15 May 2020 15:00:48 +0000 (18:00 +0300)
Adjusting parameters of algorithm depending on axes and parameters of cylinders is added in order to reduce computation time

Test case added: tests/lowalgos/intss/bug31552

tests/perf/modalg/bug26310_1: test case corrected according to current state of algorithm

src/IntPatch/IntPatch_ImpImpIntersection_4.gxx
tests/lowalgos/intss/bug31552 [new file with mode: 0644]
tests/perf/modalg/bug26310_1

index 8fe2d21..5f1977d 100644 (file)
@@ -2691,7 +2691,62 @@ static IntPatch_ImpImpIntersection::IntStatus
     if ((aRangeS1.Delta() > aMaxV1Range) || (aRangeS2.Delta() > aMaxV2Range))
       return IntPatch_ImpImpIntersection::IntStatus_InfiniteSectionCurve;
   }
+  //
+  Standard_Boolean isGoodIntersection = Standard_False;
+  Standard_Real anOptdu = 0.;
+  do
+  {
+    //Checking parameters of cylinders in order to define "good intersection"
+    //"Good intersection" means that axes of cylinders are almost perpendicular and
+    // one radius is much smaller than the other and small cylinder is "inside" big one.
+    const Standard_Real aToMuchCoeff = 3.;
+    const Standard_Real aCritAngle = M_PI / 18.; // 10 degree
+    Standard_Real anR1 = theCyl1.Radius();
+    Standard_Real anR2 = theCyl2.Radius();
+    Standard_Real anRmin = 0., anRmax = 0.;
+    //Radius criterion
+    if (anR1 > aToMuchCoeff * anR2)
+    {
+      anRmax = anR1; anRmin = anR2;
+    }
+    else if (anR2 > aToMuchCoeff * anR1)
+    {
+      anRmax = anR2; anRmin = anR1;
+    }
+    else
+    {
+      break;
+    }
+    //Angle criterion
+    const gp_Ax1& anAx1 = theCyl1.Axis();
+    const gp_Ax1& anAx2 = theCyl2.Axis();
+    if (!anAx1.IsNormal(anAx2, aCritAngle))
+    {
+      break;
+    }
+    //Placement criterion
+    gp_Lin anL1(anAx1), anL2(anAx2);
+    Standard_Real aDist = anL1.Distance(anL2);
+    if (aDist > anRmax / 2.)
+    {
+      break;
+    }
 
+    isGoodIntersection = Standard_True;
+    //Estimation of "optimal" du
+    //Relative deflection, absolut deflection is Rmin*aDeflection
+    Standard_Real aDeflection = 0.001;
+    Standard_Integer aNbP = 3;
+    if (anRmin * aDeflection > 1.e-3)
+    {
+      Standard_Real anAngle = 1.0e0 - aDeflection;
+      anAngle = 2.0e0 * ACos(anAngle);
+      aNbP = (Standard_Integer)(2. * M_PI / anAngle) + 1;
+    }
+    anOptdu = 2. * M_PI_2 / (Standard_Real)(aNbP - 1);
+
+  } while (0);
+//
   const ComputationMethods::stCoeffsValue &anEquationCoeffs = theBW.SICoeffs();
   const IntSurf_Quadric& aQuad1 = theBW.GetQSurface(1);
   const IntSurf_Quadric& aQuad2 = theBW.GetQSurface(2);
@@ -2699,15 +2754,27 @@ static IntPatch_ImpImpIntersection::IntStatus
   const Standard_Real aTol2D = theBW.Get2dTolerance();
   const Standard_Real aTol3D = theBW.Get3dTolerance();
   const Standard_Real aPeriod = 2.0*M_PI;
-  const Standard_Integer aNbMaxPoints = 2000;
-  const Standard_Integer aNbMinPoints = 200;
-  const Standard_Integer aNbPoints = Min(Max(aNbMinPoints,
-                                  RealToInt(20.0*theCyl1.Radius())), aNbMaxPoints);
-  const Standard_Real aStepMin = aTol2D,
-                                  aStepMax = (aUSurf1l - aUSurf1f > M_PI / 100.0) ?
-                                  (aUSurf1l - aUSurf1f) / IntToReal(aNbPoints) :
-                                  aUSurf1l - aUSurf1f;
-
+  Standard_Integer aNbMaxPoints = 1000;
+  Standard_Integer aNbMinPoints = 200;
+  Standard_Real du;
+  if (isGoodIntersection)
+  {
+    du = anOptdu;
+    aNbMaxPoints = 200;
+    aNbMinPoints = 50;
+  }
+  else
+  {
+    du = 2. * M_PI / aNbMaxPoints;
+  }
+  Standard_Integer aNbPts = Min(RealToInt((aUSurf1l - aUSurf1f) / du) + 1, 
+                                RealToInt(20.0*theCyl1.Radius()));
+  const Standard_Integer aNbPoints = Min(Max(aNbMinPoints, aNbPts), aNbMaxPoints);
+  const Standard_Real aStepMin = Max(aTol2D, Precision::PConfusion()), 
+    aStepMax = (aUSurf1l - aUSurf1f > M_PI / 100.0) ?
+    (aUSurf1l - aUSurf1f) / IntToReal(aNbPoints) : aUSurf1l - aUSurf1f;
+
   //The main idea of the algorithm is to change U1-parameter
   //(U-parameter of theCyl1) from aU1f to aU1l with some step
   //(step is adaptive) and to obtain set of intersection points.
@@ -3279,6 +3346,16 @@ static IntPatch_ImpImpIntersection::IntStatus
               aMinUexp = Min(aMinUexp, anUexpect[i]);
               continue;
             }
+            //
+            if (isGoodIntersection)
+            {
+              //Use constant step
+              anUexpect[i] += aStepMax;
+              aMinUexp = Min(aMinUexp, anUexpect[i]);
+
+              continue;
+            }
+            //
 
             Standard_Real aStepTmp = aStepMax;
 
diff --git a/tests/lowalgos/intss/bug31552 b/tests/lowalgos/intss/bug31552
new file mode 100644 (file)
index 0000000..f5f9a4b
--- /dev/null
@@ -0,0 +1,48 @@
+puts "========="
+puts "0031552: Modeling Algorithms - Bad performance of intersection of cylindrical surfaces"
+puts "========="
+puts ""
+
+cpulimit 200
+
+cylinder s1 0 557.800010681152 0 0 0 1 0 1 0  347.850006103516
+trim s1 s1 3.2385 6.28319 -39.957 39.957
+
+cylinder s2 5.45639675193397 189.209310035068 0 -0.254420004160252 0.96709382248213 0 0.96709382248213 0.254420004160252 0 88.5
+trim s2 s2 6.19592 6.37045 0 10.0002
+
+dchrono z reset
+dchrono z start
+
+set ic 1
+while { $ic <= 100 } {
+  intersect res s1 s2 
+  incr ic
+}
+
+dchrono z stop counter Bug31552
+
+set che [whatis res]
+set ind [string first "3d curve" $che]
+if {${ind} >= 0} {
+  puts "Error: only one curve"
+} 
+
+set che [whatis res_1]
+set ind [string first "3d curve" $che]
+if {${ind} < 0} {
+  puts "Error no first curve"
+}
+
+set che [whatis res_2]
+set ind [string first "3d curve" $che]
+if {${ind} < 0} {
+  puts "Error no second curve"
+}
+
+smallview AXON
+don res_1 res_2
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
+
+
index 1de235a..0628051 100644 (file)
@@ -6,7 +6,7 @@ puts ""
 # Very slow boolean cut operations on cylinders
 #################################################
 
-set ExpTol 3.32e-07
+set ExpTol 3.05e-07
 
 set GoodNbCurv 4