mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-04 13:13:25 +03:00
Macro NO_CXX_EXCEPTION was removed from code. Method Raise() was replaced by explicit throw statement. Method Standard_Failure::Caught() was replaced by normal C++mechanism of exception transfer. Method Standard_Failure::Caught() is deprecated now. Eliminated empty constructors. Updated samples. Eliminate empty method ChangeValue from NCollection_Map class. Removed not operable methods from NCollection classes.
427 lines
12 KiB
Plaintext
427 lines
12 KiB
Plaintext
// Copyright (c) 1995-1999 Matra Datavision
|
|
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
#include <Standard_TypeMismatch.hxx>
|
|
#include <Precision.hxx>
|
|
static const Standard_Real TolFactor = 1.e-12;
|
|
static const Standard_Real MinTol = 1.e-20;
|
|
static const Standard_Real MinStep = 1e-7;
|
|
|
|
static const Standard_Integer MaxOrder = 3;
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Fonction permettant de rechercher une distance extremale entre un point P et
|
|
une courbe C (en partant d'un point approche C(u0)).
|
|
Cette classe herite de math_FunctionWithDerivative et est utilisee par
|
|
les algorithmes math_FunctionRoot et math_FunctionRoots.
|
|
Si on note D1c et D2c les derivees premiere et seconde:
|
|
{ F(u) = (C(u)-P).D1c(u)/ ||Du||}
|
|
{ DF(u) = ||Du|| + (C(u)-P).D2c(u)/||Du|| - F(u)*Duu*Du/||Du||**2
|
|
|
|
|
|
{ F(u) = (C(u)-P).D1c(u) }
|
|
{ DF(u) = D1c(u).D1c(u) + (C(u)-P).D2c(u)
|
|
= ||D1c(u)|| ** 2 + (C(u)-P).D2c(u) }
|
|
----------------------------------------------------------------------------*/
|
|
|
|
Standard_Real Extrema_FuncExtPC::SearchOfTolerance()
|
|
{
|
|
const Standard_Integer NPoint = 10;
|
|
const Standard_Real aStep = (myUsupremum - myUinfium)/(Standard_Real)NPoint;
|
|
|
|
Standard_Integer aNum = 0;
|
|
Standard_Real aMax = -Precision::Infinite(); //Maximum value of 1st derivative
|
|
//(it is computed with using NPoint point)
|
|
|
|
do
|
|
{
|
|
Standard_Real u = myUinfium + aNum*aStep; //parameter for every point
|
|
if(u > myUsupremum)
|
|
u = myUsupremum;
|
|
|
|
Pnt Ptemp; //empty point (is not used below)
|
|
Vec VDer; // 1st derivative vector
|
|
Tool::D1(*((Curve*)myC), u, Ptemp, VDer);
|
|
|
|
if(Precision::IsInfinite(VDer.X()) || Precision::IsInfinite(VDer.Y()))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Standard_Real vm = VDer.Magnitude();
|
|
if(vm > aMax)
|
|
aMax = vm;
|
|
}
|
|
while(++aNum < NPoint+1);
|
|
|
|
return Max(aMax*TolFactor,MinTol);
|
|
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
Extrema_FuncExtPC::Extrema_FuncExtPC():
|
|
myU(0.),
|
|
myD1f(0.)
|
|
{
|
|
myPinit = Standard_False;
|
|
myCinit = Standard_False;
|
|
myD1Init = Standard_False;
|
|
|
|
SubIntervalInitialize(0.0,0.0);
|
|
myMaxDerivOrder = 0;
|
|
myTol=MinTol;
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
Extrema_FuncExtPC::Extrema_FuncExtPC (const Pnt& P,
|
|
const Curve& C): myU(0.), myD1f(0.)
|
|
{
|
|
myP = P;
|
|
myC = (Standard_Address)&C;
|
|
myPinit = Standard_True;
|
|
myCinit = Standard_True;
|
|
myD1Init = Standard_False;
|
|
|
|
SubIntervalInitialize(Tool::FirstParameter(*((Curve*)myC)),
|
|
Tool::LastParameter(*((Curve*)myC)));
|
|
|
|
switch(Tool::GetType(*((Curve*)myC)))
|
|
{
|
|
case GeomAbs_BezierCurve:
|
|
case GeomAbs_BSplineCurve:
|
|
case GeomAbs_OffsetCurve:
|
|
case GeomAbs_OtherCurve:
|
|
myMaxDerivOrder = MaxOrder;
|
|
myTol = SearchOfTolerance();
|
|
break;
|
|
default:
|
|
myMaxDerivOrder = 0;
|
|
myTol=MinTol;
|
|
break;
|
|
}
|
|
}
|
|
//=============================================================================
|
|
|
|
void Extrema_FuncExtPC::Initialize(const Curve& C)
|
|
{
|
|
myC = (Standard_Address)&C;
|
|
myCinit = Standard_True;
|
|
myPoint.Clear();
|
|
mySqDist.Clear();
|
|
myIsMin.Clear();
|
|
|
|
SubIntervalInitialize(Tool::FirstParameter(*((Curve*)myC)),
|
|
Tool::LastParameter(*((Curve*)myC)));
|
|
|
|
switch(Tool::GetType(*((Curve*)myC)))
|
|
{
|
|
case GeomAbs_BezierCurve:
|
|
case GeomAbs_BSplineCurve:
|
|
case GeomAbs_OffsetCurve:
|
|
case GeomAbs_OtherCurve:
|
|
myMaxDerivOrder = MaxOrder;
|
|
myTol = SearchOfTolerance();
|
|
break;
|
|
default:
|
|
myMaxDerivOrder = 0;
|
|
myTol=MinTol;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
void Extrema_FuncExtPC::SetPoint(const Pnt& P)
|
|
{
|
|
myP = P;
|
|
myPinit = Standard_True;
|
|
myPoint.Clear();
|
|
mySqDist.Clear();
|
|
myIsMin.Clear();
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
|
|
Standard_Boolean Extrema_FuncExtPC::Value (const Standard_Real U, Standard_Real& F)
|
|
{
|
|
if (!myPinit || !myCinit)
|
|
throw Standard_TypeMismatch("No init");
|
|
|
|
myU = U;
|
|
Vec D1c;
|
|
Tool::D1(*((Curve*)myC),myU,myPc,D1c);
|
|
|
|
if(Precision::IsInfinite(D1c.X()) || Precision::IsInfinite(D1c.Y()))
|
|
{
|
|
F = Precision::Infinite();
|
|
return Standard_False;
|
|
}
|
|
|
|
Standard_Real Ndu = D1c.Magnitude();
|
|
|
|
if(myMaxDerivOrder != 0)
|
|
{
|
|
if (Ndu <= myTol) // Cas Singulier (PMN 22/04/1998)
|
|
{
|
|
const Standard_Real DivisionFactor = 1.e-3;
|
|
Standard_Real du;
|
|
if((myUsupremum >= RealLast()) || (myUinfium <= RealFirst()))
|
|
du = 0.0;
|
|
else
|
|
du = myUsupremum-myUinfium;
|
|
|
|
const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
|
|
//Derivative is approximated by Taylor-series
|
|
|
|
Standard_Integer n = 1; //Derivative order
|
|
Vec V;
|
|
Standard_Boolean IsDeriveFound;
|
|
|
|
do
|
|
{
|
|
V = Tool::DN(*((Curve*)myC),myU,++n);
|
|
Ndu = V.Magnitude();
|
|
IsDeriveFound = (Ndu > myTol);
|
|
}
|
|
while(!IsDeriveFound && n < myMaxDerivOrder);
|
|
|
|
if(IsDeriveFound)
|
|
{
|
|
Standard_Real u;
|
|
|
|
if(myU-myUinfium < aDelta)
|
|
u = myU+aDelta;
|
|
else
|
|
u = myU-aDelta;
|
|
|
|
Pnt P1, P2;
|
|
Tool::D0(*((Curve*)myC),Min(myU, u),P1);
|
|
Tool::D0(*((Curve*)myC),Max(myU, u),P2);
|
|
|
|
Vec V1(P1,P2);
|
|
Standard_Real aDirFactor = V.Dot(V1);
|
|
|
|
if(aDirFactor < 0.0)
|
|
D1c = -V;
|
|
else
|
|
D1c = V;
|
|
}//if(IsDeriveFound)
|
|
else
|
|
{
|
|
//Derivative is approximated by three points
|
|
|
|
Pnt Ptemp; //(0,0,0)-coordinate
|
|
Pnt P1, P2, P3;
|
|
Standard_Boolean IsParameterGrown;
|
|
|
|
if(myU-myUinfium < 2*aDelta)
|
|
{
|
|
Tool::D0(*((Curve*)myC),myU,P1);
|
|
Tool::D0(*((Curve*)myC),myU+aDelta,P2);
|
|
Tool::D0(*((Curve*)myC),myU+2*aDelta,P3);
|
|
IsParameterGrown = Standard_True;
|
|
}
|
|
else
|
|
{
|
|
Tool::D0(*((Curve*)myC),myU-2*aDelta,P1);
|
|
Tool::D0(*((Curve*)myC),myU-aDelta,P2);
|
|
Tool::D0(*((Curve*)myC),myU,P3);
|
|
IsParameterGrown = Standard_False;
|
|
}
|
|
|
|
Vec V1(Ptemp,P1), V2(Ptemp,P2), V3(Ptemp,P3);
|
|
|
|
if(IsParameterGrown)
|
|
D1c=-3*V1+4*V2-V3;
|
|
else
|
|
D1c=V1-4*V2+3*V3;
|
|
}
|
|
Ndu = D1c.Magnitude();
|
|
}//(if (Ndu <= myTol)) condition
|
|
}//if(myMaxDerivOrder != 0)
|
|
|
|
if (Ndu <= MinTol)
|
|
{
|
|
//Warning: 1st derivative is equal to zero!
|
|
return Standard_False;
|
|
}
|
|
|
|
Vec PPc (myP,myPc);
|
|
F = PPc.Dot(D1c)/Ndu;
|
|
return Standard_True;
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
Standard_Boolean Extrema_FuncExtPC::Derivative (const Standard_Real U, Standard_Real& D1f)
|
|
{
|
|
if (!myPinit || !myCinit) throw Standard_TypeMismatch();
|
|
Standard_Real F;
|
|
return Values(U,F,D1f); /* on fait appel a Values pour simplifier la
|
|
sauvegarde de l'etat. */
|
|
}
|
|
//=============================================================================
|
|
|
|
Standard_Boolean Extrema_FuncExtPC::Values (const Standard_Real U,
|
|
Standard_Real& F,
|
|
Standard_Real& D1f)
|
|
{
|
|
if (!myPinit || !myCinit)
|
|
throw Standard_TypeMismatch("No init");
|
|
|
|
Pnt myPc_old = myPc, myP_old = myP;
|
|
|
|
if(Value(U,F) == Standard_False)
|
|
{
|
|
//Warning: No function value found!;
|
|
|
|
myD1Init = Standard_False;
|
|
return Standard_False;
|
|
}
|
|
|
|
myU = U;
|
|
myPc = myPc_old;
|
|
myP = myP_old;
|
|
|
|
Vec D1c,D2c;
|
|
Tool::D2(*((Curve*)myC),myU,myPc,D1c,D2c);
|
|
|
|
Standard_Real Ndu = D1c.Magnitude();
|
|
if (Ndu <= myTol) // Cas Singulier (PMN 22/04/1998)
|
|
{
|
|
//Derivative is approximated by three points
|
|
|
|
//Attention: aDelta value must be greater than same value for "Value(...)"
|
|
// function to avoid of points' collisions.
|
|
const Standard_Real DivisionFactor = 0.01;
|
|
Standard_Real du;
|
|
if((myUsupremum >= RealLast()) || (myUinfium <= RealFirst()))
|
|
du = 0.0;
|
|
else
|
|
du = myUsupremum-myUinfium;
|
|
|
|
const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
|
|
|
|
Standard_Real F1, F2, F3;
|
|
|
|
if(myU-myUinfium < 2*aDelta)
|
|
{
|
|
F1=F;
|
|
//const Standard_Real U1 = myU;
|
|
const Standard_Real U2 = myU + aDelta;
|
|
const Standard_Real U3 = myU + aDelta * 2.0;
|
|
|
|
if(!((Value(U2,F2)) && (Value(U3,F3))))
|
|
{
|
|
//There are many points close to singularity points and
|
|
//which have zero-derivative. Try to decrease aDelta variable's value.
|
|
|
|
myD1Init = Standard_False;
|
|
return Standard_False;
|
|
}
|
|
|
|
//After calling of Value(...) function variable myU will be redeterminated.
|
|
//So we must return it previous value.
|
|
D1f=(-3*F1+4*F2-F3)/(2.0*aDelta);
|
|
}
|
|
else
|
|
{
|
|
F3 = F;
|
|
const Standard_Real U1 = myU - aDelta * 2.0;
|
|
const Standard_Real U2 = myU - aDelta;
|
|
//const Standard_Real U3 = myU;
|
|
|
|
if(!((Value(U2,F2)) && (Value(U1,F1))))
|
|
{
|
|
//There are many points close to singularity points and
|
|
//which have zero-derivative. Try to decrease aDelta variable's value.
|
|
myD1Init = Standard_False;
|
|
return Standard_False;
|
|
}
|
|
//After calling of Value(...) function variable myU will be redeterminated.
|
|
//So we must return it previous value.
|
|
D1f=(F1-4*F2+3*F3)/(2.0*aDelta);
|
|
}
|
|
myU = U;
|
|
myPc = myPc_old;
|
|
myP = myP_old;
|
|
}
|
|
else
|
|
{
|
|
Vec PPc (myP,myPc);
|
|
D1f = Ndu + (PPc.Dot(D2c)/Ndu) - F*(D1c.Dot(D2c))/(Ndu*Ndu);
|
|
}
|
|
|
|
myD1f = D1f;
|
|
|
|
myD1Init = Standard_True;
|
|
return Standard_True;
|
|
}
|
|
//=============================================================================
|
|
|
|
Standard_Integer Extrema_FuncExtPC::GetStateNumber ()
|
|
{
|
|
if (!myPinit || !myCinit) throw Standard_TypeMismatch();
|
|
mySqDist.Append(myPc.SquareDistance(myP));
|
|
|
|
// It is necessary to always compute myD1f.
|
|
myD1Init = Standard_True;
|
|
Standard_Real FF, DD;
|
|
Values(myU, FF, DD);
|
|
|
|
Standard_Integer IntVal = 0;
|
|
if (myD1f > 0.0)
|
|
{
|
|
IntVal = 1;
|
|
}
|
|
|
|
myIsMin.Append(IntVal);
|
|
myPoint.Append(POnC(myU,myPc));
|
|
return 0;
|
|
}
|
|
//=============================================================================
|
|
|
|
Standard_Integer Extrema_FuncExtPC::NbExt () const { return mySqDist.Length(); }
|
|
//=============================================================================
|
|
|
|
Standard_Real Extrema_FuncExtPC::SquareDistance (const Standard_Integer N) const
|
|
{
|
|
if (!myPinit || !myCinit) throw Standard_TypeMismatch();
|
|
return mySqDist.Value(N);
|
|
}
|
|
//=============================================================================
|
|
Standard_Boolean Extrema_FuncExtPC::IsMin (const Standard_Integer N) const
|
|
{
|
|
if (!myPinit || !myCinit) throw Standard_TypeMismatch();
|
|
return (myIsMin.Value(N) == 1);
|
|
}
|
|
//=============================================================================
|
|
const POnC & Extrema_FuncExtPC::Point (const Standard_Integer N) const
|
|
{
|
|
if (!myPinit || !myCinit) throw Standard_TypeMismatch();
|
|
return myPoint.Value(N);
|
|
}
|
|
//=============================================================================
|
|
|
|
void Extrema_FuncExtPC::SubIntervalInitialize(const Standard_Real theUfirst, const Standard_Real theUlast)
|
|
{
|
|
myUinfium = theUfirst;
|
|
myUsupremum = theUlast;
|
|
}
|