mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-14 13:30:48 +03:00
0029368: Incorrect intersection state of the intersection point of two 2d curves
In the algorithm math_FunctionRoots, improve the case when it is needed to find the extremum of the function. Earlier, to solve this task the method of gold section was used. With the patch, firstly the algorithm tries to find zero value of the derivative function. In most cases it gives precise result. Secondly, the algorithm tries to find zero value of the function using the old approach. The algorithm chooses the best solution among two computed by different methods. In the method PutStickPavesOnCurve of BOPAlgo_PaveFiller, forbid putting a vertex to the end of the curve if this end already has a vertex assigned to it. This allows getting rid of unwanted colliding of vertices. In the method UpdatePaveBlocks of BOPAlgo_PaveFiller, make the check for micro edges more precise. New category of tests "lowalgos" has been added. Tests for low level algorithms are to be put there. "2dinter" is a new group of tests in this category. Introduction of the new key for "2dintersect" command, allowing printing the intersection state for each point. It has the following syntax now: "2dintersect curve1 [curve2] [-tol tol] [-state]" Options: -tol - allows changing the intersection tolerance (default value is 1.e-3); -state - allows printing the intersection state for each point. Correct the test case bugs/modalg_7/bug28274 to make proper checks of the result.
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include <math_DirectPolynomialRoots.hxx>
|
||||
#include <math_FunctionRoots.hxx>
|
||||
#include <math_FunctionWithDerivative.hxx>
|
||||
#include <math_BracketedRoot.hxx>
|
||||
#include <Standard_RangeError.hxx>
|
||||
#include <StdFail_NotDone.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
@@ -37,6 +38,21 @@ static Standard_Boolean myDebug = 0;
|
||||
static Standard_Integer nbsolve = 0;
|
||||
#endif
|
||||
|
||||
class DerivFunction: public math_Function
|
||||
{
|
||||
math_FunctionWithDerivative *myF;
|
||||
|
||||
public:
|
||||
DerivFunction(math_FunctionWithDerivative& theF)
|
||||
: myF (&theF)
|
||||
{}
|
||||
|
||||
virtual Standard_Boolean Value(const Standard_Real theX, Standard_Real& theFval)
|
||||
{
|
||||
return myF->Derivative(theX, theFval);
|
||||
}
|
||||
};
|
||||
|
||||
static void AppendRoot(TColStd_SequenceOfReal& Sol,
|
||||
TColStd_SequenceOfInteger& NbStateSol,
|
||||
const Standard_Real X,
|
||||
@@ -415,78 +431,126 @@ math_FunctionRoots::math_FunctionRoots(math_FunctionWithDerivative& F,
|
||||
}
|
||||
}
|
||||
if(Rediscr) {
|
||||
//-- --------------------------------------------------
|
||||
//-- On recherche un extrema entre x0 et x3
|
||||
//-- x1 et x2 sont tels que x0<x1<x2<x3
|
||||
//-- et |f(x0)| > |f(x1)| et |f(x3)| > |f(x2)|
|
||||
//--
|
||||
//-- En entree : a=xm-dx b=xm c=xm+dx
|
||||
Standard_Real x0,x1,x2,x3,f0,f3;
|
||||
Standard_Real R=0.61803399;
|
||||
Standard_Real C=1.0-R;
|
||||
Standard_Real tolCR=NEpsX*10.0;
|
||||
f0=ptrval(im1);
|
||||
f3=ptrval(ip1);
|
||||
x0=xm-dx;
|
||||
x3=xm+dx;
|
||||
if(x0 < X0) x0=X0;
|
||||
if(x3 > XN) x3=XN;
|
||||
Standard_Boolean recherche_minimum = (f0>0.0);
|
||||
Standard_Real x0 = xm - dx;
|
||||
Standard_Real x3 = xm + dx;
|
||||
if (x0 < X0) x0 = X0;
|
||||
if (x3 > XN) x3 = XN;
|
||||
Standard_Real aSolX1 = 0., aSolX2 = 0.;
|
||||
Standard_Real aVal1 = 0., aVal2 = 0.;
|
||||
Standard_Real aDer1 = 0., aDer2 = 0.;
|
||||
Standard_Boolean isSol1 = Standard_False;
|
||||
Standard_Boolean isSol2 = Standard_False;
|
||||
//-- ----------------------------------------------------
|
||||
//-- Find minimum of the function |F| between x0 and x3
|
||||
//-- by searching for the zero of the function derivative
|
||||
DerivFunction aDerF(F);
|
||||
math_BracketedRoot aBR(aDerF, x0, x3, EpsX);
|
||||
if (aBR.IsDone())
|
||||
{
|
||||
aSolX1 = aBR.Root();
|
||||
F.Value(aSolX1, aVal1);
|
||||
aVal1 = Abs(aVal1);
|
||||
if (aVal1 < EpsF)
|
||||
{
|
||||
isSol1 = Standard_True;
|
||||
aDer1 = aBR.Value();
|
||||
}
|
||||
}
|
||||
|
||||
if(Abs(x3-xm) > Abs(x0-xm)) { x1=xm; x2=xm+C*(x3-xm); }
|
||||
else { x2=xm; x1=xm-C*(xm-x0); }
|
||||
Standard_Real f1,f2;
|
||||
F.Value(x1,f1); f1-=K;
|
||||
F.Value(x2,f2); f2-=K;
|
||||
//-- printf("\n *************** RECHERCHE MINIMUM **********\n");
|
||||
Standard_Real tolX = 0.001 * NEpsX;
|
||||
while(Abs(x3-x0) > tolCR*(Abs(x1)+Abs(x2)) && (Abs(x1 -x2) > tolX)) {
|
||||
//-- printf("\n (%10.5g,%10.5g) (%10.5g,%10.5g) (%10.5g,%10.5g) (%10.5g,%10.5g) ",
|
||||
//-- x0,f0,x1,f1,x2,f2,x3,f3);
|
||||
if(recherche_minimum) {
|
||||
if(f2<f1) {
|
||||
x0=x1; x1=x2; x2=R*x1+C*x3;
|
||||
f0=f1; f1=f2; F.Value(x2,f2); f2-=K;
|
||||
}
|
||||
else {
|
||||
x3=x2; x2=x1; x1=R*x2+C*x0;
|
||||
f3=f2; f2=f1; F.Value(x1,f1); f1-=K;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(f2>f1) {
|
||||
x0=x1; x1=x2; x2=R*x1+C*x3;
|
||||
f0=f1; f1=f2; F.Value(x2,f2); f2-=K;
|
||||
}
|
||||
else {
|
||||
x3=x2; x2=x1; x1=R*x2+C*x0;
|
||||
f3=f2; f2=f1; F.Value(x1,f1); f1-=K;
|
||||
}
|
||||
}
|
||||
//-- On ne fait pas que chercher des extremas. Il faut verifier
|
||||
//-- si on ne tombe pas sur une racine
|
||||
if(f1*f0 <0.0) {
|
||||
//-- printf("\n Recherche entre (%10.5g,%10.5g) (%10.5g,%10.5g) ",x0,f0,x1,f1);
|
||||
Solve(F,K,x0,f0,x1,f1,tol,NEpsX,Sol,NbStateSol);
|
||||
}
|
||||
if(f2*f3 <0.0) {
|
||||
//-- printf("\n Recherche entre (%10.5g,%10.5g) (%10.5g,%10.5g) ",x2,f2,x3,f3);
|
||||
Solve(F,K,x2,f2,x3,f3,tol,NEpsX,Sol,NbStateSol);
|
||||
}
|
||||
}
|
||||
if(f1<f2) {
|
||||
//-- x1,f(x1) minimum
|
||||
if(Abs(f1) < EpsF) {
|
||||
AppendRoot(Sol,NbStateSol,x1,F,K,NEpsX);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//-- x2.f(x2) minimum
|
||||
if(Abs(f2) < EpsF) {
|
||||
AppendRoot(Sol,NbStateSol,x2,F,K,NEpsX);
|
||||
}
|
||||
}
|
||||
} //-- Recherche d un extrema
|
||||
//-- --------------------------------------------------
|
||||
//-- On recherche un extrema entre x0 et x3
|
||||
//-- x1 et x2 sont tels que x0<x1<x2<x3
|
||||
//-- et |f(x0)| > |f(x1)| et |f(x3)| > |f(x2)|
|
||||
//--
|
||||
//-- En entree : a=xm-dx b=xm c=xm+dx
|
||||
Standard_Real x1, x2, f0, f3;
|
||||
Standard_Real R = 0.61803399;
|
||||
Standard_Real C = 1.0 - R;
|
||||
Standard_Real tolCR = NEpsX*10.0;
|
||||
f0 = ptrval(im1);
|
||||
f3 = ptrval(ip1);
|
||||
Standard_Boolean recherche_minimum = (f0 > 0.0);
|
||||
|
||||
if (Abs(x3 - xm) > Abs(x0 - xm)) { x1 = xm; x2 = xm + C*(x3 - xm); }
|
||||
else { x2 = xm; x1 = xm - C*(xm - x0); }
|
||||
Standard_Real f1, f2;
|
||||
F.Value(x1, f1); f1 -= K;
|
||||
F.Value(x2, f2); f2 -= K;
|
||||
//-- printf("\n *************** RECHERCHE MINIMUM **********\n");
|
||||
Standard_Real tolX = 0.001 * NEpsX;
|
||||
while (Abs(x3 - x0) > tolCR*(Abs(x1) + Abs(x2)) && (Abs(x1 - x2) > tolX)) {
|
||||
//-- printf("\n (%10.5g,%10.5g) (%10.5g,%10.5g) (%10.5g,%10.5g) (%10.5g,%10.5g) ",
|
||||
//-- x0,f0,x1,f1,x2,f2,x3,f3);
|
||||
if (recherche_minimum) {
|
||||
if (f2 < f1) {
|
||||
x0 = x1; x1 = x2; x2 = R*x1 + C*x3;
|
||||
f0 = f1; f1 = f2; F.Value(x2, f2); f2 -= K;
|
||||
}
|
||||
else {
|
||||
x3 = x2; x2 = x1; x1 = R*x2 + C*x0;
|
||||
f3 = f2; f2 = f1; F.Value(x1, f1); f1 -= K;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (f2 > f1) {
|
||||
x0 = x1; x1 = x2; x2 = R*x1 + C*x3;
|
||||
f0 = f1; f1 = f2; F.Value(x2, f2); f2 -= K;
|
||||
}
|
||||
else {
|
||||
x3 = x2; x2 = x1; x1 = R*x2 + C*x0;
|
||||
f3 = f2; f2 = f1; F.Value(x1, f1); f1 -= K;
|
||||
}
|
||||
}
|
||||
//-- On ne fait pas que chercher des extremas. Il faut verifier
|
||||
//-- si on ne tombe pas sur une racine
|
||||
if (f1*f0 < 0.0) {
|
||||
//-- printf("\n Recherche entre (%10.5g,%10.5g) (%10.5g,%10.5g) ",x0,f0,x1,f1);
|
||||
Solve(F, K, x0, f0, x1, f1, tol, NEpsX, Sol, NbStateSol);
|
||||
}
|
||||
if (f2*f3 < 0.0) {
|
||||
//-- printf("\n Recherche entre (%10.5g,%10.5g) (%10.5g,%10.5g) ",x2,f2,x3,f3);
|
||||
Solve(F, K, x2, f2, x3, f3, tol, NEpsX, Sol, NbStateSol);
|
||||
}
|
||||
}
|
||||
if ((recherche_minimum && f1<f2) || (!recherche_minimum && f1>f2)) {
|
||||
//-- x1,f(x1) minimum
|
||||
if (Abs(f1) < EpsF) {
|
||||
isSol2 = Standard_True;
|
||||
aSolX2 = x1;
|
||||
aVal2 = Abs(f1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//-- x2.f(x2) minimum
|
||||
if (Abs(f2) < EpsF) {
|
||||
isSol2 = Standard_True;
|
||||
aSolX2 = x2;
|
||||
aVal2 = Abs(f2);
|
||||
}
|
||||
}
|
||||
// Choose the best solution between aSolX1, aSolX2
|
||||
if (isSol1 && isSol2)
|
||||
{
|
||||
if (aVal2 - aVal1 > EpsF)
|
||||
AppendRoot(Sol, NbStateSol, aSolX1, F, K, NEpsX);
|
||||
else if (aVal1 - aVal2 > EpsF)
|
||||
AppendRoot(Sol, NbStateSol, aSolX2, F, K, NEpsX);
|
||||
else
|
||||
{
|
||||
aDer1 = Abs(aDer1);
|
||||
F.Derivative(aSolX2, aDer2);
|
||||
aDer2 = Abs(aDer2);
|
||||
if (aDer1 < aDer2)
|
||||
AppendRoot(Sol, NbStateSol, aSolX1, F, K, NEpsX);
|
||||
else
|
||||
AppendRoot(Sol, NbStateSol, aSolX2, F, K, NEpsX);
|
||||
}
|
||||
}
|
||||
else if (isSol1)
|
||||
AppendRoot(Sol, NbStateSol, aSolX1, F, K, NEpsX);
|
||||
else if(isSol2)
|
||||
AppendRoot(Sol, NbStateSol, aSolX2, F, K, NEpsX);
|
||||
} //-- Recherche d un extrema
|
||||
} //-- for
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user