diff --git a/src/GCPnts/FILES b/src/GCPnts/FILES index 666b09e61e..c6edf27d61 100755 --- a/src/GCPnts/FILES +++ b/src/GCPnts/FILES @@ -1,5 +1,4 @@ GCPnts_AbscissaPoint.cxx -GCPnts_AbscissaPoint.pxx GCPnts_AbscissaPoint.hxx GCPnts_AbscissaType.hxx GCPnts_DeflectionType.hxx diff --git a/src/GCPnts/GCPnts_AbscissaPoint.cxx b/src/GCPnts/GCPnts_AbscissaPoint.cxx index a536647ae3..d916786227 100644 --- a/src/GCPnts/GCPnts_AbscissaPoint.cxx +++ b/src/GCPnts/GCPnts_AbscissaPoint.cxx @@ -14,39 +14,593 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. - -#include -#include #include + +#include +#include #include -#include + +//! Dimension independent used to implement GCPnts_AbscissaPoint +//! compute the type and the length ratio if GCPnts_LengthParametrized. +template +static GCPnts_AbscissaType computeType (const TheCurve& theC, + Standard_Real& theRatio) +{ + if (theC.NbIntervals (GeomAbs_CN) > 1) + { + return GCPnts_AbsComposite; + } + + switch (theC.GetType()) + { + case GeomAbs_Line: + { + theRatio = 1.0; + return GCPnts_LengthParametrized; + } + case GeomAbs_Circle: + { + theRatio = theC.Circle().Radius(); + return GCPnts_LengthParametrized; + } + case GeomAbs_BezierCurve: + { + Handle(typename GCPnts_TCurveTypes::BezierCurve) aBz = theC.Bezier(); + if (aBz->NbPoles() == 2 + && !aBz->IsRational()) + { + theRatio = aBz->DN (0, 1).Magnitude(); + return GCPnts_LengthParametrized; + } + return GCPnts_Parametrized; + } + case GeomAbs_BSplineCurve: + { + Handle(typename GCPnts_TCurveTypes::BSplineCurve) aBs = theC.BSpline(); + if (aBs->NbPoles() == 2 + && !aBs->IsRational()) + { + theRatio = aBs->DN (aBs->FirstParameter(), 1).Magnitude(); + return GCPnts_LengthParametrized; + } + return GCPnts_Parametrized; + } + default: + { + return GCPnts_Parametrized; + } + } +} + +//! Compute a point at distance theAbscis from parameter theU0 using theUi as initial guess +template +static void Compute (CPnts_AbscissaPoint& theComputer, + const TheCurve& theC, + Standard_Real& theAbscis, + Standard_Real& theU0, + Standard_Real& theUi, + const Standard_Real theEPSILON) +{ + // test for easy solution + if (Abs (theAbscis) <= Precision::Confusion()) + { + theComputer.SetParameter (theU0); + return; + } + + Standard_Real aRatio = 1.0; + const GCPnts_AbscissaType aType = computeType (theC, aRatio); + switch (aType) + { + case GCPnts_LengthParametrized: + { + theComputer.SetParameter (theU0 + theAbscis / aRatio); + return; + } + case GCPnts_Parametrized: + { + theComputer.Init (theC); + theComputer.Perform (theAbscis, theU0, theUi, theEPSILON); + return; + } + case GCPnts_AbsComposite: + { + const Standard_Integer aNbIntervals = theC.NbIntervals (GeomAbs_CN); + TColStd_Array1OfReal aTI (1, aNbIntervals + 1); + theC.Intervals (aTI, GeomAbs_CN); + Standard_Real aL = 0.0, aSign = 1.0; + Standard_Integer anIndex = 1; + BSplCLib::Hunt (aTI, theU0, anIndex); + Standard_Integer aDirection = 1; + if (theAbscis < 0) + { + aDirection = 0; + theAbscis = -theAbscis; + aSign = -1.0; + } + + while (anIndex >= 1 + && anIndex <= aNbIntervals) + { + aL = CPnts_AbscissaPoint::Length (theC, theU0, aTI (anIndex + aDirection)); + if (Abs (aL - theAbscis) <= Precision::Confusion()) + { + theComputer.SetParameter (aTI (anIndex + aDirection)); + return; + } + + if (aL > theAbscis) + { + if (theUi < aTI (anIndex) + || theUi > aTI (anIndex + 1)) + { + theUi = (theAbscis / aL) * (aTI (anIndex + 1) - theU0); + if (aDirection) + { + theUi = theU0 + theUi; + } + else + { + theUi = theU0 - theUi; + } + } + theComputer.Init (theC, aTI (anIndex), aTI (anIndex + 1)); + theComputer.Perform (aSign * theAbscis, theU0, theUi, theEPSILON); + return; + } + else + { + theU0 = aTI (anIndex + aDirection); + theAbscis -= aL; + } + if (aDirection) + { + ++anIndex; + } + else + { + --anIndex; + } + } + + // Push a little bit outside the limits (hairy !!!) + theUi = theU0 + 0.1; + theComputer.Init (theC, theU0, theU0 + 0.2); + theComputer.Perform (aSign * theAbscis, theU0, theUi, theEPSILON); + return; + } + break; + } +} + +//! Introduced by rbv for curvilinear parametrization +//! performs more appropriate tolerance management. +template +static void AdvCompute (CPnts_AbscissaPoint& theComputer, + const TheCurve& theC, + Standard_Real& theAbscis, + Standard_Real& theU0, + Standard_Real& theUi, + const Standard_Real theEPSILON) +{ + Standard_Real aRatio = 1.0; + const GCPnts_AbscissaType aType = computeType (theC, aRatio); + switch (aType) + { + case GCPnts_LengthParametrized: + { + theComputer.SetParameter (theU0 + theAbscis / aRatio); + return; + } + case GCPnts_Parametrized: + { + // theComputer.Init (theC); + theComputer.Init (theC, theEPSILON); //rbv's modification + theComputer.AdvPerform (theAbscis, theU0, theUi, theEPSILON); + return; + } + case GCPnts_AbsComposite: + { + const Standard_Integer aNbIntervals = theC.NbIntervals (GeomAbs_CN); + TColStd_Array1OfReal aTI (1, aNbIntervals + 1); + theC.Intervals (aTI, GeomAbs_CN); + Standard_Real aL = 0.0, aSign = 1.0; + Standard_Integer anIndex = 1; + BSplCLib::Hunt (aTI, theU0, anIndex); + + Standard_Integer aDirection = 1; + if (theAbscis < 0) + { + aDirection = 0; + theAbscis = -theAbscis; + aSign = -1.0; + } + + if (anIndex == 0 && aDirection > 0) + { + aL = CPnts_AbscissaPoint::Length (theC, theU0, aTI (anIndex + aDirection), theEPSILON); + if (Abs (aL - theAbscis) <= /*Precision::Confusion()*/theEPSILON) + { + theComputer.SetParameter (aTI (anIndex + aDirection)); + return; + } + + if (aL > theAbscis) + { + if (theUi > aTI (anIndex + 1)) + { + theUi = (theAbscis / aL) * (aTI (anIndex + 1) - theU0); + theUi = theU0 + theUi; + } + theComputer.Init (theC, theU0, aTI (anIndex + 1), theEPSILON); + theComputer.AdvPerform (aSign * theAbscis, theU0, theUi, theEPSILON); + return; + } + else + { + theU0 = aTI (anIndex + aDirection); + theAbscis -= aL; + } + ++anIndex; + } + + while (anIndex >= 1 + && anIndex <= aNbIntervals) + { + aL = CPnts_AbscissaPoint::Length (theC, theU0, aTI (anIndex + aDirection), theEPSILON); + if (Abs (aL - theAbscis) <= Precision::PConfusion()) + { + theComputer.SetParameter (aTI (anIndex + aDirection)); + return; + } + + if (aL > theAbscis) + { + if (theUi < aTI (anIndex) + || theUi > aTI (anIndex + 1)) + { + theUi = (theAbscis / aL) * (aTI (anIndex + 1) - theU0); + if (aDirection) + { + theUi = theU0 + theUi; + } + else + { + theUi = theU0 - theUi; + } + } + theComputer.Init (theC, aTI (anIndex), aTI (anIndex + 1), theEPSILON); + theComputer.AdvPerform (aSign * theAbscis, theU0, theUi, theEPSILON); + return; + } + else + { + theU0 = aTI (anIndex + aDirection); + theAbscis -= aL; + } + if (aDirection) + { + ++anIndex; + } + else + { + --anIndex; + } + } + + // Push a little bit outside the limits (hairy !!!) + const Standard_Boolean isNonPeriodic = !theC.IsPeriodic(); + theUi = theU0 + aSign * 0.1; + Standard_Real aU1 = theU0 + aSign * 0.2; + if (isNonPeriodic) + { + if (aSign > 0) + { + theUi = Min (theUi, theC.LastParameter()); + aU1 = Min (aU1, theC.LastParameter()); + } + else + { + theUi = Max (theUi, theC.FirstParameter()); + aU1 = Max (aU1, theC.FirstParameter()); + } + } + + theComputer.Init (theC, theU0, aU1, theEPSILON); + theComputer.AdvPerform (aSign * theAbscis, theU0, theUi, theEPSILON); + return; + } + break; + } +} //======================================================================= //function : GCPnts_AbscissaPoint -//purpose : +//purpose : //======================================================================= GCPnts_AbscissaPoint::GCPnts_AbscissaPoint() { + // } -#include -#include +//======================================================================= +//function : Length +//purpose : +//======================================================================= +Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor3d_Curve& theC) +{ + return GCPnts_AbscissaPoint::Length (theC, theC.FirstParameter(), theC.LastParameter()); +} -#define TheCurve Adaptor3d_Curve -#define Handle_TheBezierCurve Handle(Geom_BezierCurve) -#define Handle_TheBSplineCurve Handle(Geom_BSplineCurve) +//======================================================================= +//function : Length +//purpose : +//======================================================================= +Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor2d_Curve2d& theC) +{ + return GCPnts_AbscissaPoint::Length (theC, theC.FirstParameter(), theC.LastParameter()); +} -#include "GCPnts_AbscissaPoint.pxx" +//======================================================================= +//function : Length +//purpose : +//======================================================================= +Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor3d_Curve& theC, + const Standard_Real theTol) +{ + return GCPnts_AbscissaPoint::Length (theC, theC.FirstParameter(), theC.LastParameter(), theTol); +} -#undef TheCurve -#undef Handle_TheBezierCurve -#undef Handle_TheBSplineCurve +//======================================================================= +//function : Length +//purpose : +//======================================================================= +Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor2d_Curve2d& theC, + const Standard_Real theTol) +{ + return GCPnts_AbscissaPoint::Length (theC, theC.FirstParameter(), theC.LastParameter(), theTol); +} -#include -#include +//======================================================================= +//function : Length +//purpose : +//======================================================================= +Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor3d_Curve& theC, + const Standard_Real theU1, const Standard_Real theU2) +{ + return length (theC, theU1, theU2, NULL); +} -#define TheCurve Adaptor2d_Curve2d -#define Handle_TheBezierCurve Handle(Geom2d_BezierCurve) -#define Handle_TheBSplineCurve Handle(Geom2d_BSplineCurve) +//======================================================================= +//function : Length +//purpose : +//======================================================================= +Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor2d_Curve2d& theC, + const Standard_Real theU1, const Standard_Real theU2) +{ + return length (theC, theU1, theU2, NULL); +} -#include "GCPnts_AbscissaPoint.pxx" +//======================================================================= +//function : Length +//purpose : +//======================================================================= +Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor3d_Curve& theC, + const Standard_Real theU1, const Standard_Real theU2, + const Standard_Real theTol) +{ + return length (theC, theU1, theU2, &theTol); +} + +//======================================================================= +//function : Length +//purpose : +//======================================================================= +Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor2d_Curve2d& theC, + const Standard_Real theU1, const Standard_Real theU2, + const Standard_Real theTol) +{ + return length (theC, theU1, theU2, &theTol); +} + +//======================================================================= +//function : length +//purpose : +//======================================================================= +template +Standard_Real GCPnts_AbscissaPoint::length (const TheCurve& theC, + const Standard_Real theU1, const Standard_Real theU2, + const Standard_Real* theTol) +{ + Standard_Real aRatio = 1.0; + const GCPnts_AbscissaType aType = computeType (theC, aRatio); + switch (aType) + { + case GCPnts_LengthParametrized: + { + return Abs (theU2 - theU1) * aRatio; + } + case GCPnts_Parametrized: + { + return theTol != NULL + ? CPnts_AbscissaPoint::Length (theC, theU1, theU2, *theTol) + : CPnts_AbscissaPoint::Length (theC, theU1, theU2); + } + case GCPnts_AbsComposite: + { + const Standard_Integer aNbIntervals = theC.NbIntervals (GeomAbs_CN); + TColStd_Array1OfReal aTI (1, aNbIntervals + 1); + theC.Intervals (aTI, GeomAbs_CN); + const Standard_Real aUU1 = Min (theU1, theU2); + const Standard_Real aUU2 = Max (theU1, theU2); + Standard_Real aL = 0.0; + for (Standard_Integer anIndex = 1; anIndex <= aNbIntervals; ++anIndex) + { + if (aTI (anIndex) > aUU2) { break; } + if (aTI (anIndex + 1) < aUU1) { continue; } + if (theTol != NULL) + { + aL += CPnts_AbscissaPoint::Length (theC, + Max (aTI (anIndex), aUU1), + Min (aTI (anIndex + 1), aUU2), + *theTol); + } + else + { + aL += CPnts_AbscissaPoint::Length (theC, + Max (aTI (anIndex), aUU1), + Min (aTI (anIndex + 1), aUU2)); + } + } + return aL; + } + } + return RealLast(); +} + +//======================================================================= +//function : compute +//purpose : +//======================================================================= +template +void GCPnts_AbscissaPoint::compute (const TheCurve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0) +{ + const Standard_Real aL = GCPnts_AbscissaPoint::Length (theC); + if (aL < Precision::Confusion()) + { + throw Standard_ConstructionError(); + } + + Standard_Real anAbscis = theAbscissa; + Standard_Real aUU0 = theU0; + Standard_Real aUUi = theU0 + (anAbscis / aL) * (theC.LastParameter() - theC.FirstParameter()); + Compute (myComputer, theC, anAbscis, aUU0, aUUi, + theC.Resolution (Precision::Confusion())); +} + +//======================================================================= +//function : GCPnts_AbscissaPoint +//purpose : +//======================================================================= +GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor3d_Curve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0) +{ + compute (theC, theAbscissa, theU0); +} + +//======================================================================= +//function : GCPnts_AbscissaPoint +//purpose : +//======================================================================= +GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor2d_Curve2d& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0) +{ + compute (theC, theAbscissa, theU0); +} + +//======================================================================= +//function : advCompute +//purpose : +//======================================================================= +template +void GCPnts_AbscissaPoint::advCompute (const Standard_Real theTol, + const TheCurve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0) +{ + const Standard_Real aL = GCPnts_AbscissaPoint::Length (theC, theTol); + /*if (aL < Precision::Confusion()) + { + throw Standard_ConstructionError ("GCPnts_AbscissaPoint::GCPnts_AbscissaPoint"); + }*/ + Standard_Real anAbscis = theAbscissa; + Standard_Real aUU0 = theU0; + Standard_Real aUUi = 0.0; + if (aL >= Precision::Confusion()) + { + aUUi= theU0 + (anAbscis / aL) * (theC.LastParameter() - theC.FirstParameter()); + } + else + { + aUUi = theU0; + } + AdvCompute (myComputer, theC, anAbscis, aUU0, aUUi, theTol); +} + +//======================================================================= +//function : GCPnts_AbscissaPoint +//purpose : +//======================================================================= +GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Standard_Real theTol, + const Adaptor3d_Curve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0) +{ + advCompute (theTol, theC, theAbscissa, theU0); +} + +//======================================================================= +//function : GCPnts_AbscissaPoint +//purpose : +//======================================================================= +GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Standard_Real theTol, + const Adaptor2d_Curve2d& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0) +{ + advCompute (theTol, theC, theAbscissa, theU0); +} + +//======================================================================= +//function : GCPnts_AbscissaPoint +//purpose : +//======================================================================= +GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor3d_Curve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0, const Standard_Real theUi) +{ + Standard_Real anAbscis = theAbscissa, aUU0 = theU0, aUUi = theUi; + Compute (myComputer, theC, anAbscis, aUU0, aUUi, theC.Resolution (Precision::Confusion())); +} + +//======================================================================= +//function : GCPnts_AbscissaPoint +//purpose : +//======================================================================= +GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor2d_Curve2d& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0, const Standard_Real theUi) +{ + Standard_Real anAbscis = theAbscissa, aUU0 = theU0, aUUi = theUi; + Compute (myComputer, theC, anAbscis, aUU0, aUUi, theC.Resolution (Precision::Confusion())); +} + +//======================================================================= +//function : GCPnts_AbscissaPoint +//purpose : +//======================================================================= +GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor3d_Curve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0, const Standard_Real theUi, + const Standard_Real theTol) +{ + Standard_Real anAbscis = theAbscissa, aUU0 = theU0, aUUi = theUi; + AdvCompute (myComputer, theC, anAbscis, aUU0, aUUi, theTol); +} + +//======================================================================= +//function : GCPnts_AbscissaPoint +//purpose : +//======================================================================= +GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor2d_Curve2d& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0, const Standard_Real theUi, + const Standard_Real theTol) +{ + Standard_Real anAbscis = theAbscissa, aUU0 = theU0, aUUi = theUi; + AdvCompute (myComputer, theC, anAbscis, aUU0, aUUi, theTol); +} diff --git a/src/GCPnts/GCPnts_AbscissaPoint.hxx b/src/GCPnts/GCPnts_AbscissaPoint.hxx index 6c4498cb4a..eab3be2cab 100644 --- a/src/GCPnts/GCPnts_AbscissaPoint.hxx +++ b/src/GCPnts/GCPnts_AbscissaPoint.hxx @@ -19,104 +19,122 @@ #include -class StdFail_NotDone; -class Standard_ConstructionError; class Adaptor3d_Curve; class Adaptor2d_Curve2d; //! Provides an algorithm to compute a point on a curve -//! situated at a given distance from another point on the -//! curve, the distance being measured along the curve -//! (curvilinear abscissa on the curve). +//! situated at a given distance from another point on the curve, +//! the distance being measured along the curve (curvilinear abscissa on the curve). //! This algorithm is also used to compute the length of a curve. //! An AbscissaPoint object provides a framework for: //! - defining the point to compute //! - implementing the construction algorithm //! - consulting the result. -class GCPnts_AbscissaPoint +class GCPnts_AbscissaPoint { public: DEFINE_STANDARD_ALLOC + //! Computes the length of the 3D Curve. + Standard_EXPORT static Standard_Real Length (const Adaptor3d_Curve& theC); - //! Computes the length of the Curve . - Standard_EXPORT static Standard_Real Length (const Adaptor3d_Curve& C); + //! Computes the length of the 2D Curve. + Standard_EXPORT static Standard_Real Length (const Adaptor2d_Curve2d& theC); - //! Computes the length of the Curve . - Standard_EXPORT static Standard_Real Length (const Adaptor2d_Curve2d& C); + //! Computes the length of the 3D Curve with the given tolerance. + Standard_EXPORT static Standard_Real Length (const Adaptor3d_Curve& theC, + const Standard_Real theTol); - //! Computes the length of the Curve with the given tolerance. - Standard_EXPORT static Standard_Real Length (const Adaptor3d_Curve& C, const Standard_Real Tol); + //! Computes the length of the 2D Curve with the given tolerance. + Standard_EXPORT static Standard_Real Length (const Adaptor2d_Curve2d& theC, + const Standard_Real theTol); - //! Computes the length of the Curve with the given tolerance. - Standard_EXPORT static Standard_Real Length (const Adaptor2d_Curve2d& C, const Standard_Real Tol); + //! Computes the length of the 3D Curve. + Standard_EXPORT static Standard_Real Length (const Adaptor3d_Curve& theC, + const Standard_Real theU1, const Standard_Real theU2); - //! Computes the length of the Curve . - Standard_EXPORT static Standard_Real Length (const Adaptor3d_Curve& C, const Standard_Real U1, const Standard_Real U2); - - //! Computes the length of the Curve . - Standard_EXPORT static Standard_Real Length (const Adaptor2d_Curve2d& C, const Standard_Real U1, const Standard_Real U2); - - //! Computes the length of the Curve with the given tolerance. - Standard_EXPORT static Standard_Real Length (const Adaptor3d_Curve& C, const Standard_Real U1, const Standard_Real U2, const Standard_Real Tol); - - //! Computes the length of the Curve with the given tolerance. - //! Constructs an empty algorithm. This function is used - //! only for initializing a framework to compute the length - //! of a curve (or a series of curves). - //! Warning - //! The function IsDone will return the value false after the use of this function. - Standard_EXPORT static Standard_Real Length (const Adaptor2d_Curve2d& C, const Standard_Real U1, const Standard_Real U2, const Standard_Real Tol); + //! Computes the length of the 2D Curve. + Standard_EXPORT static Standard_Real Length (const Adaptor2d_Curve2d& theC, + const Standard_Real theU1, const Standard_Real theU2); + //! Computes the length of the 3D Curve with the given tolerance. + Standard_EXPORT static Standard_Real Length (const Adaptor3d_Curve& theC, + const Standard_Real theU1, const Standard_Real theU2, + const Standard_Real theTol); + + //! Computes the length of the Curve with the given tolerance. + Standard_EXPORT static Standard_Real Length (const Adaptor2d_Curve2d& theC, + const Standard_Real theU1, const Standard_Real theU2, + const Standard_Real theTol); + +public: + + //! Empty constructor. Standard_EXPORT GCPnts_AbscissaPoint(); - - //! the algorithm computes a point on a curve at the - //! distance from the point of parameter . - Standard_EXPORT GCPnts_AbscissaPoint(const Adaptor3d_Curve& C, const Standard_Real Abscissa, const Standard_Real U0); - - //! the algorithm computes a point on a curve at - //! the distance from the point of parameter - //! with the given tolerance. - Standard_EXPORT GCPnts_AbscissaPoint(const Standard_Real Tol, const Adaptor3d_Curve& C, const Standard_Real Abscissa, const Standard_Real U0); - - //! the algorithm computes a point on a curve at - //! the distance from the point of parameter - //! with the given tolerance. - Standard_EXPORT GCPnts_AbscissaPoint(const Standard_Real Tol, const Adaptor2d_Curve2d& C, const Standard_Real Abscissa, const Standard_Real U0); - - //! the algorithm computes a point on a curve at the - //! distance from the point of parameter . - Standard_EXPORT GCPnts_AbscissaPoint(const Adaptor2d_Curve2d& C, const Standard_Real Abscissa, const Standard_Real U0); - - //! the algorithm computes a point on a curve at the - //! distance from the point of parameter . - //! is the starting value used in the iterative process - //! which find the solution, it must be close to the final - //! solution - Standard_EXPORT GCPnts_AbscissaPoint(const Adaptor3d_Curve& C, const Standard_Real Abscissa, const Standard_Real U0, const Standard_Real Ui); - - //! the algorithm computes a point on a curve at the - //! distance from the point of parameter . - //! is the starting value used in the iterative process - //! which find the solution, it must be closed to the final - //! solution - Standard_EXPORT GCPnts_AbscissaPoint(const Adaptor2d_Curve2d& C, const Standard_Real Abscissa, const Standard_Real U0, const Standard_Real Ui); - - //! the algorithm computes a point on a curve at the - //! distance from the point of parameter . - //! is the starting value used in the iterative process - //! which find the solution, it must be close to the final - //! solution - Standard_EXPORT GCPnts_AbscissaPoint(const Adaptor3d_Curve& C, const Standard_Real Abscissa, const Standard_Real U0, const Standard_Real Ui, const Standard_Real Tol); - - //! the algorithm computes a point on a curve at the - //! distance from the point of parameter . - //! is the starting value used in the iterative process - //! which find the solution, it must be close to the final - //! solution - Standard_EXPORT GCPnts_AbscissaPoint(const Adaptor2d_Curve2d& C, const Standard_Real Abscissa, const Standard_Real U0, const Standard_Real Ui, const Standard_Real Tol); - + + //! The algorithm computes a point on a curve at the + //! distance theAbscissa from the point of parameter theU0. + Standard_EXPORT GCPnts_AbscissaPoint (const Adaptor3d_Curve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0); + + //! The algorithm computes a point on a curve at + //! the distance theAbscissa from the point of parameter + //! theU0 with the given tolerance. + Standard_EXPORT GCPnts_AbscissaPoint (const Standard_Real theTol, + const Adaptor3d_Curve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0); + + //! The algorithm computes a point on a curve at + //! the distance theAbscissa from the point of parameter + //! theU0 with the given tolerance. + Standard_EXPORT GCPnts_AbscissaPoint (const Standard_Real theTol, + const Adaptor2d_Curve2d& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0); + + //! The algorithm computes a point on a curve at the + //! distance theAbscissa from the point of parameter theU0. + Standard_EXPORT GCPnts_AbscissaPoint (const Adaptor2d_Curve2d& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0); + + //! The algorithm computes a point on a curve at the + //! distance theAbscissa from the point of parameter theU0. + //! theUi is the starting value used in the iterative process + //! which find the solution, it must be close to the final solution. + Standard_EXPORT GCPnts_AbscissaPoint (const Adaptor3d_Curve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0, const Standard_Real theUi); + + //! The algorithm computes a point on a curve at the + //! distance theAbscissa from the point of parameter theU0. + //! theUi is the starting value used in the iterative process + //! which find the solution, it must be closed to the final solution + Standard_EXPORT GCPnts_AbscissaPoint (const Adaptor2d_Curve2d& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0, const Standard_Real theUi); + + //! The algorithm computes a point on a curve at the + //! distance theAbscissa from the point of parameter theU0. + //! theUi is the starting value used in the iterative process + //! which find the solution, it must be close to the final solution + Standard_EXPORT GCPnts_AbscissaPoint (const Adaptor3d_Curve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0, const Standard_Real theUi, + const Standard_Real theTol); + + //! The algorithm computes a point on a curve at the + //! distance theAbscissa from the point of parameter theU0. + //! theUi is the starting value used in the iterative process + //! which find the solution, it must be close to the final solution + Standard_EXPORT GCPnts_AbscissaPoint (const Adaptor2d_Curve2d& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0, const Standard_Real theUi, + const Standard_Real theTol); + //! True if the computation was successful, False otherwise. //! IsDone is a protection against: //! - non-convergence of the algorithm @@ -136,6 +154,27 @@ public: return myComputer.Parameter (); } +private: + + //! Computes the length of the Curve with the optional tolerance. + template + static Standard_Real length (const TheCurve& theC, + const Standard_Real theU1, const Standard_Real theU2, + const Standard_Real* theTol); + + //! Performs algorithm from the point of parameter. + template + void compute (const TheCurve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0); + + //! Performs algorithm from the point of parameter with the given tolerance. + template + void advCompute (const Standard_Real theTol, + const TheCurve& theC, + const Standard_Real theAbscissa, + const Standard_Real theU0); + private: CPnts_AbscissaPoint myComputer; }; diff --git a/src/GCPnts/GCPnts_AbscissaPoint.pxx b/src/GCPnts/GCPnts_AbscissaPoint.pxx deleted file mode 100644 index 480e9559fb..0000000000 --- a/src/GCPnts/GCPnts_AbscissaPoint.pxx +++ /dev/null @@ -1,474 +0,0 @@ -// Created on: 1995-05-05 -// Created by: Modelistation -// 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. - -// Dimension independent used to implement GCPnts_AbscissaPoint - -// compute the type -// and the length ratio if GCPnts_LengthParametrized -#include -#include -#include -#include -#include -#include -#include -#include - -static GCPnts_AbscissaType computeType( const TheCurve& C, - Standard_Real& Ratio) -{ - GCPnts_AbscissaType LocalType ; - - if (C.NbIntervals(GeomAbs_CN) > 1) - return GCPnts_AbsComposite; - - switch (C.GetType()) { - - case GeomAbs_Line: - Ratio = 1.0e0 ; - return GCPnts_LengthParametrized; - - case GeomAbs_Circle: - Ratio = C.Circle().Radius(); - return GCPnts_LengthParametrized; - - case GeomAbs_BezierCurve: - { - Handle_TheBezierCurve Bz = C.Bezier(); - if ((Bz->NbPoles() == 2) && !(Bz->IsRational())) { - Ratio = Bz->DN(0,1).Magnitude(); - LocalType = GCPnts_LengthParametrized; - } - else - LocalType = GCPnts_Parametrized; - return LocalType ; - } - case GeomAbs_BSplineCurve: - { - Handle_TheBSplineCurve Bs = C.BSpline(); - if ((Bs->NbPoles() == 2) && !(Bs->IsRational())) { - Ratio = Bs->DN(Bs->FirstParameter(),1).Magnitude(); - LocalType = GCPnts_LengthParametrized; - } - else - LocalType = GCPnts_Parametrized; - return LocalType ; - } - default: - return GCPnts_Parametrized; - - } -} - -// compute a point at distance Abscis from parameter U0 -// using Ui as initial guess - -static void Compute(CPnts_AbscissaPoint& theComputer, - const TheCurve& C, - Standard_Real& Abscis, - Standard_Real& U0, - Standard_Real& Ui, - const Standard_Real EPSILON) -{ - // test for easy solution - if (Abs(Abscis) <= Precision::Confusion()) { - theComputer.SetParameter(U0); - return; - } - - Standard_Real Ratio = 1.; - GCPnts_AbscissaType Type = computeType(C,Ratio); - - switch (Type) { - case GCPnts_LengthParametrized : - theComputer.SetParameter(U0 + Abscis / Ratio); - return; - - case GCPnts_Parametrized : - theComputer.Init(C); - theComputer.Perform(Abscis, U0, Ui, EPSILON); - return; - - case GCPnts_AbsComposite : - { - Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN); - TColStd_Array1OfReal TI(1,NbIntervals+1); - C.Intervals(TI,GeomAbs_CN); - Standard_Real L = 0.0, sign = 1.; - Standard_Integer Index = 1; - BSplCLib::Hunt(TI,U0,Index); - Standard_Integer Direction = 1; - if (Abscis < 0) { - Direction = 0; - Abscis = -Abscis; - sign = -1.; - } - - while ((Index >= 1) && (Index <= NbIntervals)) { - - L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction)); - if (Abs(L - Abscis) <= Precision::Confusion()) { - theComputer.SetParameter(TI(Index+Direction)); - return; - } - if(L > Abscis) { - if ((Ui < TI(Index)) || (Ui > TI(Index+1))) { - Ui = (Abscis / L) * (TI(Index+1) - U0); - if (Direction) - Ui = U0 + Ui; - else - Ui = U0 - Ui; - } - theComputer.Init(C,TI(Index),TI(Index+1)); - theComputer.Perform(sign*Abscis, U0, Ui, EPSILON); - return; - } - else { - U0 = TI(Index+Direction); - Abscis -= L; - } - if (Direction) - Index++; - else - Index--; - } - - // Push a little bit outside the limits (hairy !!!) - Ui = U0 + 0.1; - theComputer.Init(C,U0,U0+0.2); - theComputer.Perform(sign*Abscis, U0, Ui, EPSILON); - return; - } - break; - } - -} - -// introduced by rbv for curvilinear parametrization -// performs more appropriate tolerance management - -static void AdvCompute(CPnts_AbscissaPoint& theComputer, - const TheCurve& C, - Standard_Real& Abscis, - Standard_Real& U0, - Standard_Real& Ui, - const Standard_Real EPSILON) -{ - Standard_Real Ratio = 1.0; - GCPnts_AbscissaType Type = computeType(C,Ratio); - - switch (Type) { - case GCPnts_LengthParametrized : - theComputer.SetParameter(U0 + Abscis / Ratio); - return; - - case GCPnts_Parametrized : -// theComputer.Init(C); - theComputer.Init(C, EPSILON); //rbv's modification -// - theComputer.AdvPerform(Abscis, U0, Ui, EPSILON); - return; - - case GCPnts_AbsComposite : - { - Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN); - TColStd_Array1OfReal TI(1,NbIntervals+1); - C.Intervals(TI,GeomAbs_CN); - Standard_Real L = 0.0, sign = 1.; - Standard_Integer Index = 1; - BSplCLib::Hunt(TI,U0,Index); - - Standard_Integer Direction = 1; - if (Abscis < 0) { - Direction = 0; - Abscis = -Abscis; - sign = -1.; - } - - if(Index == 0 && Direction > 0) { - L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON); - if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) { - theComputer.SetParameter(TI(Index+Direction)); - return; - } - if(L > Abscis) { - if ( Ui > TI(Index+1) ) { - Ui = (Abscis / L) * (TI(Index+1) - U0); - Ui = U0 + Ui; - } - theComputer.Init(C,U0,TI(Index+1), EPSILON); - theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON); - return; - } - else { - U0 = TI(Index+Direction); - Abscis -= L; - } - Index++; - } - - - while ((Index >= 1) && (Index <= NbIntervals)) { - - L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON); - if (Abs(L - Abscis) <= Precision::PConfusion()) { - theComputer.SetParameter(TI(Index+Direction)); - return; - } - if(L > Abscis) { - if ((Ui < TI(Index)) || (Ui > TI(Index+1))) { - Ui = (Abscis / L) * (TI(Index+1) - U0); - if (Direction) - Ui = U0 + Ui; - else - Ui = U0 - Ui; - } - theComputer.Init(C,TI(Index),TI(Index+1), EPSILON); - theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON); - return; - } - else { - U0 = TI(Index+Direction); - Abscis -= L; - } - if (Direction) { - Index++; - - } - else { - Index--; - - } - } - - // Push a little bit outside the limits (hairy !!!) - - Standard_Boolean nonperiodic = !C.IsPeriodic(); - Ui = U0 + sign*0.1; - Standard_Real U1 = U0 + sign*.2; - if(nonperiodic) { - if(sign > 0) { - Ui = Min(Ui,C.LastParameter()); - U1 = Min(U1, C.LastParameter()); - } - else { - Ui = Max(Ui,C.FirstParameter()); - U1 = Max(U1, C.FirstParameter()); - } - } - - theComputer.Init(C, U0, U1, EPSILON); - theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON); - return; - } - break; - } - -} - -//======================================================================= -//function : Length -//purpose : -//======================================================================= - -Standard_Real GCPnts_AbscissaPoint::Length(const TheCurve& C) -{ - return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(), - C.LastParameter()); -} - -//======================================================================= -//function : Length -//purpose : -//======================================================================= - -Standard_Real GCPnts_AbscissaPoint::Length(const TheCurve& C, - const Standard_Real Tol) -{ - return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(), - C.LastParameter(),Tol); -} - - -//======================================================================= -//function : Length -//purpose : -//======================================================================= - -Standard_Real GCPnts_AbscissaPoint::Length(const TheCurve& C, - const Standard_Real U1, - const Standard_Real U2) -{ - Standard_Real Ratio = 1.0; - GCPnts_AbscissaType Type = computeType(C,Ratio); - switch (Type) { - - case GCPnts_LengthParametrized: - return Abs(U2-U1) * Ratio; - - case GCPnts_Parametrized: - return CPnts_AbscissaPoint::Length(C, U1, U2); - - case GCPnts_AbsComposite: - { - Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN); - TColStd_Array1OfReal TI(1,NbIntervals+1); - C.Intervals(TI,GeomAbs_CN); - Standard_Real UU1 = Min(U1, U2); - Standard_Real UU2 = Max(U1, U2); - Standard_Real L = 0.0; - for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) { - if (TI(Index) > UU2) break; - if (TI(Index+1) < UU1) continue; - L += CPnts_AbscissaPoint::Length(C, - Max(TI(Index),UU1), - Min(TI(Index+1),UU2)); - } - return L; - } - } - return RealLast(); -} - -//======================================================================= -//function : Length -//purpose : -//======================================================================= - -Standard_Real GCPnts_AbscissaPoint::Length(const TheCurve& C, - const Standard_Real U1, - const Standard_Real U2, - const Standard_Real Tol) -{ - Standard_Real Ratio = 1.0; - GCPnts_AbscissaType Type = computeType(C,Ratio); - switch (Type) { - - case GCPnts_LengthParametrized: - return Abs(U2-U1) * Ratio; - - case GCPnts_Parametrized: - return CPnts_AbscissaPoint::Length(C, U1, U2, Tol); - - case GCPnts_AbsComposite: - { - Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN); - TColStd_Array1OfReal TI(1,NbIntervals+1); - C.Intervals(TI,GeomAbs_CN); - Standard_Real UU1 = Min(U1, U2); - Standard_Real UU2 = Max(U1, U2); - Standard_Real L = 0.0; - for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) { - if (TI(Index) > UU2) break; - if (TI(Index+1) < UU1) continue; - L += CPnts_AbscissaPoint::Length(C, - Max(TI(Index),UU1), - Min(TI(Index+1),UU2), - Tol); - } - return L; - } - } - return RealLast(); -} - - -//======================================================================= -//function : GCPnts_AbscissaPoint -//purpose : -//======================================================================= - -GCPnts_AbscissaPoint::GCPnts_AbscissaPoint - (const TheCurve& C, - const Standard_Real Abscissa, - const Standard_Real U0) -{ - Standard_Real L = GCPnts_AbscissaPoint::Length(C); - if (L < Precision::Confusion()) { - throw Standard_ConstructionError(); - } - Standard_Real Abscis = Abscissa; - Standard_Real UU0 = U0; - Standard_Real UUi = U0 + - (Abscis / L) * (C.LastParameter() - C.FirstParameter()); - Compute(myComputer, C, Abscis, UU0, UUi, - C.Resolution(Precision::Confusion())); -} - -//======================================================================= -//function : GCPnts_AbscissaPoint -//purpose : rbv for curvilinear parametrization -//======================================================================= - -GCPnts_AbscissaPoint::GCPnts_AbscissaPoint - (const Standard_Real Tol, - const TheCurve& C, - const Standard_Real Abscissa, - const Standard_Real U0) -{ - Standard_Real L = GCPnts_AbscissaPoint::Length(C, Tol); -/* if (L < Precision::Confusion()) { - cout<<"FirstParameter = "<= Precision::Confusion()) - UUi= U0 + - (Abscis / L) * (C.LastParameter() - C.FirstParameter()); - else UUi = U0; - - AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol); -} - -//======================================================================= -//function : GCPnts_AbscissaPoint -//purpose : -//======================================================================= - -GCPnts_AbscissaPoint::GCPnts_AbscissaPoint - (const TheCurve& C, - const Standard_Real Abscissa, - const Standard_Real U0, - const Standard_Real Ui) -{ - Standard_Real Abscis = Abscissa; - Standard_Real UU0 = U0; - Standard_Real UUi = Ui; - Compute(myComputer, C, Abscis, UU0, UUi, - C.Resolution(Precision::Confusion())); -} - -//======================================================================= -//function : GCPnts_AbscissaPoint -//purpose : rbv for curvilinear parametrization -//======================================================================= - -GCPnts_AbscissaPoint::GCPnts_AbscissaPoint - (const TheCurve& C, - const Standard_Real Abscissa, - const Standard_Real U0, - const Standard_Real Ui, - const Standard_Real Tol) -{ - Standard_Real Abscis = Abscissa; - Standard_Real UU0 = U0; - Standard_Real UUi = Ui; - AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol); -}