1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +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,123 +77,55 @@
// 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 or surfaces otherwise the resulted parameter(s) may be wrong.
// To make search process more common the tolerance value is used to define
// the proximity of point to curve or surface. It is clear that this tolerance
// 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 MaxDist
// 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;
//=======================================================================
//function : Parameter
//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
//=======================================================================
Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom_Curve)& Curve,
const gp_Pnt& Point,
const Standard_Real Tolerance,
const Standard_Real MaxDist,
Standard_Real& U)
{
if( Curve.IsNull() ) return Standard_False;
//
U = 0.;
Standard_Real aTol = (Tolerance < MAXTOLERANCEGEOM) ? Tolerance : MAXTOLERANCEGEOM;
aTol *= aTol;
Standard_Real aTol = MaxDist * MaxDist;
//
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) )
GeomAdaptor_Curve aGAC(Curve);
Extrema_ExtPC extrema(Point,aGAC);
//
if( !extrema.IsDone() ) return Standard_False;
//
Standard_Integer n = extrema.NbExt();
if( n <= 0 ) return Standard_False;
//
Standard_Integer i = 0, iMin = 0;
Standard_Real Dist2Min = RealLast();
for( i = 1; i <= n; i++ )
{
Standard_Real D = 0.;
if( KindOfCurve == STANDARD_TYPE (Geom_Line) )
if (extrema.SquareDistance(i) < Dist2Min)
{
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;
}
iMin = i;
Dist2Min = extrema.SquareDistance(i);
}
}
// 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) )
if( iMin != 0 && Dist2Min <= aTol )
{
GeomAdaptor_Curve aGAC(Curve);
Extrema_ExtPC extrema(Point,aGAC);
if( !extrema.IsDone() ) return Standard_False;
Standard_Integer n = extrema.NbExt();
if( n <= 0 ) return Standard_False;
Standard_Integer i = 0, iMin = 0;
Standard_Real Dist2Min = 1.e+100;
for( i = 1; i <= n; i++ )
{
if (extrema.SquareDistance(i) < Dist2Min)
{
iMin = i;
Dist2Min = extrema.SquareDistance(i);
}
}
if( iMin != 0 && Dist2Min <= aTol ) U = (extrema.Point(iMin)).Parameter();
else return Standard_False;
U = (extrema.Point(iMin)).Parameter();
}
else { return Standard_False; }
else
{
return Standard_False;
}
return Standard_True;
}
@ -201,13 +133,13 @@ Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom_Curve)& Curve,
//=======================================================================
//function : Parameters
//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
//=======================================================================
Standard_Boolean GeomLib_Tool::Parameters(const Handle(Geom_Surface)& Surface,
const gp_Pnt& Point,
const Standard_Real Tolerance,
const Standard_Real MaxDist,
Standard_Real& U,
Standard_Real& V)
{
@ -215,106 +147,36 @@ Standard_Boolean GeomLib_Tool::Parameters(const Handle(Geom_Surface)& Surface,
//
U = 0.;
V = 0.;
Standard_Real aTol = (Tolerance < MAXTOLERANCEGEOM) ? Tolerance : MAXTOLERANCEGEOM;
aTol *= aTol;
Standard_Real aTol = MaxDist * MaxDist;
//
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) )
GeomAdaptor_Surface aGAS(Surface);
Standard_Real aTolU = PARTOLERANCE, aTolV = PARTOLERANCE;
//
Extrema_ExtPS extrema(Point,aGAS,aTolU,aTolV);
//
if( !extrema.IsDone() ) return Standard_False;
//
Standard_Integer n = extrema.NbExt();
if( n <= 0 ) return Standard_False;
//
Standard_Real Dist2Min = RealLast();
Standard_Integer i = 0, iMin = 0;
for( i = 1; i <= n; i++ )
{
Standard_Real D = 0.;
if( KindOfSurface == STANDARD_TYPE (Geom_Plane) )
if( extrema.SquareDistance(i) < Dist2Min )
{
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);
Dist2Min = extrema.SquareDistance(i);
iMin = i;
}
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) )
if( iMin != 0 && Dist2Min <= aTol)
{
GeomAdaptor_Surface aGAS(Surface);
Standard_Real aTolU = PARTOLERANCE, aTolV = PARTOLERANCE;
Extrema_ExtPS extrema(Point,aGAS,aTolU,aTolV);
if( !extrema.IsDone() ) return Standard_False;
Standard_Integer n = extrema.NbExt();
if( n <= 0 ) return Standard_False;
Standard_Real Dist2Min = 1.e+100;
Standard_Integer i = 0, iMin = 0;
for( i = 1; i <= n; i++ )
{
if( extrema.SquareDistance(i) < Dist2Min )
{
Dist2Min = extrema.SquareDistance(i);
iMin = i;
}
}
if( iMin != 0 && Dist2Min <= aTol) extrema.Point(iMin).Parameter(U,V);
else return Standard_False;
extrema.Point(iMin).Parameter(U,V);
}
else
{
return Standard_False;
}
else { return Standard_False; }
return Standard_True;
@ -323,114 +185,43 @@ Standard_Boolean GeomLib_Tool::Parameters(const Handle(Geom_Surface)& Surface,
//=======================================================================
//function : Parameter
//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
//=======================================================================
Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom2d_Curve)& Curve,
const gp_Pnt2d& Point,
const Standard_Real Tolerance,
const Standard_Real MaxDist,
Standard_Real& U)
{
if( Curve.IsNull() ) return Standard_False;
//
U = 0.;
Standard_Real aTol = (Tolerance < MAXTOLERANCEGEOM) ? Tolerance : MAXTOLERANCEGEOM;
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 aTol = MaxDist * MaxDist;
//
Geom2dAdaptor_Curve aGAC(Curve);
Extrema_ExtPC2d extrema(Point,aGAC);
if( !extrema.IsDone() ) return Standard_False;
Standard_Integer n = extrema.NbExt();
if( n <= 0 ) return Standard_False;
Standard_Integer i = 0, iMin = 0;
Standard_Real Dist2Min = RealLast();
for ( i = 1; i <= n; i++ )
{
Standard_Real D = 0.;
if( KindOfCurve == STANDARD_TYPE (Geom2d_Line) )
if( extrema.SquareDistance(i) < Dist2Min )
{
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);
Dist2Min = extrema.SquareDistance(i);
iMin = i;
}
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) )
if( iMin != 0 && Dist2Min <= aTol )
{
Geom2dAdaptor_Curve aGAC(Curve);
Extrema_ExtPC2d extrema(Point,aGAC);
if( !extrema.IsDone() ) return Standard_False;
Standard_Integer n = extrema.NbExt();
if( n <= 0 ) return Standard_False;
Standard_Integer i = 0, iMin = 0;
Standard_Real Dist2Min = 1.e+100;
for ( i = 1; i <= n; i++ )
{
if( extrema.SquareDistance(i) < Dist2Min )
{
Dist2Min = extrema.SquareDistance(i);
iMin = i;
}
}
if( iMin != 0 && Dist2Min <= aTol ) U = (extrema.Point(iMin)).Parameter();
else return Standard_False;
U = (extrema.Point(iMin)).Parameter();
}
else
{
return Standard_False;
}
else { return Standard_False; }
return Standard_True;
}

View File

@ -31,14 +31,13 @@ class gp_Pnt2d;
//! 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
//! curve or a surface. The point must be located either
//! on the curve (surface) itself or relatively to the latter at
//! a distance less than the tolerance value.
//! Return FALSE if the point is beyond the tolerance
//! curve or a surface. To get the valid result the point must be located rather close
//! to the curve (surface) or at least to allow getting unambiguous result
//! (do not put point at center of circle...),
//! 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.
//! 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
{
public:
@ -48,16 +47,16 @@ public:
//! Extracts the parameter of a 3D point lying on a 3D curve
//! or at a distance less than the tolerance value.
Standard_EXPORT static Standard_Boolean Parameter (const Handle(Geom_Curve)& Curve, const gp_Pnt& Point, const Standard_Real Tolerance, Standard_Real& U);
//! 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 MaxDist, Standard_Real& U);
//! Extracts the parameter of a 3D point lying on a surface
//! or at a distance less than the tolerance 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);
//! 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 MaxDist, Standard_Real& U, Standard_Real& V);
//! Extracts the parameter of a 2D point lying on a 2D curve
//! or at a distance less than the tolerance value.
Standard_EXPORT static Standard_Boolean Parameter (const Handle(Geom2d_Curve)& Curve, const gp_Pnt2d& Point, const Standard_Real Tolerance, Standard_Real& U);
//! 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 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."
}