0026674: Performance regression in BRepExtrema_DistShapeShape in OCCT 6.9.0 in compar...
authornbv <nbv@opencascade.com>
Thu, 17 Sep 2015 10:55:39 +0000 (13:55 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 17 Sep 2015 14:01:29 +0000 (17:01 +0300)
Creation the test case for current issue.

Added flag for single extrema computation. Now implemented only for parametric solver GenExtCC.
Default behavior of curve/curve solver in distmini command changed to "find one solution".

src/BRepExtrema/BRepExtrema_ExtCC.cxx
src/Extrema/Extrema_ECC.hxx
src/Extrema/Extrema_ECC2d.hxx
src/Extrema/Extrema_ExtCC.cxx
src/Extrema/Extrema_ExtCC.hxx
src/Extrema/Extrema_ExtCC2d.cxx
src/Extrema/Extrema_ExtCC2d.hxx
src/Extrema/Extrema_GenExtCC.gxx
src/math/math_GlobOptMin.cxx
src/math/math_GlobOptMin.hxx
tests/bugs/modalg_6/bug26674 [new file with mode: 0644]

index 9ca3b84..c4fbdc9 100644 (file)
@@ -65,6 +65,7 @@ void BRepExtrema_ExtCC::Perform(const TopoDS_Edge& E1)
   BRep_Tool::Range(E1,U1,U2);
   myExtCC.SetCurve (1, HC->Curve(), U1, U2);
   myExtCC.SetTolerance(1, Tol);
+  myExtCC.SetSingleSolutionFlag(Standard_True);
   myExtCC.Perform();
 }
 
index c4f7f8a..c3f1b52 100644 (file)
@@ -55,7 +55,13 @@ public:
   Standard_EXPORT void SetParams (const Adaptor3d_Curve& C1, const Adaptor3d_Curve& C2, const Standard_Real Uinf, const Standard_Real Usup, const Standard_Real Vinf, const Standard_Real Vsup);
   
   Standard_EXPORT void SetTolerance (const Standard_Real Tol);
-  
+
+  //! Set flag for single extrema computation. Works on parametric solver only.
+  Standard_EXPORT void SetSingleSolutionFlag (const Standard_Boolean theSingleSolutionFlag);
+
+  //! Get flag for single extrema computation. Works on parametric solver only.
+  Standard_EXPORT Standard_Boolean GetSingleSolutionFlag () const;
+
   Standard_EXPORT void Perform();
   
   Standard_EXPORT Standard_Boolean IsDone() const;
@@ -80,7 +86,7 @@ protected:
 private:
 
 
-
+  Standard_Boolean myIsFindSingleSolution; // Default value is false.
   Standard_Boolean myParallel;
   Standard_Real myCurveMinTol;
   math_Vector myLowBorder;
index 3b37ee9..c339723 100644 (file)
@@ -55,7 +55,13 @@ public:
   Standard_EXPORT void SetParams (const Adaptor2d_Curve2d& C1, const Adaptor2d_Curve2d& C2, const Standard_Real Uinf, const Standard_Real Usup, const Standard_Real Vinf, const Standard_Real Vsup);
   
   Standard_EXPORT void SetTolerance (const Standard_Real Tol);
-  
+
+  //! Set flag for single extrema computation. Works on parametric solver only.
+  Standard_EXPORT void SetSingleSolutionFlag (const Standard_Boolean theSingleSolutionFlag);
+
+  //! Get flag for single extrema computation. Works on parametric solver only.
+  Standard_EXPORT Standard_Boolean GetSingleSolutionFlag () const;
+
   Standard_EXPORT void Perform();
   
   Standard_EXPORT Standard_Boolean IsDone() const;
@@ -80,7 +86,7 @@ protected:
 private:
 
 
-
+  Standard_Boolean myIsFindSingleSolution; // Default value is false.
   Standard_Boolean myParallel;
   Standard_Real myCurveMinTol;
   math_Vector myLowBorder;
index c0ffa6b..fffd4c8 100644 (file)
@@ -53,8 +53,9 @@
 //purpose  : 
 //=======================================================================
 Extrema_ExtCC::Extrema_ExtCC (const Standard_Real TolC1,
-                                           const Standard_Real TolC2) :
-                                             myDone (Standard_False)
+                              const Standard_Real TolC2)
+: myIsFindSingleSolution(Standard_False),
+  myDone (Standard_False)
 {
   myC[0] = 0; myC[1] = 0;
   myTol[0] = TolC1; myTol[1] = TolC2;
@@ -65,15 +66,16 @@ Extrema_ExtCC::Extrema_ExtCC (const Standard_Real TolC1,
 //purpose  : 
 //=======================================================================
 
-Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, 
-                              const Adaptor3d_Curve& C2,
-                              const Standard_Real      U1,
-                              const Standard_Real      U2,
-                              const Standard_Real      V1,
-                              const Standard_Real      V2,
-                              const Standard_Real      TolC1,
-                              const Standard_Real      TolC2)
-: myECC(C1, C2, U1, U2, V1, V2),
+Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
+                             const Adaptor3d_Curve& C2,
+                             const Standard_Real      U1,
+                             const Standard_Real      U2,
+                             const Standard_Real      V1,
+                             const Standard_Real      V2,
+                             const Standard_Real      TolC1,
+                             const Standard_Real      TolC2)
+: myIsFindSingleSolution(Standard_False),
+  myECC(C1, C2, U1, U2, V1, V2),
   myDone (Standard_False)
 {
   SetCurve (1, C1, U1, U2);
@@ -90,10 +92,11 @@ Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
 //=======================================================================
 
 Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, 
-                              const Adaptor3d_Curve& C2,
-                              const Standard_Real      TolC1,
-                              const Standard_Real      TolC2)
-: myECC(C1, C2),
+                             const Adaptor3d_Curve& C2,
+                             const Standard_Real      TolC1,
+                             const Standard_Real      TolC2)
+: myIsFindSingleSolution(Standard_False),
+  myECC(C1, C2),
   myDone (Standard_False)
 {
   SetCurve (1, C1, C1.FirstParameter(), C1.LastParameter());
@@ -165,6 +168,7 @@ void Extrema_ExtCC::Perform()
   myECC.SetParams(*((Adaptor3d_Curve*)myC[0]), 
                   *((Adaptor3d_Curve*)myC[1]), myInf[0], mySup[0], myInf[1], mySup[1]);
   myECC.SetTolerance(Min(myTol[0], myTol[1]));
+  myECC.SetSingleSolutionFlag(GetSingleSolutionFlag());
   myDone = Standard_False;
   mypoints.Clear();
   mySqDist.Clear();
@@ -720,3 +724,21 @@ void Extrema_ExtCC::Results(const Extrema_ECC&   AlgExt,
     }
   }
 }
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+void Extrema_ExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+  myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+Standard_Boolean Extrema_ExtCC::GetSingleSolutionFlag() const
+{
+  return myIsFindSingleSolution;
+}
index 8785317..57180fe 100644 (file)
@@ -88,8 +88,11 @@ public:
   //! parameter FirstParameter on C2.
   Standard_EXPORT void TrimmedSquareDistances (Standard_Real& dist11, Standard_Real& distP12, Standard_Real& distP21, Standard_Real& distP22, gp_Pnt& P11, gp_Pnt& P12, gp_Pnt& P21, gp_Pnt& P22) const;
 
+  //! Set flag for single extrema computation. Works on parametric solver only.
+  Standard_EXPORT void SetSingleSolutionFlag (const Standard_Boolean theSingleSolutionFlag);
 
-
+  //! Get flag for single extrema computation. Works on parametric solver only.
+  Standard_EXPORT Standard_Boolean GetSingleSolutionFlag () const;
 
 protected:
 
@@ -104,7 +107,7 @@ protected:
 private:
 
 
-
+  Standard_Boolean myIsFindSingleSolution; // Default value is false.
   Extrema_ECC myECC;
   Standard_Boolean myDone;
   Standard_Boolean myIsPar;
index cf145c2..cf93af4 100644 (file)
 #include <StdFail_NotDone.hxx>
 
 Extrema_ExtCC2d::Extrema_ExtCC2d()
+: myIsFindSingleSolution(Standard_False)
 {
 }
 
 
-Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d&       C1, 
-                                  const Adaptor2d_Curve2d&       C2,
-                                  const Standard_Real TolC1, 
-                                  const Standard_Real TolC2)
+Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d&       C1,
+                                 const Adaptor2d_Curve2d&       C2,
+                                 const Standard_Real TolC1,
+                                 const Standard_Real TolC2)
+: myIsFindSingleSolution(Standard_False)
 {
   Initialize(C2, Extrema_Curve2dTool::FirstParameter(C2), Extrema_Curve2dTool::LastParameter(C2), TolC1, TolC2);
   Perform(C1, Extrema_Curve2dTool::FirstParameter(C1), Extrema_Curve2dTool::LastParameter(C1));
 }
 
 Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d&        C1, 
-                                  const Adaptor2d_Curve2d&        C2,
-                                  const Standard_Real  U1,
-                                  const Standard_Real  U2,
-                                  const Standard_Real  V1,
-                                  const Standard_Real  V2,
-                                  const Standard_Real  TolC1,
-                                  const Standard_Real  TolC2)
+                                 const Adaptor2d_Curve2d&        C2,
+                                 const Standard_Real  U1,
+                                 const Standard_Real  U2,
+                                 const Standard_Real  V1,
+                                 const Standard_Real  V2,
+                                 const Standard_Real  TolC1,
+                                 const Standard_Real  TolC2)
+: myIsFindSingleSolution(Standard_False)
 {
   Initialize(C2, V1, V2, TolC1, TolC2);
   Perform(C1, U1, U2);
@@ -137,11 +140,12 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
       case GeomAbs_BezierCurve:
       case GeomAbs_OtherCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Standard_Real Period2 = 0.;
-       if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 2*M_PI,Period2);
+          Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+          aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+          aParamSolver.Perform();
+          Standard_Real Period2 = 0.;
+          if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
+          Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -166,35 +170,39 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
        Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 2*M_PI);
         }
        break;
-      case GeomAbs_Ellipse: {
-       //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22,2*M_PI, 2*M_PI);
+      case GeomAbs_Ellipse:
+        {
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22,2*M_PI, 2*M_PI);
         }
        break;
       case GeomAbs_Parabola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.);
       }
        break;
       case GeomAbs_Hyperbola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.);
       }
        break;
       case GeomAbs_BezierCurve:
       case GeomAbs_OtherCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();        
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
        Standard_Real Period2 = 0.;
        if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 2*M_PI,Period2);
+       Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -222,34 +230,38 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
       case GeomAbs_Ellipse: {
        //inverse = Standard_True;
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI);
         }
        break;
       case GeomAbs_Parabola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Parabola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
       }
        break;
       case GeomAbs_Hyperbola: {
        //inverse = Standard_True;
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
       }
        break;
       case GeomAbs_BezierCurve:
       case GeomAbs_OtherCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
        Standard_Real Period2 = 0.;
        if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 0., Period2);
+       Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -277,33 +289,37 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
       case GeomAbs_Ellipse: {
        //inverse = Standard_True;
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Hyperbola(C1));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI );
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI );
         }
        break;
       case GeomAbs_Parabola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
       }
        break;
       case GeomAbs_Hyperbola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
       }
        break;
       case GeomAbs_OtherCurve:
       case GeomAbs_BezierCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-  Xtrem.Perform();
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
        Standard_Real Period2 = 0.;
        if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 0., Period2);
+       Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -322,13 +338,14 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
   case GeomAbs_BezierCurve:
   case GeomAbs_OtherCurve:
   case GeomAbs_BSplineCurve: {
-    Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-    Xtrem.Perform();
+    Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+    aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+    aParamSolver.Perform();
     Standard_Real Period1 = 0.;
     if (Extrema_Curve2dTool::IsPeriodic(C1)) Period1 = Extrema_Curve2dTool::Period(C1);
     Standard_Real Period2 = 0.;
     if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-    Results(Xtrem, U11, U12, U21, U22, Period1, Period2);
+    Results(aParamSolver, U11, U12, U21, U22, Period1, Period2);
   }
   break;
 
@@ -361,11 +378,12 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
       case GeomAbs_BezierCurve:
       case GeomAbs_OtherCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
        Standard_Real Period2 = 0.;
        if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 0., Period2);
+       Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -558,3 +576,21 @@ Standard_Boolean Extrema_ExtCC2d::IsParallel() const
   if (!myDone) StdFail_NotDone::Raise();
   return myIsPar;
 }
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+void Extrema_ExtCC2d::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+  myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+Standard_Boolean Extrema_ExtCC2d::GetSingleSolutionFlag() const
+{
+  return myIsFindSingleSolution;
+}
index 0ff2c19..fe7bc96 100644 (file)
@@ -82,7 +82,11 @@ public:
   //! parameter FirstParameter on C2.
   Standard_EXPORT void TrimmedSquareDistances (Standard_Real& dist11, Standard_Real& distP12, Standard_Real& distP21, Standard_Real& distP22, gp_Pnt2d& P11, gp_Pnt2d& P12, gp_Pnt2d& P21, gp_Pnt2d& P22) const;
 
+  //! Set flag for single extrema computation. Works on parametric solver only.
+  Standard_EXPORT void SetSingleSolutionFlag (const Standard_Boolean theSingleSolutionFlag);
 
+  //! Get flag for single extrema computation. Works on parametric solver only.
+  Standard_EXPORT Standard_Boolean GetSingleSolutionFlag () const;
 
 
 protected:
@@ -98,7 +102,7 @@ protected:
 private:
 
 
-
+  Standard_Boolean myIsFindSingleSolution; // Default value is false.
   Standard_Boolean myDone;
   Standard_Boolean myIsPar;
   Extrema_SequenceOfPOnCurv2d mypoints;
index 6acba89..88ca463 100644 (file)
@@ -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),
@@ -204,6 +207,7 @@ void Extrema_GenExtCC::Perform()
   Standard_Real aValueTol = 1.0e-2;
   Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
   aFinder.SetTol(aDiscTol, aSameTol);
+  aFinder.SetFunctionalMinimalValue(0.0); // Best disntance 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 +232,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();
@@ -388,3 +392,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;
+}
index 99e968d..2560aa2 100644 (file)
@@ -54,6 +54,7 @@ math_GlobOptMin::math_GlobOptMin(math_MultipleVarFunction* theFunc,
   myFunc = theFunc;
   myC = theC;
   myIsFindSingleSolution = Standard_False;
+  myFunctionalMinimalValue = -Precision::Infinite();
   myZ = -1;
   mySolCount = 0;
 
@@ -247,6 +248,13 @@ void math_GlobOptMin::Perform(const Standard_Boolean isFindSingleSolution)
       myE3 = - maxLength * myTol * myC / 4.0;
   }
 
+  // Search single solution and current solution in its neighbourhood.
+  if (CheckFunctionalStopCriteria())
+  {
+    myDone = Standard_True;
+    return;
+  }
+
   isFirstCellFilterInvoke = Standard_True;
   computeGlobalExtremum(myN);
 
@@ -409,7 +417,7 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
   Standard_Real r;
   Standard_Boolean isReached = Standard_False;
 
-  for(myX(j) = myA(j) + myE1; 
+  for(myX(j) = myA(j) + myE1;
      (myX(j) < myB(j) + myE1) && (!isReached);
       myX(j) += myV(j))
   {
@@ -419,6 +427,9 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
       isReached = Standard_True;
     }
 
+    if (CheckFunctionalStopCriteria())
+      return; // Best possible value is obtained.
+
     if (j == 1)
     {
       isInside = Standard_False;
@@ -463,6 +474,9 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
         isFirstCellFilterInvoke = Standard_True;
       }
 
+      if (CheckFunctionalStopCriteria())
+        return; // Best possible value is obtained.
+
       aRealStep = myE2 + Abs(myF - d) / myC;
       myV(1) = Min(aRealStep, myMaxV(1));
     }
@@ -589,6 +603,24 @@ Standard_Real math_GlobOptMin::GetF()
 }
 
 //=======================================================================
+//function : SetFunctionalMinimalValue
+//purpose  :
+//=======================================================================
+void math_GlobOptMin::SetFunctionalMinimalValue(const Standard_Real theMinimalValue)
+{
+  myFunctionalMinimalValue = theMinimalValue;
+}
+
+//=======================================================================
+//function : GetFunctionalMinimalValue
+//purpose  :
+//=======================================================================
+Standard_Real math_GlobOptMin::GetFunctionalMinimalValue()
+{
+  return myFunctionalMinimalValue;
+}
+
+//=======================================================================
 //function : IsDone
 //purpose  :
 //=======================================================================
@@ -621,3 +653,17 @@ void math_GlobOptMin::initCellSize()
       * Precision::PConfusion() / (2.0 * Sqrt(2.0));
   }
 }
+
+//=======================================================================
+//function : CheckFunctionalStopCriteria
+//purpose  :
+//=======================================================================
+Standard_Boolean math_GlobOptMin::CheckFunctionalStopCriteria()
+{
+  // Search single solution and current solution in its neighbourhood.
+  if (myIsFindSingleSolution &&
+      Abs (myF - myFunctionalMinimalValue) < mySameTol * 0.01)
+    return Standard_True;
+
+  return Standard_False;
+}
index 0af9820..1d42ab9 100644 (file)
@@ -141,7 +141,13 @@ public:
   //! Return solution theIndex, 1 <= theIndex <= NbExtrema.
   Standard_EXPORT void Points(const Standard_Integer theIndex, math_Vector& theSol);
 
-  Standard_Boolean isDone();
+  Standard_EXPORT Standard_Boolean isDone();
+
+  //! Set functional minimal value.
+  Standard_EXPORT void SetFunctionalMinimalValue(const Standard_Real theMinimalValue);
+
+  //! Get functional minimal value.
+  Standard_EXPORT Standard_Real GetFunctionalMinimalValue();
 
 private:
 
@@ -154,6 +160,10 @@ private:
 
   void computeGlobalExtremum(Standard_Integer theIndex);
 
+  //! Check possibility to stop computations.
+  //! Find single solution + in neighbourhood of best possible solution.
+  Standard_Boolean CheckFunctionalStopCriteria();
+
   //! Computes starting value / approximation:
   //! myF - initial best value.
   //! myY - initial best point.
@@ -180,6 +190,7 @@ private:
                            // default value is 1.0e-7.
   Standard_Real myC; //Lipschitz constant, default 9
   Standard_Boolean myIsFindSingleSolution; // Default value is false.
+  Standard_Real myFunctionalMinimalValue; // Default value is -Precision::Infinite
 
   // Output.
   Standard_Boolean myDone;
diff --git a/tests/bugs/modalg_6/bug26674 b/tests/bugs/modalg_6/bug26674
new file mode 100644 (file)
index 0000000..7fa6813
--- /dev/null
@@ -0,0 +1,37 @@
+puts "========"
+puts "OCC26674"
+puts "========"
+puts ""
+#################################################
+# Performance regression in BRepExtrema_DistShapeShape in OCCT 6.9.0 in compare with OCCT 6.7.1
+#################################################
+
+set max_time 1
+
+restore [locate_data_file OCC26674-face.brep] a1
+restore [locate_data_file OCC26674-shell.brep] a2
+
+dchrono cr reset
+dchrono cr start
+
+distmini dd a1 a2
+
+dchrono cr stop
+
+set log [dchrono cr show]
+
+regexp {CPU user time: ([-0-9.+eE]+) seconds} $log full z
+puts "$z"
+
+if { $z > ${max_time} } {
+    puts "Elapsed time of BRepExtrema_DistShapeShape is more than ${max_time} seconds - Error"
+} else {
+    puts "Elapsed time of BRepExtrema_DistShapeShape is less than ${max_time} seconds - OK"
+}
+
+regexp {([-0-9.+eE]+)$} [dump dd_val] full dist
+
+set expected_dist 0.0
+set tol_abs_dist 1.0e-07
+set tol_rel_dist 0.0
+checkreal "Dump of dd_val" ${dist} ${expected_dist} ${tol_abs_dist} ${tol_rel_dist}