diff --git a/src/GeomLib/GeomLib_Tool.cxx b/src/GeomLib/GeomLib_Tool.cxx index daa44083f3..4996027d3e 100644 --- a/src/GeomLib/GeomLib_Tool.cxx +++ b/src/GeomLib/GeomLib_Tool.cxx @@ -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; } diff --git a/src/GeomLib/GeomLib_Tool.hxx b/src/GeomLib/GeomLib_Tool.hxx index adde730f88..5746a6d155 100644 --- a/src/GeomLib/GeomLib_Tool.hxx +++ b/src/GeomLib/GeomLib_Tool.hxx @@ -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); diff --git a/tests/bugs/modalg_6/bug27110 b/tests/bugs/modalg_6/bug27110 new file mode 100644 index 0000000000..ce5a7071a4 --- /dev/null +++ b/tests/bugs/modalg_6/bug27110 @@ -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." +}