#include <Standard_Real.hxx>
#include <Precision.hxx>
+//=======================================================================
+//function : DistanceToBorder
+//purpose :
+//=======================================================================
+static Standard_Real DistanceToBorder(const math_Vector & theX,
+ const math_Vector & theMin,
+ const math_Vector & theMax)
+{
+ Standard_Real aDist = RealLast();
+
+ for (Standard_Integer anIdx = theMin.Lower(); anIdx <= theMin.Upper(); ++anIdx)
+ {
+ const Standard_Real aDist1 = Abs (theX(anIdx) - theMin(anIdx));
+ const Standard_Real aDist2 = Abs (theX(anIdx) - theMax(anIdx));
+
+ aDist = Min (aDist, Min (aDist1, aDist2));
+ }
+
+ return aDist;
+}
+
//=======================================================================
//function : math_GlobOptMin
myMaxV(i) = (myB(i) - myA(i)) / 3.0;
}
- myExpandCoeff(1) = 1.0;
- for(i = 2; i <= myN; i++)
- {
- myExpandCoeff(i) = (myB(i) - myA(i)) / (myB(i - 1) - myA(i - 1));
- }
-
myTol = theDiscretizationTol;
mySameTol = theSameTol;
myMaxV(i) = (myB(i) - myA(i)) / 3.0;
}
- myExpandCoeff(1) = 1.0;
- for(i = 2; i <= myN; i++)
- {
- myExpandCoeff(i) = (myB(i) - myA(i)) / (myB(i - 1) - myA(i - 1));
- }
-
myTol = theDiscretizationTol;
mySameTol = theSameTol;
myMaxV(i) = (myB(i) - myA(i)) / 3.0;
}
- myExpandCoeff(1) = 1.0;
- for(i = 2; i <= myN; i++)
- {
- myExpandCoeff(i) = (myB(i) - myA(i)) / (myB(i - 1) - myA(i - 1));
- }
-
myDone = Standard_False;
}
void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
{
Standard_Integer i;
- Standard_Real d; // Functional in moved point.
+ Standard_Real d = RealLast(), aPrevVal; // Functional in original and moved points.
Standard_Real val = RealLast(); // Local extrema computed in moved point.
Standard_Real aStepBestValue = RealLast();
math_Vector aStepBestPoint(1, myN);
- Standard_Boolean isInside = Standard_False;
- Standard_Real r;
- Standard_Boolean isReached = Standard_False;
+ Standard_Boolean isInside = Standard_False,
+ isReached = Standard_False;
+ Standard_Real r1, r2, r;
-
- for(myX(j) = myA(j) + myE1;
- (myX(j) < myB(j) + myE1) && (!isReached);
- myX(j) += myV(j))
+ for(myX(j) = myA(j) + myE1; !isReached; myX(j) += myV(j))
{
if (myX(j) > myB(j))
{
if (j == 1)
{
isInside = Standard_False;
+ aPrevVal = d;
myFunc->Value(myX, d);
- r = (d + myZ * myC * myLastStep - myF) * myZ;
+ r1 = (d + myZ * myC * myLastStep - myF) * myZ; // Evtushenko estimation.
+ r2 = ((d + aPrevVal - myC * myLastStep) * 0.5 - myF) * myZ; // Shubert / Piyavsky estimation.
+ r = Min(r1, r2);
if(r > myE3)
{
- isInside = computeLocalExtremum(myX, val, myTmp);
+ Standard_Real aSaveParam = myX(1);
+
+ // Piyavsky midpoint estimation.
+ Standard_Real aParam = (2 * myX(1) - myV(1) ) * 0.5 + (aPrevVal - d) * 0.5 / myC;
+ if (Precision::IsInfinite(aPrevVal))
+ aParam = myX(1) - myV(1) * 0.5; // Protection from upper dimension step.
+
+ myX(1) = aParam;
+ Standard_Real aVal = 0;
+ myFunc->Value(myX, aVal);
+ myX(1) = aSaveParam;
+
+ if ( (aVal < d && aVal < aPrevVal) ||
+ DistanceToBorder(myX, myA, myB) < myE1 ) // Condition optimization case near the border.
+ {
+ isInside = computeLocalExtremum(myX, val, myTmp);
+ }
}
aStepBestValue = (isInside && (val < d))? val : d;
aStepBestPoint = (isInside && (val < d))? myTmp : myX;
// Compute step in (j + 1) dimension according to scale.
if (j < myN)
{
- Standard_Real aUpperDimStep = myV(j) * myExpandCoeff(j + 1);
+ Standard_Real aUpperDimStep = Max(myV(j), myE2);
if (myV(j + 1) > aUpperDimStep)
{
if (aUpperDimStep > myMaxV(j + 1)) // Case of too big step.
--- /dev/null
+puts "========"
+puts "OCC27371"
+puts "========"
+puts ""
+##############################################
+# Regression: BRepExtrema works too much slower in 691 (from 670)
+##############################################
+restore [locate_data_file bug27371.brep] aShape
+explode aShape
+
+cpulimit 200
+
+# Check computation time
+chrono h reset; chrono h start
+for { set i 1 } { $i <= 100 } { incr i } {
+ distmini d aShape_1 aShape_2
+ distmini d aShape_2 aShape_1
+}
+chrono h stop; chrono h show
+
+regexp {CPU user time: (\d*)} [dchrono h show] dummy sec
+if {$sec > 1} {
+ puts "Error: too long computation time $sec seconds"
+} else {
+ puts "Computation time is OK"
+}
+
+# Check result of distance distance
+set absTol 1.0e-10
+set relTol 0.001
+set aDist_Exp 0.2
+set aDist [dval d_val]
+checkreal "Distance value check" $aDist $aDist_Exp $absTol $relTol
\ No newline at end of file