1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-19 13:40:49 +03:00

0026329: Restore floating point signals handling in DRAW

Added DRAW command dsetsignal, resetting OSD signal handler with either armed or disabled FPE handler, according to an option.
If called without arguments, it sets FPE handler only if environment variable OSD_FPE is defined (with value different from 0).
On start, DRAW calls dsetsignal to set FPE signal if CSF_FPE is defined.
Test bugs fclasses bug6143 uses dsetsignal to set FPE handler unconditionally before the test command, and resets it to default at the end.

A number of changes in the code have been done in order to fix floating point exceptions that became generated after enabling signals:

- Global functions Sinh() and Cosh() defined in Standard_Real.hxx are improved to raise Standard_NumericError exception if argument is too big (greater than 710.47586), instead of relying on system treatment of floating point overflow. These functions are used instead of sinh and cosh in ElCLib.cxx.

- Maximal value of parameter on hyperbola is restricted by 23 (corresponding to ~1e10 in 3d) in order to avoid FP overflow in Extrema_GenExtCS.cxx, ShapeFix_EdgeProjAux.cxx.

- Interface of the root curve adaptor class Adaptor3d_Curve has been updated to add new virtual methods BasisCurve and OffsetValue. They complement the adaptor for the case of offset curves. These methods are used in Extrema_GenExtCS.cxx to restrict domain search in the case of offset of hyperbola, in order to get rid of floating point overflow. All classes inheriting Adaptor3d_Curve have been changed to implement the new virtual methods.

- Protection against division by zero has been implemented in ApproxInt_KnotTools.cxx, BRepClass3d_SClassifier.cxx, BRepGProp_Face.cxx, BRepMesh_FastDiscretFace.cxx, Geom2dGcc_Circ2d2TanOnIter.cxx, Geom2dInt_Geom2dCurveTool.cxx, IntPolyh_MaillageAffinage.cxx.

- Protection against calling of math functions of infinite arguments has been added in BRepCheck_Edge.cxx, BRepLib.cxx, CSLib_NormalPolyDef.cxx, Extrema_FuncExtPC.gxx, Extrema_GExtPC.gxx, Extrema_GLocateExtPC.gxx, Intf_InterferencePolygonPolyhedron.gxx, ShapeAnalysis_Surface.cxx, ShapeAnalysis_TransferParametersProj.cxx, ShapeAnalysis_Wire.cxx, math_FunctionSetRoot.cxx.

- Proper initialization of local variables is done in BOPAlgo_PaveFiller_6.cxx, XSDRAWSTLVRML.cxx.

- Inconsistent usage of Standard_Boolean* to access integer data in HLR (caused by #27772) is corrected

Some test cases have been updated to actual state.
This commit is contained in:
ifv
2016-08-09 20:12:59 +03:00
committed by kgv
parent 73594f7248
commit f4dee9bb20
48 changed files with 595 additions and 228 deletions

View File

@@ -55,6 +55,12 @@ Standard_Real Extrema_FuncExtPC::SearchOfTolerance()
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;
@@ -160,6 +166,13 @@ Standard_Boolean Extrema_FuncExtPC::Value (const Standard_Real U, Standard_Real&
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)

View File

@@ -204,7 +204,7 @@ void Extrema_GExtPC::Perform(const ThePoint& P)
}
// Solve on the first and last intervals.
if (mydist1 > Precision::SquareConfusion())
if (mydist1 > Precision::SquareConfusion() && !Precision::IsPositiveInfinite(mydist1))
{
ThePoint aP1, aP2;
TheVector aV1, aV2;
@@ -213,21 +213,23 @@ void Extrema_GExtPC::Perform(const ThePoint& P)
TheVector aBase1(P, aP1), aBase2(P, aP2);
Standard_Real aVal1 = aV1.Dot(aBase1); // Derivative of (C(u) - P)^2
Standard_Real aVal2 = aV2.Dot(aBase2); // Derivative of (C(u) - P)^2
// Derivatives have opposite signs - min or max inside of interval (sufficient condition).
// Necessary condition - when point lies on curve.
// Necessary condition - when derivative of point is too small.
if(aVal1 * aVal2 <= 0.0 ||
aBase1.Dot(aBase2) <= 0.0 ||
2.0 * Abs(aVal1) < Precision::Confusion() )
if(!(Precision::IsInfinite(aVal1) || Precision::IsInfinite(aVal2)))
{
myintuinf = aParam(aVal.Lower());
myintusup = aParam(aVal.Lower() + 1);
IntervalPerform(P);
// Derivatives have opposite signs - min or max inside of interval (sufficient condition).
// Necessary condition - when point lies on curve.
// Necessary condition - when derivative of point is too small.
if(aVal1 * aVal2 <= 0.0 ||
aBase1.Dot(aBase2) <= 0.0 ||
2.0 * Abs(aVal1) < Precision::Confusion() )
{
myintuinf = aParam(aVal.Lower());
myintusup = aParam(aVal.Lower() + 1);
IntervalPerform(P);
}
}
}
if (mydist2 > Precision::SquareConfusion())
if (mydist2 > Precision::SquareConfusion() && !Precision::IsPositiveInfinite(mydist2))
{
ThePoint aP1, aP2;
TheVector aV1, aV2;
@@ -237,16 +239,19 @@ void Extrema_GExtPC::Perform(const ThePoint& P)
Standard_Real aVal1 = aV1.Dot(aBase1); // Derivative of (C(u) - P)^2
Standard_Real aVal2 = aV2.Dot(aBase2); // Derivative of (C(u) - P)^2
// Derivatives have opposite signs - min or max inside of interval (sufficient condition).
// Necessary condition - when point lies on curve.
// Necessary condition - when derivative of point is too small.
if(aVal1 * aVal2 <= 0.0 ||
aBase1.Dot(aBase2) <= 0.0 ||
2.0 * Abs(aVal2) < Precision::Confusion() )
if(!(Precision::IsInfinite(aVal1) || Precision::IsInfinite(aVal2)))
{
myintuinf = aParam(aVal.Upper() - 1);
myintusup = aParam(aVal.Upper());
IntervalPerform(P);
// Derivatives have opposite signs - min or max inside of interval (sufficient condition).
// Necessary condition - when point lies on curve.
// Necessary condition - when derivative of point is too small.
if(aVal1 * aVal2 <= 0.0 ||
aBase1.Dot(aBase2) <= 0.0 ||
2.0 * Abs(aVal2) < Precision::Confusion() )
{
myintuinf = aParam(aVal.Upper() - 1);
myintusup = aParam(aVal.Upper());
IntervalPerform(P);
}
}
}

View File

@@ -187,6 +187,10 @@ void Extrema_GLocateExtPC::Perform(const ThePoint& P,
{
TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
s2sup = (TheVector(P, P1)*V1);
if(Precision::IsInfinite(s2sup) || Precision::IsInfinite(s1sup))
{
break;
}
if (s1sup*s2sup <= RealEpsilon())
{
// extremum:
@@ -220,6 +224,10 @@ void Extrema_GLocateExtPC::Perform(const ThePoint& P,
{
TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
s1inf = (TheVector(P, P1)*V1);
if(Precision::IsInfinite(s2inf) || Precision::IsInfinite(s1inf))
{
break;
}
if (s1inf*s2inf <= RealEpsilon())
{
// extremum:

View File

@@ -24,7 +24,9 @@
#include <Extrema_GlobOptFuncCS.hxx>
#include <Extrema_POnCurv.hxx>
#include <Extrema_POnSurf.hxx>
#include <Geom_Hyperbola.hxx>
#include <Geom_Line.hxx>
#include <Geom_OffsetCurve.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <math_FunctionSetRoot.hxx>
#include <math_PSO.hxx>
@@ -35,9 +37,53 @@
#include <Standard_TypeMismatch.hxx>
#include <StdFail_NotDone.hxx>
#include <TColgp_HArray1OfPnt.hxx>
#include <Adaptor3d_HSurface.hxx>
#include <Geom_TrimmedCurve.hxx>
const Standard_Real aMaxParamVal = 1.0e+10;
const Standard_Real MaxParamVal = 1.0e+10;
const Standard_Real aBorderDivisor = 1.0e+4;
const Standard_Real HyperbolaLimit = 23.; //ln(MaxParamVal)
// restrict maximal parameter on hyperbola to avoid FPE
static Standard_Real GetCurvMaxParamVal (const Adaptor3d_Curve& theC)
{
if (theC.GetType() == GeomAbs_Hyperbola)
{
return HyperbolaLimit;
}
if (theC.GetType() == GeomAbs_OffsetCurve)
{
Handle(Geom_Curve) aBC (theC.OffsetCurve()->BasisCurve());
Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast (aBC);
if (! aTC.IsNull())
{
aBC = aTC->BasisCurve();
}
if (aBC->IsKind (STANDARD_TYPE(Geom_Hyperbola)))
return HyperbolaLimit;
}
return MaxParamVal;
}
// restrict maximal parameter on surfaces based on hyperbola to avoid FPE
static void GetSurfMaxParamVals (const Adaptor3d_Surface& theS,
Standard_Real& theUmax, Standard_Real& theVmax)
{
theUmax = theVmax = MaxParamVal;
if (theS.GetType() == GeomAbs_SurfaceOfExtrusion)
{
theUmax = GetCurvMaxParamVal (theS.BasisCurve()->Curve());
}
else if (theS.GetType() == GeomAbs_SurfaceOfRevolution)
{
theVmax = GetCurvMaxParamVal (theS.BasisCurve()->Curve());
}
else if (theS.GetType() == GeomAbs_OffsetSurface)
{
GetSurfMaxParamVals (theS.BasisSurface()->Surface(), theUmax, theVmax);
}
}
//=======================================================================
//function : Extrema_GenExtCS
@@ -126,15 +172,32 @@ void Extrema_GenExtCS::Initialize (const Adaptor3d_Surface& S,
myvsup = Vsup;
mytol2 = Tol2;
const Standard_Real aTrimMaxU = Precision::IsInfinite (myusup) ? aMaxParamVal : myusup;
const Standard_Real aTrimMinU = Precision::IsInfinite (myumin) ? -aMaxParamVal : myumin;
const Standard_Real aTrimMaxV = Precision::IsInfinite (myvsup) ? aMaxParamVal : myvsup;
const Standard_Real aTrimMinV = Precision::IsInfinite (myvmin) ? -aMaxParamVal : myvmin;
Standard_Real umaxpar, vmaxpar;
GetSurfMaxParamVals(*myS, umaxpar, vmaxpar);
const Standard_Real aMinU = aTrimMinU + (aTrimMaxU - aTrimMinU) / aBorderDivisor;
const Standard_Real aMinV = aTrimMinV + (aTrimMaxV - aTrimMinV) / aBorderDivisor;
const Standard_Real aMaxU = aTrimMaxU - (aTrimMaxU - aTrimMinU) / aBorderDivisor;
const Standard_Real aMaxV = aTrimMaxV - (aTrimMaxV - aTrimMinV) / aBorderDivisor;
if(Precision::IsInfinite (myusup))
{
myusup = umaxpar;
}
if(Precision::IsInfinite (myumin))
{
myumin = -umaxpar;
}
if(Precision::IsInfinite (myvsup))
{
myvsup = vmaxpar;
}
if(Precision::IsInfinite (myvmin))
{
myvmin = -vmaxpar;
}
Standard_Real du = (myusup - myumin) / aBorderDivisor;
Standard_Real dv = (myvsup - myvmin) / aBorderDivisor;
const Standard_Real aMinU = myumin + du;
const Standard_Real aMinV = myvmin + dv;
const Standard_Real aMaxU = myusup - du;
const Standard_Real aMaxV = myvsup - dv;
const Standard_Real aStepSU = (aMaxU - aMinU) / myusample;
const Standard_Real aStepSV = (aMaxV - aMinV) / myvsample;
@@ -184,17 +247,12 @@ void Extrema_GenExtCS::Perform (const Adaptor3d_Curve& C,
// Modif de lvt pour trimer la surface non pas aux infinis mais a +/- 10000
Standard_Real trimusup = myusup, trimumin = myumin,trimvsup = myvsup,trimvmin = myvmin;
if (Precision::IsInfinite(trimusup)){
trimusup = aMaxParamVal;
Standard_Real aCMaxVal = GetCurvMaxParamVal (C);
if (Precision::IsInfinite(mytsup)){
mytsup = aCMaxVal;
}
if (Precision::IsInfinite(trimvsup)){
trimvsup = aMaxParamVal;
}
if (Precision::IsInfinite(trimumin)){
trimumin = -aMaxParamVal;
}
if (Precision::IsInfinite(trimvmin)){
trimvmin = -aMaxParamVal;
if (Precision::IsInfinite(mytmin)){
mytmin = -aCMaxVal;
}
//
math_Vector Tol(1, 3);