mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-03 17:56:21 +03:00
0029858: Modeling Data - Regression in GeomAPI_ExtremaCurveCurve
Fix Newton's minimum projection algorithm onto boundaries in case of conditional optimization. Add possibility to detect several optimal points at initialization of the math_GlobOptMin.
This commit is contained in:
parent
5a7808160e
commit
94beb42a68
@ -437,7 +437,7 @@ static void CurveHermite (const TopOpeBRepDS_DataStructure& DStr,
|
||||
GeomAdaptor_Curve L (Bezier);
|
||||
Extrema_ExtCC ext (C,L);
|
||||
if (ext.IsDone()){
|
||||
if (ext.NbExt()!=0){
|
||||
if (!ext.IsParallel() && ext.NbExt()!=0){
|
||||
Extrema_POnCurv POnC, POnL;
|
||||
ext.Points(1, POnC, POnL);
|
||||
if (POnC.Value().Distance(POnL.Value()) < Precision::Confusion())
|
||||
|
@ -243,8 +243,8 @@ static Standard_Boolean MinimizeDirection(math_Vector& P,
|
||||
// Make direction to go along the border
|
||||
for (Standard_Integer anIdx = 1; anIdx <= theLeft.Upper(); anIdx++)
|
||||
{
|
||||
if (Abs(P(anIdx) - theRight(anIdx)) < Precision::PConfusion() ||
|
||||
Abs(P(anIdx) - theLeft(anIdx)) < Precision::PConfusion())
|
||||
if ((Abs(P(anIdx) - theRight(anIdx)) < Precision::PConfusion() && Dir(anIdx) > 0.0) ||
|
||||
(Abs(P(anIdx) - theLeft(anIdx)) < Precision::PConfusion() && Dir(anIdx) < 0.0))
|
||||
{
|
||||
Dir(anIdx) = 0.0;
|
||||
}
|
||||
|
@ -69,7 +69,8 @@ math_GlobOptMin::math_GlobOptMin(math_MultipleVarFunction* theFunc,
|
||||
myMaxV(1, myN),
|
||||
myCellSize(0, myN - 1),
|
||||
myFilter(theFunc->NbVariables()),
|
||||
myCont(2)
|
||||
myCont(2),
|
||||
myF(Precision::Infinite())
|
||||
{
|
||||
Standard_Integer i;
|
||||
|
||||
@ -382,17 +383,6 @@ void math_GlobOptMin::computeInitialValues()
|
||||
myC = Max(aLipConst * aMinEps, aMinLC);
|
||||
else if (aLipConst > myC * aMaxEps)
|
||||
myC = Min(myC * aMaxEps, aMaxLC);
|
||||
|
||||
// Clear all solutions except one.
|
||||
if (myY.Size() != myN)
|
||||
{
|
||||
for(i = 1; i <= myN; i++)
|
||||
aBestPnt(i) = myY(i);
|
||||
myY.Clear();
|
||||
for(i = 1; i <= myN; i++)
|
||||
myY.Append(aBestPnt(i));
|
||||
}
|
||||
mySolCount = 1;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -453,37 +443,8 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
|
||||
aStepBestValue = (isInside && (val < d))? val : d;
|
||||
aStepBestPoint = (isInside && (val < d))? myTmp : myX;
|
||||
|
||||
// Solutions are close to each other
|
||||
// and it is allowed to have more than one solution.
|
||||
if (Abs(aStepBestValue - myF) < mySameTol * 0.01 &&
|
||||
!myIsFindSingleSolution)
|
||||
{
|
||||
if (!isStored(aStepBestPoint))
|
||||
{
|
||||
if ((aStepBestValue - myF) * myZ > 0.0)
|
||||
myF = aStepBestValue;
|
||||
for(i = 1; i <= myN; i++)
|
||||
myY.Append(aStepBestPoint(i));
|
||||
mySolCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// New best solution:
|
||||
// new point is out of (mySameTol * 0.01) surrounding or
|
||||
// new point is better than old + single point search.
|
||||
Standard_Real aFunctionalDelta = (aStepBestValue - myF) * myZ;
|
||||
if (aFunctionalDelta > mySameTol * 0.01 ||
|
||||
(aFunctionalDelta > 0.0 && myIsFindSingleSolution))
|
||||
{
|
||||
mySolCount = 0;
|
||||
myF = aStepBestValue;
|
||||
myY.Clear();
|
||||
for(i = 1; i <= myN; i++)
|
||||
myY.Append(aStepBestPoint(i));
|
||||
mySolCount++;
|
||||
|
||||
isFirstCellFilterInvoke = Standard_True;
|
||||
}
|
||||
// Check point and value on the current step to be optimal.
|
||||
checkAddCandidate(aStepBestPoint, aStepBestValue);
|
||||
|
||||
if (CheckFunctionalStopCriteria())
|
||||
return; // Best possible value is obtained.
|
||||
@ -639,34 +600,59 @@ Standard_Boolean math_GlobOptMin::CheckFunctionalStopCriteria()
|
||||
//=======================================================================
|
||||
void math_GlobOptMin::ComputeInitSol()
|
||||
{
|
||||
Standard_Real aCurrVal, aBestVal;
|
||||
math_Vector aCurrPnt(1, myN);
|
||||
math_Vector aBestPnt(1, myN);
|
||||
math_Vector aParamStep(1, myN);
|
||||
// Check functional value in midpoint, lower and upper border points and
|
||||
// in each point try to perform local optimization.
|
||||
aBestPnt = (myGlobA + myGlobB) * 0.5;
|
||||
myFunc->Value(aBestPnt, aBestVal);
|
||||
Standard_Real aVal;
|
||||
math_Vector aPnt(1, myN);
|
||||
|
||||
Standard_Integer i;
|
||||
for(i = 1; i <= 3; i++)
|
||||
// Check functional value in midpoint. It is necessary since local optimization
|
||||
// algorithm may fail and return nothing. This is a protection from uninitialized
|
||||
// variables.
|
||||
aPnt = (myGlobA + myGlobB) * 0.5;
|
||||
myFunc->Value(aPnt, aVal);
|
||||
checkAddCandidate(aPnt, aVal);
|
||||
|
||||
// Run local optimization from lower corner, midpoint, and upper corner.
|
||||
for(Standard_Integer i = 1; i <= 3; i++)
|
||||
{
|
||||
aCurrPnt = myA + (myB - myA) * (i - 1) / 2.0;
|
||||
aPnt = myA + (myB - myA) * (i - 1) / 2.0;
|
||||
|
||||
if(computeLocalExtremum(aCurrPnt, aCurrVal, aCurrPnt))
|
||||
if(computeLocalExtremum(aPnt, aVal, aPnt))
|
||||
checkAddCandidate(aPnt, aVal);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : checkAddCandidate
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void math_GlobOptMin::checkAddCandidate(const math_Vector& thePnt,
|
||||
const Standard_Real theValue)
|
||||
{
|
||||
if (Abs(theValue - myF) < mySameTol * 0.01 && // Value in point is close to optimal value.
|
||||
!myIsFindSingleSolution) // Several optimal solutions are allowed.
|
||||
{
|
||||
if (!isStored(thePnt))
|
||||
{
|
||||
// Local search tries to find better solution than current point.
|
||||
if (aCurrVal < aBestVal)
|
||||
{
|
||||
aBestVal = aCurrVal;
|
||||
aBestPnt = aCurrPnt;
|
||||
}
|
||||
if ((theValue - myF) * myZ > 0.0)
|
||||
myF = theValue;
|
||||
for (Standard_Integer j = 1; j <= myN; j++)
|
||||
myY.Append(thePnt(j));
|
||||
mySolCount++;
|
||||
}
|
||||
}
|
||||
|
||||
myF = aBestVal;
|
||||
myY.Clear();
|
||||
for(i = 1; i <= myN; i++)
|
||||
myY.Append(aBestPnt(i));
|
||||
mySolCount = 1;
|
||||
// New best solution:
|
||||
// new point is out of (mySameTol * 0.01) surrounding or
|
||||
// new point is better than old and single point search.
|
||||
Standard_Real aDelta = (theValue - myF) * myZ;
|
||||
if (aDelta > mySameTol * 0.01 ||
|
||||
(aDelta > 0.0 && myIsFindSingleSolution))
|
||||
{
|
||||
myF = theValue;
|
||||
myY.Clear();
|
||||
for (Standard_Integer j = 1; j <= myN; j++)
|
||||
myY.Append(thePnt(j));
|
||||
mySolCount = 1;
|
||||
|
||||
isFirstCellFilterInvoke = Standard_True;
|
||||
}
|
||||
}
|
||||
|
@ -232,6 +232,13 @@ private:
|
||||
//! Check presence of thePnt in GlobOpt sequence.
|
||||
Standard_Boolean isStored(const math_Vector &thePnt);
|
||||
|
||||
//! Check and add candidate point into solutions.
|
||||
//! @param thePnt Candidate point.
|
||||
//! @param theValue Function value in the candidate point.
|
||||
void checkAddCandidate(const math_Vector& thePnt,
|
||||
const Standard_Real theValue);
|
||||
|
||||
|
||||
// Input.
|
||||
math_MultipleVarFunction* myFunc;
|
||||
Standard_Integer myN;
|
||||
|
@ -195,8 +195,8 @@ void math_NewtonMinimum::Perform(math_MultipleVarFunctionWithHessian& F,
|
||||
// Nullify corresponding TheStep indexes.
|
||||
for(Standard_Integer anIdx = 1; anIdx <= myLeft.Upper(); anIdx++)
|
||||
{
|
||||
if (Abs(precedent->Value(anIdx) - myRight(anIdx)) < Precision::PConfusion() ||
|
||||
Abs(precedent->Value(anIdx) - myLeft(anIdx) ) < Precision::PConfusion())
|
||||
if ((Abs(precedent->Value(anIdx) - myRight(anIdx)) < Precision::PConfusion() && TheStep(anIdx) < 0.0) ||
|
||||
(Abs(precedent->Value(anIdx) - myLeft(anIdx) ) < Precision::PConfusion() && TheStep(anIdx) > 0.0) )
|
||||
{
|
||||
TheStep(anIdx) = 0.0;
|
||||
}
|
||||
|
21
tests/lowalgos/extcc/bug29858_01
Normal file
21
tests/lowalgos/extcc/bug29858_01
Normal file
@ -0,0 +1,21 @@
|
||||
puts "========"
|
||||
puts "OCC29858"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# Regression in GeomAPI_ExtremaCurveCurve
|
||||
#################################################
|
||||
|
||||
# Read input
|
||||
restore [locate_data_file bug29858_01_e1.brep] e1
|
||||
restore [locate_data_file bug29858_01_e2.brep] e2
|
||||
|
||||
# Extract geometry from topology
|
||||
mkcurve c1 e1
|
||||
mkcurve c2 e2
|
||||
|
||||
# Run extrema
|
||||
extrema c1 c2
|
||||
|
||||
# Check result
|
||||
checklength ext_1 -l 9.4224516867962155e-10 -eps 0.01
|
28
tests/lowalgos/extcc/bug29858_02
Normal file
28
tests/lowalgos/extcc/bug29858_02
Normal file
@ -0,0 +1,28 @@
|
||||
puts "========"
|
||||
puts "OCC29858"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# Regression in GeomAPI_ExtremaCurveCurve
|
||||
#################################################
|
||||
|
||||
# Read input
|
||||
restore [locate_data_file bug29858_02_e1.brep] e1
|
||||
restore [locate_data_file bug29858_02_e2.brep] e2
|
||||
|
||||
# Extract geometry from topology
|
||||
mkcurve c1 e1
|
||||
mkcurve c2 e2
|
||||
|
||||
# Run extrema
|
||||
set info [extrema c1 c2]
|
||||
|
||||
# Check result
|
||||
regexp {Extrema 1 is point : +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $info full x y z
|
||||
# Point check
|
||||
set good_x 0.001
|
||||
set good_y 0.0073371170841145797
|
||||
set good_z -0.083369169789921913
|
||||
checkreal "Intersection point x:" ${x} ${good_x} 0.01 0.01
|
||||
checkreal "Intersection point y:" ${y} ${good_y} 0.01 0.01
|
||||
checkreal "Intersection point z:" ${z} ${good_z} 0.01 0.01
|
28
tests/lowalgos/extcc/bug29858_03
Normal file
28
tests/lowalgos/extcc/bug29858_03
Normal file
@ -0,0 +1,28 @@
|
||||
puts "========"
|
||||
puts "OCC29858"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# Regression in GeomAPI_ExtremaCurveCurve
|
||||
#################################################
|
||||
|
||||
# Read input
|
||||
restore [locate_data_file bug29858_03_e1.brep] e1
|
||||
restore [locate_data_file bug29858_03_e2.brep] e2
|
||||
|
||||
# Extract geometry from topology
|
||||
mkcurve c1 e1
|
||||
mkcurve c2 e2
|
||||
|
||||
# Run extrema
|
||||
set info [extrema c1 c2]
|
||||
|
||||
# Check result
|
||||
regexp {Extrema 1 is point : +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $info full x y z
|
||||
# Point check
|
||||
set good_x 0.0
|
||||
set good_y 0.070710562195021642
|
||||
set good_z -0.65305318986891325
|
||||
checkreal "Intersection point x:" ${x} ${good_x} 0.01 0.01
|
||||
checkreal "Intersection point y:" ${y} ${good_y} 0.01 0.01
|
||||
checkreal "Intersection point z:" ${z} ${good_z} 0.01 0.01
|
27
tests/lowalgos/extcc/bug29858_04
Normal file
27
tests/lowalgos/extcc/bug29858_04
Normal file
@ -0,0 +1,27 @@
|
||||
puts "========"
|
||||
puts "OCC29858"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# Regression in GeomAPI_ExtremaCurveCurve
|
||||
#################################################
|
||||
|
||||
# Read input
|
||||
restore [locate_data_file bug29858_04_e1.brep] e1
|
||||
restore [locate_data_file bug29858_04_e2.brep] e2
|
||||
|
||||
# Extract geometry from topology
|
||||
mkcurve c1 e1
|
||||
mkcurve c2 e2
|
||||
|
||||
# Run extrema
|
||||
set info [extrema c1 c2]
|
||||
|
||||
# Amount Check
|
||||
if { [llength $info] != 2 } {
|
||||
puts "Error: Invalid extrema number in extrema output"
|
||||
}
|
||||
|
||||
# Check result
|
||||
checklength ext_1 -l 2.2204460492503131e-16 -eps 0.01
|
||||
checklength ext_2 -l 9.693032344962995e-16 -eps 0.01
|
Loading…
x
Reference in New Issue
Block a user