1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +03:00

0027110: Regression: Draw command "parameters" can not compute parameter on the line.

Useless variable MAXTOLERANCEGEOM is removed in order to allow to place point at any distance from curve/surface.
Algorithm is simplified: particular calculations for analytical geometry are removed, only using of Extrema_... is kept.

Test case for issue #27110
This commit is contained in:
ifv 2016-01-26 16:56:23 +03:00 committed by bugmaster
parent 671b6fe0cc
commit e2ca538ae6
3 changed files with 101 additions and 294 deletions

View File

@ -77,110 +77,38 @@
// The functions Parameter(s) are used to compute parameter(s) of point // The functions Parameter(s) are used to compute parameter(s) of point
// on curves and surfaces. The main rule is that tested point must lied // on curves and surfaces. The main rule is that tested point must lied
// on curves or surfaces otherwise the resulted parameter(s) may be wrong. // on curves or surfaces otherwise the resulted parameter(s) may be wrong.
// To make search process more common the tolerance value is used to define // To make search process more common the MaxDist value is used to define
// the proximity of point to curve or surface. It is clear that this tolerance // the proximity of point to curve or surface. It is clear that this MaxDist
// value can't be too high to be not in conflict with previous rule. // value can't be too high to be not in conflict with previous rule.
static const Standard_Real MAXTOLERANCEGEOM = 1.e-4;
static const Standard_Real PARTOLERANCE = 1.e-9; static const Standard_Real PARTOLERANCE = 1.e-9;
//======================================================================= //=======================================================================
//function : Parameter //function : Parameter
//purpose : Get parameter on curve of given point //purpose : Get parameter on curve of given point
// return FALSE if point is far from curve than tolerance // return FALSE if point is far from curve than MaxDist
// or computation fails // or computation fails
//======================================================================= //=======================================================================
Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom_Curve)& Curve, Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom_Curve)& Curve,
const gp_Pnt& Point, const gp_Pnt& Point,
const Standard_Real Tolerance, const Standard_Real MaxDist,
Standard_Real& U) Standard_Real& U)
{ {
if( Curve.IsNull() ) return Standard_False; if( Curve.IsNull() ) return Standard_False;
// //
U = 0.; U = 0.;
Standard_Real aTol = (Tolerance < MAXTOLERANCEGEOM) ? Tolerance : MAXTOLERANCEGEOM; Standard_Real aTol = MaxDist * MaxDist;
aTol *= aTol;
// //
Handle(Standard_Type) KindOfCurve = Curve->DynamicType();
// process analitical curves
if( KindOfCurve == STANDARD_TYPE (Geom_Line) ||
KindOfCurve == STANDARD_TYPE (Geom_Circle) ||
KindOfCurve == STANDARD_TYPE (Geom_Ellipse) ||
KindOfCurve == STANDARD_TYPE (Geom_Parabola) ||
KindOfCurve == STANDARD_TYPE (Geom_Hyperbola) )
{
Standard_Real D = 0.;
if( KindOfCurve == STANDARD_TYPE (Geom_Line) )
{
Handle(Geom_Line) aGL = Handle(Geom_Line)::DownCast(Curve);
gp_Lin aLin = aGL->Lin();
D = aLin.SquareDistance(Point);
if(D > aTol)
{
return Standard_False;
}
U = ElCLib::Parameter(aLin,Point);
}
else if( KindOfCurve == STANDARD_TYPE (Geom_Circle) )
{
Handle(Geom_Circle) aGC = Handle(Geom_Circle)::DownCast(Curve);
gp_Circ aCirc = aGC->Circ();
D = aCirc.SquareDistance(Point);
if(D > aTol)
{
return Standard_False;
}
U = ElCLib::Parameter(aCirc,Point);
}
else if( KindOfCurve == STANDARD_TYPE (Geom_Ellipse) )
{
Handle(Geom_Ellipse) aGE = Handle(Geom_Ellipse)::DownCast(Curve);
gp_Elips anElips = aGE->Elips();
U = ElCLib::Parameter(anElips,Point);
D = Point.SquareDistance(aGE->Value(U));
if(D > aTol)
{
return Standard_False;
}
}
else if( KindOfCurve == STANDARD_TYPE (Geom_Parabola) )
{
Handle(Geom_Parabola) aGP = Handle(Geom_Parabola)::DownCast(Curve);
gp_Parab aParab = aGP->Parab();
U = ElCLib::Parameter(aParab,Point);
D = Point.SquareDistance(aGP->Value(U));
if(D > aTol)
{
return Standard_False;
}
}
else if( KindOfCurve == STANDARD_TYPE (Geom_Hyperbola) )
{
Handle(Geom_Hyperbola) aGH = Handle(Geom_Hyperbola)::DownCast(Curve);
gp_Hypr aHypr = aGH->Hypr();
U = ElCLib::Parameter(aHypr,Point);
D = Point.SquareDistance(aGH->Value(U));
if(D > aTol)
{
return Standard_False;
}
}
}
// process parametrical curves
else if( KindOfCurve == STANDARD_TYPE (Geom_BSplineCurve) ||
KindOfCurve == STANDARD_TYPE (Geom_BezierCurve) ||
KindOfCurve == STANDARD_TYPE (Geom_TrimmedCurve) ||
KindOfCurve == STANDARD_TYPE (Geom_OffsetCurve) )
{
GeomAdaptor_Curve aGAC(Curve); GeomAdaptor_Curve aGAC(Curve);
Extrema_ExtPC extrema(Point,aGAC); Extrema_ExtPC extrema(Point,aGAC);
//
if( !extrema.IsDone() ) return Standard_False; if( !extrema.IsDone() ) return Standard_False;
//
Standard_Integer n = extrema.NbExt(); Standard_Integer n = extrema.NbExt();
if( n <= 0 ) return Standard_False; if( n <= 0 ) return Standard_False;
//
Standard_Integer i = 0, iMin = 0; Standard_Integer i = 0, iMin = 0;
Standard_Real Dist2Min = 1.e+100; Standard_Real Dist2Min = RealLast();
for( i = 1; i <= n; i++ ) for( i = 1; i <= n; i++ )
{ {
if (extrema.SquareDistance(i) < Dist2Min) if (extrema.SquareDistance(i) < Dist2Min)
@ -189,10 +117,14 @@ Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom_Curve)& Curve,
Dist2Min = extrema.SquareDistance(i); Dist2Min = extrema.SquareDistance(i);
} }
} }
if( iMin != 0 && Dist2Min <= aTol ) U = (extrema.Point(iMin)).Parameter(); if( iMin != 0 && Dist2Min <= aTol )
else return Standard_False; {
U = (extrema.Point(iMin)).Parameter();
}
else
{
return Standard_False;
} }
else { return Standard_False; }
return Standard_True; return Standard_True;
@ -201,13 +133,13 @@ Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom_Curve)& Curve,
//======================================================================= //=======================================================================
//function : Parameters //function : Parameters
//purpose : Get parameters on surface of given point //purpose : Get parameters on surface of given point
// return FALSE if point is far from surface than tolerance // return FALSE if point is far from surface than MaxDist
// or computation fails // or computation fails
//======================================================================= //=======================================================================
Standard_Boolean GeomLib_Tool::Parameters(const Handle(Geom_Surface)& Surface, Standard_Boolean GeomLib_Tool::Parameters(const Handle(Geom_Surface)& Surface,
const gp_Pnt& Point, const gp_Pnt& Point,
const Standard_Real Tolerance, const Standard_Real MaxDist,
Standard_Real& U, Standard_Real& U,
Standard_Real& V) Standard_Real& V)
{ {
@ -215,93 +147,19 @@ Standard_Boolean GeomLib_Tool::Parameters(const Handle(Geom_Surface)& Surface,
// //
U = 0.; U = 0.;
V = 0.; V = 0.;
Standard_Real aTol = (Tolerance < MAXTOLERANCEGEOM) ? Tolerance : MAXTOLERANCEGEOM; Standard_Real aTol = MaxDist * MaxDist;
aTol *= aTol;
// //
Handle(Standard_Type) KindOfSurface = Surface->DynamicType();
// process analitical surfaces
if( KindOfSurface == STANDARD_TYPE (Geom_Plane) ||
KindOfSurface == STANDARD_TYPE (Geom_CylindricalSurface) ||
KindOfSurface == STANDARD_TYPE (Geom_ConicalSurface) ||
KindOfSurface == STANDARD_TYPE (Geom_SphericalSurface) ||
KindOfSurface == STANDARD_TYPE (Geom_ToroidalSurface) )
{
Standard_Real D = 0.;
if( KindOfSurface == STANDARD_TYPE (Geom_Plane) )
{
Handle(Geom_Plane) aGP = Handle(Geom_Plane)::DownCast(Surface);
gp_Pln aPlane = aGP->Pln();
D = aPlane.SquareDistance(Point);
if(D > aTol)
{
return Standard_False;
}
ElSLib::Parameters (aPlane,Point,U,V);
}
else if( KindOfSurface == STANDARD_TYPE (Geom_CylindricalSurface) )
{
Handle(Geom_CylindricalSurface) aGC = Handle(Geom_CylindricalSurface)::DownCast(Surface);
gp_Cylinder aCylinder = aGC->Cylinder();
ElSLib::Parameters(aCylinder,Point,U,V);
D = Point.SquareDistance(aGC->Value(U, V));
if(D > aTol)
{
return Standard_False;
}
}
else if( KindOfSurface == STANDARD_TYPE (Geom_ConicalSurface) )
{
Handle(Geom_ConicalSurface) aGC = Handle(Geom_ConicalSurface)::DownCast(Surface);
gp_Cone aCone = aGC->Cone();
ElSLib::Parameters(aCone,Point,U,V);
D = Point.SquareDistance(aGC->Value(U, V));
if(D > aTol)
{
return Standard_False;
}
}
else if( KindOfSurface == STANDARD_TYPE (Geom_SphericalSurface) )
{
Handle(Geom_SphericalSurface) aGS = Handle(Geom_SphericalSurface)::DownCast(Surface);
gp_Sphere aSphere = aGS->Sphere();
ElSLib::Parameters(aSphere,Point,U,V);
D = Point.SquareDistance(aGS->Value(U, V));
if(D > aTol)
{
return Standard_False;
}
}
else if( KindOfSurface == STANDARD_TYPE (Geom_ToroidalSurface) )
{
Handle(Geom_ToroidalSurface) aTS = Handle(Geom_ToroidalSurface)::DownCast(Surface);
gp_Torus aTorus = aTS->Torus();
ElSLib::Parameters(aTorus,Point,U,V);
D = Point.SquareDistance(aTS->Value(U, V));
if(D > aTol)
{
return Standard_False;
}
}
else return Standard_False;
}
// process parametrical surfaces
else if( KindOfSurface == STANDARD_TYPE (Geom_BSplineSurface) ||
KindOfSurface == STANDARD_TYPE (Geom_BezierSurface) ||
KindOfSurface == STANDARD_TYPE (Geom_RectangularTrimmedSurface) ||
KindOfSurface == STANDARD_TYPE (Geom_OffsetSurface) ||
KindOfSurface == STANDARD_TYPE (Geom_SurfaceOfLinearExtrusion) ||
KindOfSurface == STANDARD_TYPE (Geom_SurfaceOfRevolution) )
{
GeomAdaptor_Surface aGAS(Surface); GeomAdaptor_Surface aGAS(Surface);
Standard_Real aTolU = PARTOLERANCE, aTolV = PARTOLERANCE; Standard_Real aTolU = PARTOLERANCE, aTolV = PARTOLERANCE;
//
Extrema_ExtPS extrema(Point,aGAS,aTolU,aTolV); Extrema_ExtPS extrema(Point,aGAS,aTolU,aTolV);
//
if( !extrema.IsDone() ) return Standard_False; if( !extrema.IsDone() ) return Standard_False;
//
Standard_Integer n = extrema.NbExt(); Standard_Integer n = extrema.NbExt();
if( n <= 0 ) return Standard_False; if( n <= 0 ) return Standard_False;
//
Standard_Real Dist2Min = 1.e+100; Standard_Real Dist2Min = RealLast();
Standard_Integer i = 0, iMin = 0; Standard_Integer i = 0, iMin = 0;
for( i = 1; i <= n; i++ ) for( i = 1; i <= n; i++ )
{ {
@ -311,10 +169,14 @@ Standard_Boolean GeomLib_Tool::Parameters(const Handle(Geom_Surface)& Surface,
iMin = i; iMin = i;
} }
} }
if( iMin != 0 && Dist2Min <= aTol) extrema.Point(iMin).Parameter(U,V); if( iMin != 0 && Dist2Min <= aTol)
else return Standard_False; {
extrema.Point(iMin).Parameter(U,V);
}
else
{
return Standard_False;
} }
else { return Standard_False; }
return Standard_True; return Standard_True;
@ -323,102 +185,27 @@ Standard_Boolean GeomLib_Tool::Parameters(const Handle(Geom_Surface)& Surface,
//======================================================================= //=======================================================================
//function : Parameter //function : Parameter
//purpose : Get parameter on curve of given point //purpose : Get parameter on curve of given point
// return FALSE if point is far from curve than tolerance // return FALSE if point is far from curve than MaxDist
// or computation fails // or computation fails
//======================================================================= //=======================================================================
Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom2d_Curve)& Curve, Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom2d_Curve)& Curve,
const gp_Pnt2d& Point, const gp_Pnt2d& Point,
const Standard_Real Tolerance, const Standard_Real MaxDist,
Standard_Real& U) Standard_Real& U)
{ {
if( Curve.IsNull() ) return Standard_False; if( Curve.IsNull() ) return Standard_False;
// //
U = 0.; U = 0.;
Standard_Real aTol = (Tolerance < MAXTOLERANCEGEOM) ? Tolerance : MAXTOLERANCEGEOM; Standard_Real aTol = MaxDist * MaxDist;
aTol *= aTol; //
Handle(Standard_Type) KindOfCurve = Curve->DynamicType();
// process analytical curves
if( KindOfCurve == STANDARD_TYPE (Geom2d_Line) ||
KindOfCurve == STANDARD_TYPE (Geom2d_Circle) ||
KindOfCurve == STANDARD_TYPE (Geom2d_Ellipse) ||
KindOfCurve == STANDARD_TYPE (Geom2d_Parabola) ||
KindOfCurve == STANDARD_TYPE (Geom2d_Hyperbola) )
{
Standard_Real D = 0.;
if( KindOfCurve == STANDARD_TYPE (Geom2d_Line) )
{
Handle(Geom2d_Line) aGL = Handle(Geom2d_Line)::DownCast(Curve);
gp_Lin2d aLin = aGL->Lin2d();
D = aLin.SquareDistance(Point);
if(D > aTol)
{
return Standard_False;
}
U = ElCLib::Parameter(aLin,Point);
}
else if( KindOfCurve == STANDARD_TYPE (Geom2d_Circle) )
{
Handle(Geom2d_Circle) aGC = Handle(Geom2d_Circle)::DownCast(Curve);
gp_Circ2d aCirc = aGC->Circ2d();
D = aCirc.SquareDistance(Point);
if(D > aTol)
{
return Standard_False;
}
U = ElCLib::Parameter(aCirc,Point);
}
else if( KindOfCurve == STANDARD_TYPE (Geom2d_Ellipse) )
{
Handle(Geom2d_Ellipse) aGE = Handle(Geom2d_Ellipse)::DownCast(Curve);
gp_Elips2d anElips = aGE->Elips2d();
U = ElCLib::Parameter(anElips,Point);
D = Point.SquareDistance(aGE->Value(U));
if(D > aTol)
{
return Standard_False;
}
}
else if( KindOfCurve == STANDARD_TYPE (Geom2d_Parabola) )
{
Handle(Geom2d_Parabola) aGP = Handle(Geom2d_Parabola)::DownCast(Curve);
gp_Parab2d aParab = aGP->Parab2d();
U = ElCLib::Parameter(aParab,Point);
D = Point.SquareDistance(aGP->Value(U));
if(D > aTol)
{
return Standard_False;
}
}
else if( KindOfCurve == STANDARD_TYPE (Geom2d_Hyperbola) )
{
Handle(Geom2d_Hyperbola) aGH = Handle(Geom2d_Hyperbola)::DownCast(Curve);
gp_Hypr2d aHypr = aGH->Hypr2d();
U = ElCLib::Parameter(aHypr,Point);
D = Point.SquareDistance(aGH->Value(U));
if(D > aTol)
{
return Standard_False;
}
}
else return Standard_False;
}
// process parametrical curves
else if( KindOfCurve == STANDARD_TYPE (Geom2d_BSplineCurve) ||
KindOfCurve == STANDARD_TYPE (Geom2d_BezierCurve) ||
KindOfCurve == STANDARD_TYPE (Geom2d_TrimmedCurve) ||
KindOfCurve == STANDARD_TYPE (Geom2d_OffsetCurve) )
{
Geom2dAdaptor_Curve aGAC(Curve); Geom2dAdaptor_Curve aGAC(Curve);
Extrema_ExtPC2d extrema(Point,aGAC); Extrema_ExtPC2d extrema(Point,aGAC);
if( !extrema.IsDone() ) return Standard_False; if( !extrema.IsDone() ) return Standard_False;
Standard_Integer n = extrema.NbExt(); Standard_Integer n = extrema.NbExt();
if( n <= 0 ) return Standard_False; if( n <= 0 ) return Standard_False;
Standard_Integer i = 0, iMin = 0; Standard_Integer i = 0, iMin = 0;
Standard_Real Dist2Min = 1.e+100; Standard_Real Dist2Min = RealLast();
for ( i = 1; i <= n; i++ ) for ( i = 1; i <= n; i++ )
{ {
if( extrema.SquareDistance(i) < Dist2Min ) if( extrema.SquareDistance(i) < Dist2Min )
@ -427,10 +214,14 @@ Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom2d_Curve)& Curve,
iMin = i; iMin = i;
} }
} }
if( iMin != 0 && Dist2Min <= aTol ) U = (extrema.Point(iMin)).Parameter(); if( iMin != 0 && Dist2Min <= aTol )
else return Standard_False; {
U = (extrema.Point(iMin)).Parameter();
}
else
{
return Standard_False;
} }
else { return Standard_False; }
return Standard_True; return Standard_True;
} }

View File

@ -31,14 +31,13 @@ class gp_Pnt2d;
//! Provides various methods with Geom2d and Geom curves and surfaces. //! Provides various methods with Geom2d and Geom curves and surfaces.
//! The methods of this class compute the parameter(s) of a given point on a //! The methods of this class compute the parameter(s) of a given point on a
//! curve or a surface. The point must be located either //! curve or a surface. To get the valid result the point must be located rather close
//! on the curve (surface) itself or relatively to the latter at //! to the curve (surface) or at least to allow getting unambiguous result
//! a distance less than the tolerance value. //! (do not put point at center of circle...),
//! Return FALSE if the point is beyond the tolerance //! but choice of "trust" distance between curve/surface and point is
//! responcibility of user (parameter MaxDist).
//! Return FALSE if the point is beyond the MaxDist
//! limit or if computation fails. //! limit or if computation fails.
//! Max Tolerance value is currently limited to 1.e-4 for
//! geometrical curves and 1.e-3 for BSpline, Bezier and
//! other parametrical curves.
class GeomLib_Tool class GeomLib_Tool
{ {
public: public:
@ -48,16 +47,16 @@ public:
//! Extracts the parameter of a 3D point lying on a 3D curve //! Extracts the parameter of a 3D point lying on a 3D curve
//! or at a distance less than the tolerance value. //! or at a distance less than the MaxDist value.
Standard_EXPORT static Standard_Boolean Parameter (const Handle(Geom_Curve)& Curve, const gp_Pnt& Point, const Standard_Real Tolerance, Standard_Real& U); Standard_EXPORT static Standard_Boolean Parameter (const Handle(Geom_Curve)& Curve, const gp_Pnt& Point, const Standard_Real MaxDist, Standard_Real& U);
//! Extracts the parameter of a 3D point lying on a surface //! Extracts the parameter of a 3D point lying on a surface
//! or at a distance less than the tolerance value. //! or at a distance less than the MaxDist value.
Standard_EXPORT static Standard_Boolean Parameters (const Handle(Geom_Surface)& Surface, const gp_Pnt& Point, const Standard_Real Tolerance, Standard_Real& U, Standard_Real& V); Standard_EXPORT static Standard_Boolean Parameters (const Handle(Geom_Surface)& Surface, const gp_Pnt& Point, const Standard_Real MaxDist, Standard_Real& U, Standard_Real& V);
//! Extracts the parameter of a 2D point lying on a 2D curve //! Extracts the parameter of a 2D point lying on a 2D curve
//! or at a distance less than the tolerance value. //! or at a distance less than the MaxDist value.
Standard_EXPORT static Standard_Boolean Parameter (const Handle(Geom2d_Curve)& Curve, const gp_Pnt2d& Point, const Standard_Real Tolerance, Standard_Real& U); Standard_EXPORT static Standard_Boolean Parameter (const Handle(Geom2d_Curve)& Curve, const gp_Pnt2d& Point, const Standard_Real MaxDist, Standard_Real& U);

View File

@ -0,0 +1,17 @@
puts "========"
puts "OCC27110"
puts "========"
puts ""
###############################################################################
# Regression: Draw command "parameters" can not compute parameter on the line
###############################################################################
restore [locate_data_file bug27110-ClosedWireEdge.brep] e1
mkcurve c1 e1
parameters c1 800.0 0.001 0 0.001 U
set bug_info [dump U]
set bug_info [string trim [string range $bug_info [expr {[string last "\n" $bug_info] + 1}] [expr {[string length $bug_info] - 1}]]]
if {$bug_info != 800} {
puts "ERROR: OCC27110 is reproduced. Parameters U is not equal 800."
}