0027371: Regression: BRepExtrema works too much slower in 691 (from 670)
[occt.git] / src / Extrema / Extrema_GenExtCC.gxx
index 6acba89..bb28481 100644 (file)
@@ -38,7 +38,7 @@ static Standard_Boolean comp(const gp_XY& theA,
   {
     if (theA.X() == theB.X())
     {
-      if (theA.Y() <= theB.Y())
+      if (theA.Y() < theB.Y())
         return Standard_True;
     }
   }
@@ -97,7 +97,8 @@ private:
 //purpose  : 
 //=======================================================================
 Extrema_GenExtCC::Extrema_GenExtCC()
-: myParallel(Standard_False),
+: myIsFindSingleSolution(Standard_False),
+  myParallel(Standard_False),
   myCurveMinTol(Precision::PConfusion()),
   myLowBorder(1,2),
   myUppBorder(1,2),
@@ -112,7 +113,8 @@ Extrema_GenExtCC::Extrema_GenExtCC()
 //=======================================================================
 Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
                                    const Curve2& C2)
-: myParallel(Standard_False),
+: myIsFindSingleSolution(Standard_False),
+  myParallel(Standard_False),
   myCurveMinTol(Precision::PConfusion()),
   myLowBorder(1,2),
   myUppBorder(1,2),
@@ -136,7 +138,8 @@ Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
                                    const Standard_Real Usup,
                                    const Standard_Real Vinf,
                                    const Standard_Real Vsup)
-: myParallel(Standard_False),
+: myIsFindSingleSolution(Standard_False),
+  myParallel(Standard_False),
   myCurveMinTol(Precision::PConfusion()),
   myLowBorder(1,2),
   myUppBorder(1,2),
@@ -191,19 +194,60 @@ void Extrema_GenExtCC::Perform()
   Curve2 &C2 = *(Curve2*)myC[1];
 
   Standard_Integer aNbInter[2];
-  aNbInter[0] = C1.NbIntervals(GeomAbs_C2);
-  aNbInter[1] = C2.NbIntervals(GeomAbs_C2);
+  GeomAbs_Shape aContinuity = GeomAbs_C2;
+  aNbInter[0] = C1.NbIntervals(aContinuity);
+  aNbInter[1] = C2.NbIntervals(aContinuity);
+
+  if (aNbInter[0] * aNbInter[1] > 100)
+  {
+    aContinuity = GeomAbs_C1;
+    aNbInter[0] = C1.NbIntervals(aContinuity);
+    aNbInter[1] = C2.NbIntervals(aContinuity);
+  }
+
   TColStd_Array1OfReal anIntervals1(1, aNbInter[0] + 1);
   TColStd_Array1OfReal anIntervals2(1, aNbInter[1] + 1);
-  C1.Intervals(anIntervals1, GeomAbs_C2);
-  C2.Intervals(anIntervals2, GeomAbs_C2);
+  C1.Intervals(anIntervals1, aContinuity);
+  C2.Intervals(anIntervals2, aContinuity);
+
+  // Lipchitz constant computation.
+  Standard_Real aLC = 9.0; // Default value.
+  const Standard_Real aMaxDer1 = 1.0 / C1.Resolution(1.0);
+  const Standard_Real aMaxDer2 = 1.0 / C2.Resolution(1.0);
+  const Standard_Real aMaxDer = Max(aMaxDer1, aMaxDer2) * Sqrt(2.0);
+  if (aLC > aMaxDer)
+    aLC = aMaxDer;
+
+  // Change constant value according to the concrete curve types.
+  Standard_Boolean isConstLockedFlag = Standard_False;
+  if (C1.GetType() == GeomAbs_Line)
+  {
+    Standard_Real aMaxDer = 1.0 / C2.Resolution(1.0);
+    if (aLC > aMaxDer)
+    {
+      isConstLockedFlag = Standard_True;
+      aLC = aMaxDer;
+    }
+  }
+  if (C2.GetType() == GeomAbs_Line)
+  {
+    Standard_Real aMaxDer = 1.0 / C1.Resolution(1.0);
+    if (aLC > aMaxDer)
+    {
+      isConstLockedFlag = Standard_True;
+      aLC = aMaxDer;
+    }
+  }
 
   Extrema_GlobOptFuncCCC2 aFunc (C1, C2);
-  math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder);
+  math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder, aLC);
+  aFinder.SetLipConstState(isConstLockedFlag);
+  aFinder.SetContinuity(aContinuity == GeomAbs_C2 ? 2 : 1);
   Standard_Real aDiscTol = 1.0e-2;
   Standard_Real aValueTol = 1.0e-2;
   Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
   aFinder.SetTol(aDiscTol, aSameTol);
+  aFinder.SetFunctionalMinimalValue(0.0); // Best distance cannot be lower than 0.0.
 
   // Size computed to have cell index inside of int32 value.
   const Standard_Real aCellSize = Max(anIntervals1.Upper() - anIntervals1.Lower(),
@@ -228,7 +272,7 @@ void Extrema_GenExtCC::Perform()
       aSecondBorderInterval(2) = anIntervals2(j + 1);
 
       aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
-      aFinder.Perform();
+      aFinder.Perform(GetSingleSolutionFlag());
 
       // Check that solution found on current interval is not worse than previous.
       aCurrF = aFinder.GetF();
@@ -283,7 +327,7 @@ void Extrema_GenExtCC::Perform()
   // Check for infinity solutions case, for this:
   // Sort points lexicographically and check midpoint between each two neighboring points.
   // If all midpoints functional value is acceptable
-  // then set myParallel flag to true and return one soulution.
+  // then set myParallel flag to true and return one solution.
   std::sort(aPnts.begin(), aPnts.end(), comp);
   Standard_Boolean isParallel = Standard_False;
   Standard_Real aVal = 0.0;
@@ -388,3 +432,21 @@ void Extrema_GenExtCC::Points(const Standard_Integer N,
   P1.SetValues(myPoints1(N), Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)));
   P2.SetValues(myPoints2(N), Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
 }
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+void Extrema_GenExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+  myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+Standard_Boolean Extrema_GenExtCC::GetSingleSolutionFlag() const
+{
+  return myIsFindSingleSolution;
+}