1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0025004: Extrema curve/curve incorrect result

Fixed bug in extrema clustering algorithm.
Tolerances changing is available now.
Testcase with Branin function added.

Test cases for issue CR25004
This commit is contained in:
aml
2014-07-03 16:00:36 +04:00
committed by apn
parent 5b14f80036
commit 5493d33411
11 changed files with 402 additions and 83 deletions

View File

@@ -163,6 +163,7 @@ void Extrema_ExtCC::Perform()
Standard_NullObject_Raise_if (!myC[0] || !myC[1], "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]));
myDone = Standard_False;
mypoints.Clear();
mySqDist.Clear();

View File

@@ -44,18 +44,21 @@ is
---Purpose: It calculates all the distances.
-- The function F(u,v)=distance(C1(u),C2(v)) has an
-- extremum when gradient(f)=0. The algorithm uses
-- Evtushenko's global optimization solver..
-- Evtushenko's global optimization solver.
Create (C1: Curve1; C2: Curve2; Uinf, Usup, Vinf, Vsup: Real) returns GenExtCC;
---Purpose: Calculates all the distances as above
-- between Uinf and Usup for C1 and between Vinf and Vsup
-- for C2.
SetParams(me: in out; C1: Curve1; C2: Curve2; Uinf, Usup, Vinf, Vsup: Real)
SetParams (me: in out; C1: Curve1; C2: Curve2; Uinf, Usup, Vinf, Vsup: Real)
---Purpose: Set params in case of empty constructor is usage.
is static;
Perform(me: in out) is static;
SetTolerance (me: in out; Tol: Real);
---Purpose:
Perform (me: in out) is static;
---Purpose: Performs calculations.
@@ -93,12 +96,13 @@ is
is static;
fields
myLowBorder : Vector from math;
myUppBorder : Vector from math;
mySolCount : Integer from Standard;
myPoints1 : SequenceOfReal from TColStd;
myPoints2 : SequenceOfReal from TColStd;
myC : Address from Standard [2];
myDone : Boolean;
myCurveMinTol : Real from Standard;
myLowBorder : Vector from math;
myUppBorder : Vector from math;
mySolCount : Integer from Standard;
myPoints1 : SequenceOfReal from TColStd;
myPoints2 : SequenceOfReal from TColStd;
myC : Address from Standard [2];
myDone : Boolean;
end GenExtCC;

View File

@@ -22,6 +22,10 @@
#include <TColStd_Array1OfReal.hxx>
#include <Precision.hxx>
//=======================================================================
//function : Extrema_GenExtCC
//purpose :
//=======================================================================
Extrema_GenExtCC::Extrema_GenExtCC()
: myLowBorder(1,2),
myUppBorder(1,2),
@@ -29,8 +33,12 @@ Extrema_GenExtCC::Extrema_GenExtCC()
{
}
Extrema_GenExtCC::Extrema_GenExtCC (const Curve1& C1,
const Curve2& C2)
//=======================================================================
//function : Extrema_GenExtCC
//purpose :
//=======================================================================
Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
const Curve2& C2)
: myLowBorder(1,2),
myUppBorder(1,2),
myDone(Standard_False)
@@ -41,15 +49,19 @@ Extrema_GenExtCC::Extrema_GenExtCC (const Curve1& C1,
myLowBorder(2) = C2.FirstParameter();
myUppBorder(1) = C1.LastParameter();
myUppBorder(2) = C2.LastParameter();
myCurveMinTol = 1.0e-9;
}
Extrema_GenExtCC::Extrema_GenExtCC (const Curve1& C1,
const Curve2& C2,
const Standard_Real Uinf,
const Standard_Real Usup,
const Standard_Real Vinf,
const Standard_Real Vsup)
//=======================================================================
//function : Extrema_GenExtCC
//purpose :
//=======================================================================
Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
const Curve2& C2,
const Standard_Real Uinf,
const Standard_Real Usup,
const Standard_Real Vinf,
const Standard_Real Vsup)
: myLowBorder(1,2),
myUppBorder(1,2),
myDone(Standard_False)
@@ -60,14 +72,19 @@ Extrema_GenExtCC::Extrema_GenExtCC (const Curve1& C1,
myLowBorder(2) = Vinf;
myUppBorder(1) = Usup;
myUppBorder(2) = Vsup;
myCurveMinTol = 1.0e-9;
}
void Extrema_GenExtCC::SetParams (const Curve1& C1,
const Curve2& C2,
const Standard_Real Uinf,
const Standard_Real Usup,
const Standard_Real Vinf,
const Standard_Real Vsup)
//=======================================================================
//function : SetParams
//purpose :
//=======================================================================
void Extrema_GenExtCC::SetParams(const Curve1& C1,
const Curve2& C2,
const Standard_Real Uinf,
const Standard_Real Usup,
const Standard_Real Vinf,
const Standard_Real Vsup)
{
myC[0] = (Standard_Address)&C1;
myC[1] = (Standard_Address)&C2;
@@ -77,8 +94,20 @@ void Extrema_GenExtCC::SetParams (const Curve1& C1,
myUppBorder(2) = Vsup;
}
//=============================================================================
void Extrema_GenExtCC::Perform ()
//=======================================================================
//function : SetTolerance
//purpose :
//=======================================================================
void Extrema_GenExtCC::SetTolerance(Standard_Real theTol)
{
myCurveMinTol = theTol;
}
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
void Extrema_GenExtCC::Perform()
{
myDone = Standard_False;
@@ -95,6 +124,10 @@ void Extrema_GenExtCC::Perform ()
math_MultipleVarFunction *aFunc = new Extrema_GlobOptFuncCCC2(C1, C2);
math_GlobOptMin aFinder(aFunc, myLowBorder, myUppBorder);
Standard_Real aDiscTol = 1.0e-2;
Standard_Real aValueTol = 1.0e-2;
Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
aFinder.SetTol(aDiscTol, aSameTol);
Standard_Integer i,j,k;
math_Vector aFirstBorderInterval(1,2);
@@ -114,12 +147,15 @@ void Extrema_GenExtCC::Perform ()
aFinder.Perform();
aCurrF = aFinder.GetF();
if (aCurrF < aF + Precision::Confusion())
if (aCurrF < aF + aSameTol * aValueTol)
{
if (aCurrF > Abs(aF - Precision::Confusion()) || (aCurrF < 1.0e-15 && aF < 1.0e-15))
if (aCurrF > aF - aSameTol * aValueTol)
{
Standard_Integer myTmpSolCount = aFinder.NbExtrema();
if (aCurrF < aF)
aF = aCurrF;
math_Vector sol(1,2);
Standard_Integer myTmpSolCount = aFinder.NbExtrema();
for(k = 1; k <= myTmpSolCount; k++)
{
aFinder.Points(k, sol);
@@ -127,7 +163,7 @@ void Extrema_GenExtCC::Perform ()
myPoints2.Append(sol(2));
}
mySolCount += myTmpSolCount;
} // if (aCurrF > aF - Precision::Confusion())
} // if (aCurrF > aF - aSameTol * aValueTol)
else
{
aF = aCurrF;
@@ -142,7 +178,7 @@ void Extrema_GenExtCC::Perform ()
myPoints2.Append(sol(2));
}
} // else
} //if (aCurrF < aF + Precision::Confusion())
} //if (aCurrF < aF + aSameTol * aValueTol)
}
}
@@ -151,10 +187,10 @@ void Extrema_GenExtCC::Perform ()
{
for(j = i + 1; j <= mySolCount; j++)
{
if ((myPoints1(i) - myPoints1(j)) < (myUppBorder(1) - myLowBorder(1)) * Precision::Confusion() &&
(myPoints2(i) - myPoints2(j)) < (myUppBorder(2) - myLowBorder(2)) * Precision::Confusion())
if (Abs(myPoints1(i) - myPoints1(j)) < (myUppBorder(1) - myLowBorder(1)) * Precision::Confusion() &&
Abs(myPoints2(i) - myPoints2(j)) < (myUppBorder(2) - myLowBorder(2)) * Precision::Confusion())
{
// Points with indexes i and j is in same cluster, delete j point from it.
// Points with indexes i and j is in same cluster, delete j point from extrema array.
myPoints1.Remove(j);
myPoints2.Remove(j);
j--;
@@ -166,34 +202,46 @@ void Extrema_GenExtCC::Perform ()
delete aFunc;
myDone = Standard_True;
}
//=============================================================================
Standard_Boolean Extrema_GenExtCC::IsDone () const
//=======================================================================
//function : IsDone
//purpose :
//=======================================================================
Standard_Boolean Extrema_GenExtCC::IsDone() const
{
return myDone;
}
//=============================================================================
Standard_Integer Extrema_GenExtCC::NbExt () const
//=======================================================================
//function : NbExt
//purpose :
//=======================================================================
Standard_Integer Extrema_GenExtCC::NbExt() const
{
StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::NbExt()")
return mySolCount;
}
//=============================================================================
Standard_Real Extrema_GenExtCC::SquareDistance (const Standard_Integer N) const
//=======================================================================
//function : SquareDistance
//purpose :
//=======================================================================
Standard_Real Extrema_GenExtCC::SquareDistance(const Standard_Integer N) const
{
StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::SquareDistance()")
Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::SquareDistance()")
return Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)).SquareDistance(Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
}
//=============================================================================
void Extrema_GenExtCC::Points (const Standard_Integer N,
POnC& P1,
POnC& P2) const
//=======================================================================
//function : Points
//purpose :
//=======================================================================
void Extrema_GenExtCC::Points(const Standard_Integer N,
POnC& P1,
POnC& P2) const
{
StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::Points()")
Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::Points()")