mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
0024682: Move out B-spline cache from curves and surfaces to dedicated classes BSplCLib_Cache and BSplSLib_Cache
1. B-spline cache was moved into separated classes: BSplCLib_Cache for 2D and 3D curves and BSplSLib_Cache for surfaces. 2. The cache is used now in corresponding adaptor classes (Geom2dAdaptor_Curve, GeomAdaptor_Curve and GeomAdaptor_Surface) when the curve or surface is a B-spline. 3. Algorithms were changed to use adaptors for B-spline calculations instead of curves or surfaces. 4. Precised calculation of derivatives of surface of revolution is implemented for the points of surface placed on the axis of revolution (Geom_SurfaceOfRevolution.cxx) 5. Small modifications are made to adjust algorithms to new behavior of B-spline calculation. 6. Test cases were modified according to the modern behavior. 7. Changes in BOPAlgo_WireSplitter, BOPTools_AlgoTools, BRepLib_CheckCurveOnSurface and ShapeAnalysis_Wire to use adaptors instead of geometric entities 8. Allow Geom2dAdaptor and GeomAdaptor in case of offset curve to use corresponding adaptor for basis curve Modification of test-cases according to the new behavior.
This commit is contained in:
@@ -124,8 +124,7 @@ uses Array1OfInteger from TColStd,
|
||||
Vec2d from gp,
|
||||
BSplKnotDistribution from GeomAbs,
|
||||
Geometry from Geom2d,
|
||||
Shape from GeomAbs,
|
||||
Mutex from Standard
|
||||
Shape from GeomAbs
|
||||
|
||||
raises ConstructionError from Standard,
|
||||
DimensionError from Standard,
|
||||
@@ -642,17 +641,6 @@ is
|
||||
-- Returns True if the weights are not identical.
|
||||
-- The tolerance criterion is Epsilon of the class Real.
|
||||
|
||||
IsCacheValid(me; Parameter : Real) returns Boolean
|
||||
|
||||
---Purpose :
|
||||
-- Tells whether the Cache is valid for the
|
||||
-- given parameter
|
||||
-- Warnings : the parameter must be normalized within
|
||||
-- the period if the curve is periodic. Otherwise
|
||||
-- the answer will be false
|
||||
--
|
||||
is static private;
|
||||
|
||||
Continuity (me) returns Shape from GeomAbs;
|
||||
--- Purpose :
|
||||
-- Returns the global continuity of the curve :
|
||||
@@ -843,6 +831,11 @@ is
|
||||
raises DimensionError;
|
||||
--- Purpose :
|
||||
-- Raised if the length of K is not equal to the number of knots.
|
||||
Knots (me)
|
||||
returns Array1OfReal from TColStd
|
||||
---Purpose : returns the knot values of the B-spline curve;
|
||||
---C++ : return const &
|
||||
is static;
|
||||
|
||||
|
||||
KnotSequence (me; K : out Array1OfReal from TColStd)
|
||||
@@ -854,6 +847,15 @@ is
|
||||
raises DimensionError;
|
||||
--- Purpose :
|
||||
-- Raised if the length of K is not equal to NbPoles + Degree + 1
|
||||
KnotSequence (me)
|
||||
returns Array1OfReal from TColStd
|
||||
---Purpose : Returns the knots sequence.
|
||||
-- In this sequence the knots with a multiplicity greater than 1
|
||||
-- are repeated.
|
||||
-- Example :
|
||||
-- K = {k1, k1, k1, k2, k3, k3, k4, k4, k4}
|
||||
---C++ : return const &
|
||||
is static;
|
||||
|
||||
|
||||
|
||||
@@ -919,6 +921,11 @@ is
|
||||
raises DimensionError;
|
||||
--- Purpose :
|
||||
-- Raised if the length of M is not equal to NbKnots.
|
||||
Multiplicities (me)
|
||||
returns Array1OfInteger from TColStd
|
||||
---Purpose : returns the multiplicity of the knots of the curve.
|
||||
---C++ : return const &
|
||||
is static;
|
||||
|
||||
|
||||
NbKnots (me) returns Integer;
|
||||
@@ -942,6 +949,11 @@ is
|
||||
raises DimensionError;
|
||||
--- Purpose :
|
||||
-- Raised if the length of P is not equal to the number of poles.
|
||||
Poles (me)
|
||||
returns Array1OfPnt2d from TColgp
|
||||
---Purpose : Returns the poles of the B-spline curve;
|
||||
---C++ : return const &
|
||||
is static;
|
||||
|
||||
|
||||
StartPoint (me) returns Pnt2d;
|
||||
@@ -963,6 +975,11 @@ is
|
||||
raises DimensionError;
|
||||
--- Purpose :
|
||||
-- Raised if the length of W is not equal to NbPoles.
|
||||
Weights (me)
|
||||
returns Array1OfReal from TColStd
|
||||
---Purpose : Returns the weights of the B-spline curve;
|
||||
---C++ : return const &
|
||||
is static;
|
||||
|
||||
|
||||
|
||||
@@ -996,17 +1013,8 @@ is
|
||||
UpdateKnots(me : mutable)
|
||||
---Purpose: Recompute the flatknots, the knotsdistribution, the continuity.
|
||||
is static private;
|
||||
|
||||
InvalidateCache(me : mutable)
|
||||
---Purpose : Invalidates the cache. This has to be private this has to be private
|
||||
is static private;
|
||||
|
||||
|
||||
ValidateCache(me : mutable ; Parameter : Real)
|
||||
|
||||
is static private;
|
||||
---Purpose : updates the cache and validates it
|
||||
|
||||
fields
|
||||
|
||||
rational : Boolean;
|
||||
@@ -1019,35 +1027,7 @@ fields
|
||||
flatknots : HArray1OfReal from TColStd;
|
||||
knots : HArray1OfReal from TColStd;
|
||||
mults : HArray1OfInteger from TColStd;
|
||||
cachepoles : HArray1OfPnt2d from TColgp;
|
||||
-- Taylor expansion of the poles function, in homogeneous
|
||||
-- form if the curve is rational. The taylor expansion
|
||||
-- is normalized so that the span corresponds to
|
||||
-- [0 1] see below
|
||||
cacheweights : HArray1OfReal from TColStd;
|
||||
-- Taylor expansion of the poles function, in homogeneous
|
||||
-- form if the curve is rational. The taylor expansion
|
||||
-- is normalized so that the span corresponds to
|
||||
-- [0 1] see below
|
||||
validcache : Integer;
|
||||
-- = 1 the cache is valid
|
||||
-- = 0 the cache is invalid
|
||||
parametercache : Real;
|
||||
-- Parameter at which the Taylor expension is stored in
|
||||
-- the cache
|
||||
spanlenghtcache : Real;
|
||||
-- Since the Taylor expansion is normalized in the
|
||||
-- cache to evaluate the cache one has to use
|
||||
-- (Parameter - refcache) * normcache
|
||||
spanindexcache : Integer;
|
||||
-- the span for which the cache is valid if
|
||||
-- validcache is 1
|
||||
|
||||
-- usefull to evaluate the parametric resolution
|
||||
maxderivinv : Real from Standard;
|
||||
maxderivinvok : Boolean from Standard;
|
||||
|
||||
myMutex : Mutex from Standard;
|
||||
-- protected bspline-cache
|
||||
|
||||
end;
|
||||
|
@@ -123,12 +123,11 @@ Geom2d_BSplineCurve::Geom2d_BSplineCurve
|
||||
{
|
||||
// check
|
||||
|
||||
CheckCurveData (Poles,
|
||||
Knots,
|
||||
Mults,
|
||||
Degree,
|
||||
Periodic);
|
||||
|
||||
CheckCurveData(Poles,
|
||||
Knots,
|
||||
Mults,
|
||||
Degree,
|
||||
Periodic);
|
||||
|
||||
// copy arrays
|
||||
|
||||
@@ -142,10 +141,6 @@ Geom2d_BSplineCurve::Geom2d_BSplineCurve
|
||||
mults->ChangeArray1() = Mults;
|
||||
|
||||
UpdateKnots();
|
||||
cachepoles = new TColgp_HArray1OfPnt2d(1,Degree + 1);
|
||||
parametercache = 0.0e0 ;
|
||||
spanlenghtcache = 0.0e0 ;
|
||||
spanindexcache = 0 ;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -169,11 +164,11 @@ Geom2d_BSplineCurve::Geom2d_BSplineCurve
|
||||
|
||||
// check
|
||||
|
||||
CheckCurveData (Poles,
|
||||
Knots,
|
||||
Mults,
|
||||
Degree,
|
||||
Periodic);
|
||||
CheckCurveData(Poles,
|
||||
Knots,
|
||||
Mults,
|
||||
Degree,
|
||||
Periodic);
|
||||
|
||||
if (Weights.Length() != Poles.Length())
|
||||
Standard_ConstructionError::Raise("Geom2d_BSplineCurve :Weights and Poles array size mismatch");
|
||||
@@ -192,11 +187,9 @@ Geom2d_BSplineCurve::Geom2d_BSplineCurve
|
||||
|
||||
poles = new TColgp_HArray1OfPnt2d(1,Poles.Length());
|
||||
poles->ChangeArray1() = Poles;
|
||||
cachepoles = new TColgp_HArray1OfPnt2d(1,Degree + 1);
|
||||
if (rational) {
|
||||
weights = new TColStd_HArray1OfReal(1,Weights.Length());
|
||||
weights->ChangeArray1() = Weights;
|
||||
cacheweights = new TColStd_HArray1OfReal(1,Degree + 1);
|
||||
}
|
||||
|
||||
knots = new TColStd_HArray1OfReal(1,Knots.Length());
|
||||
@@ -206,10 +199,6 @@ Geom2d_BSplineCurve::Geom2d_BSplineCurve
|
||||
mults->ChangeArray1() = Mults;
|
||||
|
||||
UpdateKnots();
|
||||
|
||||
parametercache = 0.0e0 ;
|
||||
spanlenghtcache = 0.0e0 ;
|
||||
spanindexcache = 0 ;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -1090,7 +1079,6 @@ void Geom2d_BSplineCurve::SetPole
|
||||
if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : SetPole : index and #pole mismatch");
|
||||
poles->SetValue (Index, P);
|
||||
maxderivinvok = 0;
|
||||
InvalidateCache();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -1140,7 +1128,6 @@ void Geom2d_BSplineCurve::SetWeight
|
||||
}
|
||||
|
||||
maxderivinvok = 0;
|
||||
InvalidateCache() ;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -1149,11 +1136,11 @@ void Geom2d_BSplineCurve::SetWeight
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_BSplineCurve::MovePoint(const Standard_Real U,
|
||||
const gp_Pnt2d& P,
|
||||
const Standard_Integer Index1,
|
||||
const Standard_Integer Index2,
|
||||
Standard_Integer& FirstModifiedPole,
|
||||
Standard_Integer& LastmodifiedPole)
|
||||
const gp_Pnt2d& P,
|
||||
const Standard_Integer Index1,
|
||||
const Standard_Integer Index2,
|
||||
Standard_Integer& FirstModifiedPole,
|
||||
Standard_Integer& LastmodifiedPole)
|
||||
{
|
||||
if (Index1 < 1 || Index1 > poles->Length() ||
|
||||
Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) {
|
||||
@@ -1164,12 +1151,11 @@ void Geom2d_BSplineCurve::MovePoint(const Standard_Real U,
|
||||
D0(U, P0);
|
||||
gp_Vec2d Displ(P0, P);
|
||||
BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(),
|
||||
weights->Array1(), flatknots->Array1(),
|
||||
FirstModifiedPole, LastmodifiedPole, npoles);
|
||||
weights->Array1(), flatknots->Array1(),
|
||||
FirstModifiedPole, LastmodifiedPole, npoles);
|
||||
if (FirstModifiedPole) {
|
||||
poles->ChangeArray1() = npoles;
|
||||
maxderivinvok = 0;
|
||||
InvalidateCache() ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1222,7 +1208,6 @@ MovePointAndTangent(const Standard_Real U,
|
||||
if (!ErrorStatus) {
|
||||
poles->ChangeArray1() = new_poles;
|
||||
maxderivinvok = 0;
|
||||
InvalidateCache() ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1266,33 +1251,6 @@ void Geom2d_BSplineCurve::UpdateKnots()
|
||||
default : smooth = GeomAbs_C3; break;
|
||||
}
|
||||
}
|
||||
InvalidateCache() ;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Invalidate the Cache
|
||||
//purpose : as the name says
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_BSplineCurve::InvalidateCache()
|
||||
{
|
||||
validcache = 0 ;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : check if the Cache is valid
|
||||
//purpose : as the name says
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2d_BSplineCurve::IsCacheValid
|
||||
(const Standard_Real U) const
|
||||
{
|
||||
//Roman Lygin 26.12.08, see comments in Geom_BSplineCurve::IsCacheValid()
|
||||
Standard_Real aDelta = U - parametercache;
|
||||
|
||||
return ( validcache &&
|
||||
(aDelta >= 0.0e0) &&
|
||||
((aDelta < spanlenghtcache) || (spanindexcache == flatknots->Upper() - deg)) );
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -1315,83 +1273,3 @@ void Geom2d_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Validate the Cache
|
||||
//purpose : that is compute the cache so that it is valid
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_BSplineCurve::ValidateCache(const Standard_Real Parameter)
|
||||
{
|
||||
Standard_Real NewParameter ;
|
||||
Standard_Integer LocalIndex = 0 ;
|
||||
//
|
||||
// check if the degree did not change
|
||||
//
|
||||
if (cachepoles->Upper() < deg + 1)
|
||||
cachepoles = new TColgp_HArray1OfPnt2d(1,deg + 1);
|
||||
if (rational)
|
||||
{
|
||||
if (cacheweights.IsNull() || cacheweights->Upper() < deg + 1)
|
||||
cacheweights = new TColStd_HArray1OfReal(1,deg + 1);
|
||||
}
|
||||
else if (!cacheweights.IsNull())
|
||||
cacheweights.Nullify();
|
||||
|
||||
BSplCLib::LocateParameter(deg,
|
||||
(flatknots->Array1()),
|
||||
(BSplCLib::NoMults()),
|
||||
Parameter,
|
||||
periodic,
|
||||
LocalIndex,
|
||||
NewParameter);
|
||||
spanindexcache = LocalIndex ;
|
||||
if (Parameter == flatknots->Value(LocalIndex + 1)) {
|
||||
|
||||
LocalIndex += 1 ;
|
||||
parametercache = flatknots->Value(LocalIndex) ;
|
||||
if (LocalIndex == flatknots->Upper() - deg) {
|
||||
//
|
||||
// for the last span if the parameter is outside of
|
||||
// the domain of the curve than use the last knot
|
||||
// and normalize with the last span Still set the
|
||||
// spanindexcache to flatknots->Upper() - deg so that
|
||||
// the IsCacheValid will know for sure we are extending
|
||||
// the Bspline
|
||||
//
|
||||
|
||||
spanlenghtcache = flatknots->Value(LocalIndex - 1) - parametercache ;
|
||||
}
|
||||
else {
|
||||
spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
parametercache = flatknots->Value(LocalIndex) ;
|
||||
spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ;
|
||||
}
|
||||
|
||||
if (rational) {
|
||||
BSplCLib::BuildCache(parametercache,
|
||||
spanlenghtcache,
|
||||
periodic,
|
||||
deg,
|
||||
(flatknots->Array1()),
|
||||
poles->Array1(),
|
||||
weights->Array1(),
|
||||
cachepoles->ChangeArray1(),
|
||||
cacheweights->ChangeArray1()) ;
|
||||
}
|
||||
else {
|
||||
BSplCLib::BuildCache(parametercache,
|
||||
spanlenghtcache,
|
||||
periodic,
|
||||
deg,
|
||||
(flatknots->Array1()),
|
||||
poles->Array1(),
|
||||
*((TColStd_Array1OfReal*) NULL),
|
||||
cachepoles->ChangeArray1(),
|
||||
*((TColStd_Array1OfReal*) NULL)) ;
|
||||
}
|
||||
validcache = 1 ;
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include <Standard_OutOfRange.hxx>
|
||||
#include <Standard_DomainError.hxx>
|
||||
#include <Standard_RangeError.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#define POLES (poles->Array1())
|
||||
#define KNOTS (knots->Array1())
|
||||
@@ -183,36 +183,28 @@ Standard_Integer Geom2d_BSplineCurve::Degree () const
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_BSplineCurve::D0 ( const Standard_Real U,
|
||||
gp_Pnt2d& P) const
|
||||
void Geom2d_BSplineCurve::D0(const Standard_Real U,
|
||||
gp_Pnt2d& P) const
|
||||
{
|
||||
Standard_Real NewU(U);
|
||||
PeriodicNormalization(NewU);
|
||||
|
||||
Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
|
||||
Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
|
||||
|
||||
if (!IsCacheValid(NewU))
|
||||
MyCurve->ValidateCache(NewU);
|
||||
|
||||
if(rational)
|
||||
Standard_Integer aSpanIndex = 0;
|
||||
Standard_Real aNewU(U);
|
||||
PeriodicNormalization(aNewU);
|
||||
BSplCLib::LocateParameter(deg, knots->Array1(), mults->Array1(), U, periodic, aSpanIndex, aNewU);
|
||||
if (aNewU < knots->Value(aSpanIndex))
|
||||
aSpanIndex--;
|
||||
if (rational)
|
||||
{
|
||||
BSplCLib::CacheD0(NewU,
|
||||
deg,
|
||||
parametercache,
|
||||
spanlenghtcache,
|
||||
(cachepoles->Array1()),
|
||||
cacheweights->Array1(),
|
||||
P) ;
|
||||
BSplCLib::D0(aNewU,aSpanIndex,deg,periodic,POLES,
|
||||
weights->Array1(),
|
||||
knots->Array1(), mults->Array1(),
|
||||
P);
|
||||
}
|
||||
else {
|
||||
BSplCLib::CacheD0(NewU,
|
||||
deg,
|
||||
parametercache,
|
||||
spanlenghtcache,
|
||||
(cachepoles->Array1()),
|
||||
BSplCLib::NoWeights(),
|
||||
P) ;
|
||||
else
|
||||
{
|
||||
BSplCLib::D0(aNewU,aSpanIndex,deg,periodic,POLES,
|
||||
*((TColStd_Array1OfReal*) NULL),
|
||||
knots->Array1(), mults->Array1(),
|
||||
P);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,39 +214,29 @@ void Geom2d_BSplineCurve::D0 ( const Standard_Real U,
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_BSplineCurve::D1 (const Standard_Real U,
|
||||
gp_Pnt2d& P,
|
||||
gp_Vec2d& V1) const
|
||||
void Geom2d_BSplineCurve::D1(const Standard_Real U,
|
||||
gp_Pnt2d& P,
|
||||
gp_Vec2d& V1) const
|
||||
{
|
||||
Standard_Real NewU(U);
|
||||
PeriodicNormalization(NewU);
|
||||
|
||||
Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
|
||||
Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
|
||||
|
||||
if (!IsCacheValid(NewU))
|
||||
MyCurve->ValidateCache(NewU);
|
||||
|
||||
if(rational)
|
||||
Standard_Integer aSpanIndex = 0;
|
||||
Standard_Real aNewU(U);
|
||||
PeriodicNormalization(aNewU);
|
||||
BSplCLib::LocateParameter(deg, knots->Array1(), mults->Array1(), U, periodic, aSpanIndex, aNewU);
|
||||
if (aNewU < knots->Value(aSpanIndex))
|
||||
aSpanIndex--;
|
||||
if (rational)
|
||||
{
|
||||
BSplCLib::CacheD1(NewU,
|
||||
deg,
|
||||
parametercache,
|
||||
spanlenghtcache,
|
||||
(cachepoles->Array1()),
|
||||
cacheweights->Array1(),
|
||||
P,
|
||||
V1) ;
|
||||
BSplCLib::D1(aNewU,aSpanIndex,deg,periodic,POLES,
|
||||
weights->Array1(),
|
||||
knots->Array1(), mults->Array1(),
|
||||
P, V1);
|
||||
}
|
||||
else {
|
||||
BSplCLib::CacheD1(NewU,
|
||||
deg,
|
||||
parametercache,
|
||||
spanlenghtcache,
|
||||
(cachepoles->Array1()),
|
||||
BSplCLib::NoWeights(),
|
||||
P,
|
||||
V1) ;
|
||||
else
|
||||
{
|
||||
BSplCLib::D1(aNewU,aSpanIndex,deg,periodic,POLES,
|
||||
*((TColStd_Array1OfReal*) NULL),
|
||||
knots->Array1(), mults->Array1(),
|
||||
P, V1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,42 +245,30 @@ void Geom2d_BSplineCurve::D1 (const Standard_Real U,
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_BSplineCurve::D2 (const Standard_Real U ,
|
||||
gp_Pnt2d& P ,
|
||||
gp_Vec2d& V1,
|
||||
gp_Vec2d& V2 ) const
|
||||
void Geom2d_BSplineCurve::D2(const Standard_Real U,
|
||||
gp_Pnt2d& P,
|
||||
gp_Vec2d& V1,
|
||||
gp_Vec2d& V2) const
|
||||
{
|
||||
Standard_Real NewU(U);
|
||||
PeriodicNormalization(NewU);
|
||||
|
||||
Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
|
||||
Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
|
||||
|
||||
if (!IsCacheValid(NewU))
|
||||
MyCurve->ValidateCache(NewU);
|
||||
|
||||
if(rational)
|
||||
Standard_Integer aSpanIndex = 0;
|
||||
Standard_Real aNewU(U);
|
||||
PeriodicNormalization(aNewU);
|
||||
BSplCLib::LocateParameter(deg, knots->Array1(), mults->Array1(), U, periodic, aSpanIndex, aNewU);
|
||||
if (aNewU < knots->Value(aSpanIndex))
|
||||
aSpanIndex--;
|
||||
if (rational)
|
||||
{
|
||||
BSplCLib::CacheD2(NewU,
|
||||
deg,
|
||||
parametercache,
|
||||
spanlenghtcache,
|
||||
(cachepoles->Array1()),
|
||||
cacheweights->Array1(),
|
||||
P,
|
||||
V1,
|
||||
V2) ;
|
||||
BSplCLib::D2(aNewU,aSpanIndex,deg,periodic,POLES,
|
||||
weights->Array1(),
|
||||
knots->Array1(), mults->Array1(),
|
||||
P, V1, V2);
|
||||
}
|
||||
else {
|
||||
BSplCLib::CacheD2(NewU,
|
||||
deg,
|
||||
parametercache,
|
||||
spanlenghtcache,
|
||||
(cachepoles->Array1()),
|
||||
BSplCLib::NoWeights(),
|
||||
P,
|
||||
V1,
|
||||
V2) ;
|
||||
else
|
||||
{
|
||||
BSplCLib::D2(aNewU,aSpanIndex,deg,periodic,POLES,
|
||||
*((TColStd_Array1OfReal*) NULL),
|
||||
knots->Array1(), mults->Array1(),
|
||||
P, V1, V2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,45 +277,31 @@ void Geom2d_BSplineCurve::D2 (const Standard_Real U ,
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_BSplineCurve::D3 (const Standard_Real U ,
|
||||
gp_Pnt2d& P ,
|
||||
gp_Vec2d& V1,
|
||||
gp_Vec2d& V2,
|
||||
gp_Vec2d& V3 ) const
|
||||
void Geom2d_BSplineCurve::D3(const Standard_Real U,
|
||||
gp_Pnt2d& P,
|
||||
gp_Vec2d& V1,
|
||||
gp_Vec2d& V2,
|
||||
gp_Vec2d& V3) const
|
||||
{
|
||||
Standard_Real NewU(U);
|
||||
PeriodicNormalization(NewU);
|
||||
|
||||
Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
|
||||
Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
|
||||
|
||||
if (!IsCacheValid(NewU))
|
||||
MyCurve->ValidateCache(NewU);
|
||||
|
||||
if(rational)
|
||||
Standard_Integer aSpanIndex = 0;
|
||||
Standard_Real aNewU(U);
|
||||
PeriodicNormalization(aNewU);
|
||||
BSplCLib::LocateParameter(deg, knots->Array1(), mults->Array1(), U, periodic, aSpanIndex, aNewU);
|
||||
if (aNewU < knots->Value(aSpanIndex))
|
||||
aSpanIndex--;
|
||||
if (rational)
|
||||
{
|
||||
BSplCLib::CacheD3(NewU,
|
||||
deg,
|
||||
parametercache,
|
||||
spanlenghtcache,
|
||||
(cachepoles->Array1()),
|
||||
cacheweights->Array1(),
|
||||
P,
|
||||
V1,
|
||||
V2,
|
||||
V3) ;
|
||||
BSplCLib::D3(aNewU,aSpanIndex,deg,periodic,POLES,
|
||||
weights->Array1(),
|
||||
knots->Array1(), mults->Array1(),
|
||||
P, V1, V2, V3);
|
||||
}
|
||||
else {
|
||||
BSplCLib::CacheD3(NewU,
|
||||
deg,
|
||||
parametercache,
|
||||
spanlenghtcache,
|
||||
(cachepoles->Array1()),
|
||||
BSplCLib::NoWeights(),
|
||||
P,
|
||||
V1,
|
||||
V2,
|
||||
V3) ;
|
||||
else
|
||||
{
|
||||
BSplCLib::D3(aNewU,aSpanIndex,deg,periodic,POLES,
|
||||
*((TColStd_Array1OfReal*) NULL),
|
||||
knots->Array1(), mults->Array1(),
|
||||
P, V1, V2, V3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,20 +310,20 @@ void Geom2d_BSplineCurve::D3 (const Standard_Real U ,
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
gp_Vec2d Geom2d_BSplineCurve::DN (const Standard_Real U,
|
||||
const Standard_Integer N ) const
|
||||
gp_Vec2d Geom2d_BSplineCurve::DN(const Standard_Real U,
|
||||
const Standard_Integer N) const
|
||||
{
|
||||
gp_Vec2d V;
|
||||
|
||||
if ( rational ) {
|
||||
BSplCLib::DN(U,N,0,deg,periodic,POLES,
|
||||
weights->Array1(),
|
||||
FKNOTS,FMULTS,V);
|
||||
weights->Array1(),
|
||||
FKNOTS,FMULTS,V);
|
||||
}
|
||||
else {
|
||||
else {
|
||||
BSplCLib::DN(U,N,0,deg,periodic,POLES,
|
||||
*((TColStd_Array1OfReal*) NULL),
|
||||
FKNOTS,FMULTS,V);
|
||||
*((TColStd_Array1OfReal*) NULL),
|
||||
FKNOTS,FMULTS,V);
|
||||
}
|
||||
return V;
|
||||
}
|
||||
@@ -440,6 +396,11 @@ void Geom2d_BSplineCurve::Knots (TColStd_Array1OfReal& K) const
|
||||
K = knots->Array1();
|
||||
}
|
||||
|
||||
const TColStd_Array1OfReal& Geom2d_BSplineCurve::Knots() const
|
||||
{
|
||||
return knots->Array1();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : KnotSequence
|
||||
//purpose :
|
||||
@@ -452,6 +413,11 @@ void Geom2d_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const
|
||||
K = flatknots->Array1();
|
||||
}
|
||||
|
||||
const TColStd_Array1OfReal& Geom2d_BSplineCurve::KnotSequence() const
|
||||
{
|
||||
return flatknots->Array1();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : LastUKnotIndex
|
||||
//purpose :
|
||||
@@ -676,6 +642,11 @@ void Geom2d_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const
|
||||
M = mults->Array1();
|
||||
}
|
||||
|
||||
const TColStd_Array1OfInteger& Geom2d_BSplineCurve::Multiplicities() const
|
||||
{
|
||||
return mults->Array1();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : NbKnots
|
||||
//purpose :
|
||||
@@ -716,6 +687,11 @@ void Geom2d_BSplineCurve::Poles (TColgp_Array1OfPnt2d& P) const
|
||||
P = poles->Array1();
|
||||
}
|
||||
|
||||
const TColgp_Array1OfPnt2d& Geom2d_BSplineCurve::Poles() const
|
||||
{
|
||||
return poles->Array1();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : StartPoint
|
||||
//purpose :
|
||||
@@ -764,6 +740,13 @@ void Geom2d_BSplineCurve::Weights
|
||||
}
|
||||
}
|
||||
|
||||
const TColStd_Array1OfReal& Geom2d_BSplineCurve::Weights() const
|
||||
{
|
||||
if (IsRational())
|
||||
return weights->Array1();
|
||||
return BSplCLib::NoWeights();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : IsRational
|
||||
//purpose :
|
||||
@@ -786,7 +769,6 @@ void Geom2d_BSplineCurve::Transform
|
||||
for (Standard_Integer I = 1; I <= CPoles.Length(); I++)
|
||||
CPoles (I).Transform (T);
|
||||
|
||||
InvalidateCache();
|
||||
// maxderivinvok = 0;
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include <Standard_ConstructionError.hxx>
|
||||
#include <Standard_RangeError.hxx>
|
||||
#include <Standard_NotImplemented.hxx>
|
||||
#include <CSLib_Offset.hxx>
|
||||
#include <Geom2d_UndefinedDerivative.hxx>
|
||||
#include <Geom2d_UndefinedValue.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
@@ -54,6 +55,14 @@ static const int maxDerivOrder = 3;
|
||||
static const Standard_Real MinStep = 1e-7;
|
||||
static const Standard_Real MyAngularToleranceForG1 = Precision::Angular();
|
||||
|
||||
static gp_Vec2d dummyDerivative; // used as empty value for unused derivatives in AdjustDerivative
|
||||
|
||||
// Recalculate derivatives in the singular point
|
||||
// Returns true if the direction of derivatives is changed
|
||||
static Standard_Boolean AdjustDerivative(const Handle(Geom2d_Curve)& theCurve, Standard_Integer theMaxDerivative,
|
||||
Standard_Real theU, gp_Vec2d& theD1, gp_Vec2d& theD2 = dummyDerivative,
|
||||
gp_Vec2d& theD3 = dummyDerivative, gp_Vec2d& theD4 = dummyDerivative);
|
||||
|
||||
//=======================================================================
|
||||
//function : Copy
|
||||
//purpose :
|
||||
@@ -211,163 +220,38 @@ GeomAbs_Shape Geom2d_OffsetCurve::Continuity () const
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_OffsetCurve::D0 (const Standard_Real theU,
|
||||
Pnt2d& theP ) const
|
||||
void Geom2d_OffsetCurve::D0 (const Standard_Real theU,
|
||||
Pnt2d& theP) const
|
||||
{
|
||||
const Standard_Real aTol = gp::Resolution();
|
||||
|
||||
Vec2d vD1;
|
||||
|
||||
basisCurve->D1 (theU, theP, vD1);
|
||||
Standard_Real Ndu = vD1.Magnitude();
|
||||
|
||||
if(Ndu <= aTol)
|
||||
{
|
||||
const Standard_Real anUinfium = basisCurve->FirstParameter();
|
||||
const Standard_Real anUsupremum = basisCurve->LastParameter();
|
||||
Standard_Boolean IsDirectionChange = Standard_False;
|
||||
if(vD1.SquareMagnitude() <= gp::Resolution())
|
||||
IsDirectionChange = AdjustDerivative(basisCurve, 1, theU, vD1);
|
||||
|
||||
const Standard_Real DivisionFactor = 1.e-3;
|
||||
Standard_Real du;
|
||||
if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
|
||||
du = 0.0;
|
||||
else
|
||||
du = anUsupremum-anUinfium;
|
||||
|
||||
const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
|
||||
//Derivative is approximated by Taylor-series
|
||||
|
||||
Standard_Integer anIndex = 1; //Derivative order
|
||||
Vec2d V;
|
||||
|
||||
do
|
||||
{
|
||||
V = basisCurve->DN(theU,++anIndex);
|
||||
Ndu = V.Magnitude();
|
||||
}
|
||||
while((Ndu <= aTol) && anIndex < maxDerivOrder);
|
||||
|
||||
Standard_Real u;
|
||||
|
||||
if(theU-anUinfium < aDelta)
|
||||
u = theU+aDelta;
|
||||
else
|
||||
u = theU-aDelta;
|
||||
|
||||
Pnt2d P1, P2;
|
||||
basisCurve->D0(Min(theU, u),P1);
|
||||
basisCurve->D0(Max(theU, u),P2);
|
||||
|
||||
Vec2d V1(P1,P2);
|
||||
Standard_Real aDirFactor = V.Dot(V1);
|
||||
|
||||
if(aDirFactor < 0.0)
|
||||
vD1 = -V;
|
||||
else
|
||||
vD1 = V;
|
||||
|
||||
Ndu = vD1.Magnitude();
|
||||
}//if(Ndu <= aTol)
|
||||
|
||||
if (Ndu <= aTol)
|
||||
Geom2d_UndefinedValue::Raise("Exception: Undefined normal vector "
|
||||
"because tangent vector has zero-magnitude!");
|
||||
|
||||
Standard_Real A = vD1.Y();
|
||||
Standard_Real B = - vD1.X();
|
||||
A = A * offsetValue/Ndu;
|
||||
B = B * offsetValue/Ndu;
|
||||
theP.SetCoord(theP.X() + A, theP.Y() + B);
|
||||
}
|
||||
CSLib_Offset::D0(theP, vD1, offsetValue, IsDirectionChange, theP);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : D1
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void Geom2d_OffsetCurve::D1 (const Standard_Real theU, Pnt2d& P, Vec2d& theV1) const
|
||||
{
|
||||
void Geom2d_OffsetCurve::D1 (const Standard_Real theU, Pnt2d& theP, Vec2d& theV1) const
|
||||
{
|
||||
// P(u) = p(u) + Offset * Ndir / R
|
||||
// with R = || p' ^ Z|| and Ndir = P' ^ Z
|
||||
|
||||
// P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
|
||||
|
||||
const Standard_Real aTol = gp::Resolution();
|
||||
|
||||
Vec2d V2;
|
||||
basisCurve->D2 (theU, P, theV1, V2);
|
||||
|
||||
if(theV1.Magnitude() <= aTol)
|
||||
{
|
||||
const Standard_Real anUinfium = basisCurve->FirstParameter();
|
||||
const Standard_Real anUsupremum = basisCurve->LastParameter();
|
||||
basisCurve->D2 (theU, theP, theV1, V2);
|
||||
|
||||
const Standard_Real DivisionFactor = 1.e-3;
|
||||
Standard_Real du;
|
||||
if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
|
||||
du = 0.0;
|
||||
else
|
||||
du = anUsupremum-anUinfium;
|
||||
|
||||
const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
|
||||
//Derivative is approximated by Taylor-series
|
||||
|
||||
Standard_Integer anIndex = 1; //Derivative order
|
||||
Vec2d V;
|
||||
|
||||
do
|
||||
{
|
||||
V = basisCurve->DN(theU,++anIndex);
|
||||
}
|
||||
while((V.Magnitude() <= aTol) && anIndex < maxDerivOrder);
|
||||
|
||||
Standard_Real u;
|
||||
|
||||
if(theU-anUinfium < aDelta)
|
||||
u = theU+aDelta;
|
||||
else
|
||||
u = theU-aDelta;
|
||||
|
||||
Pnt2d P1, P2;
|
||||
basisCurve->D0(Min(theU, u),P1);
|
||||
basisCurve->D0(Max(theU, u),P2);
|
||||
|
||||
Vec2d V1(P1,P2);
|
||||
Standard_Real aDirFactor = V.Dot(V1);
|
||||
|
||||
if(aDirFactor < 0.0)
|
||||
{
|
||||
theV1 = -V;
|
||||
V2 = - basisCurve->DN (theU, anIndex+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
theV1 = V;
|
||||
V2 = basisCurve->DN (theU, anIndex+1);
|
||||
}
|
||||
}//if(theV1.Magnitude() <= aTol)
|
||||
Standard_Boolean IsDirectionChange = Standard_False;
|
||||
if(theV1.SquareMagnitude() <= gp::Resolution())
|
||||
IsDirectionChange = AdjustDerivative(basisCurve, 2, theU, theV1, V2);
|
||||
|
||||
XY Ndir (theV1.Y(), -theV1.X());
|
||||
XY DNdir (V2.Y(), -V2.X());
|
||||
Standard_Real R2 = Ndir.SquareModulus();
|
||||
Standard_Real R = Sqrt (R2);
|
||||
Standard_Real R3 = R * R2;
|
||||
Standard_Real Dr = Ndir.Dot (DNdir);
|
||||
if (R3 <= gp::Resolution()) {
|
||||
//We try another computation but the stability is not very good.
|
||||
if (R2 <= gp::Resolution()) Geom2d_UndefinedDerivative::Raise();
|
||||
DNdir.Multiply(R);
|
||||
DNdir.Subtract (Ndir.Multiplied (Dr/R));
|
||||
DNdir.Multiply (offsetValue/R2);
|
||||
theV1.Add (Vec2d(DNdir));
|
||||
}
|
||||
else {
|
||||
// Same computation as IICURV in EUCLID-IS because the stability is
|
||||
// better
|
||||
DNdir.Multiply (offsetValue/R);
|
||||
DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
|
||||
theV1.Add (Vec2d(DNdir));
|
||||
}
|
||||
|
||||
D0(theU, P);
|
||||
CSLib_Offset::D1(theP, theV1, V2, offsetValue, IsDirectionChange, theP, theV1);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -376,8 +260,8 @@ void Geom2d_OffsetCurve::D1 (const Standard_Real theU, Pnt2d& P, Vec2d& theV1) c
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_OffsetCurve::D2 (const Standard_Real theU,
|
||||
Pnt2d& P,
|
||||
Vec2d& theV1, Vec2d& V2) const
|
||||
Pnt2d& theP,
|
||||
Vec2d& theV1, Vec2d& theV2) const
|
||||
{
|
||||
// P(u) = p(u) + Offset * Ndir / R
|
||||
// with R = || p' ^ Z|| and Ndir = P' ^ Z
|
||||
@@ -388,124 +272,13 @@ void Geom2d_OffsetCurve::D2 (const Standard_Real theU,
|
||||
// Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
|
||||
|
||||
Vec2d V3;
|
||||
basisCurve->D3 (theU, P, theV1, V2, V3);
|
||||
|
||||
const Standard_Real aTol = gp::Resolution();
|
||||
basisCurve->D3 (theU, theP, theV1, theV2, V3);
|
||||
|
||||
Standard_Boolean IsDirectionChange = Standard_False;
|
||||
if(theV1.SquareMagnitude() <= gp::Resolution())
|
||||
IsDirectionChange = AdjustDerivative(basisCurve, 3, theU, theV1, theV2, V3);
|
||||
|
||||
if(theV1.Magnitude() <= aTol)
|
||||
{
|
||||
const Standard_Real anUinfium = basisCurve->FirstParameter();
|
||||
const Standard_Real anUsupremum = basisCurve->LastParameter();
|
||||
|
||||
const Standard_Real DivisionFactor = 1.e-3;
|
||||
Standard_Real du;
|
||||
if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
|
||||
du = 0.0;
|
||||
else
|
||||
du = anUsupremum-anUinfium;
|
||||
|
||||
const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
|
||||
//Derivative is approximated by Taylor-series
|
||||
|
||||
Standard_Integer anIndex = 1; //Derivative order
|
||||
Vec2d V;
|
||||
|
||||
do
|
||||
{
|
||||
V = basisCurve->DN(theU,++anIndex);
|
||||
}
|
||||
while((V.Magnitude() <= aTol) && anIndex < maxDerivOrder);
|
||||
|
||||
Standard_Real u;
|
||||
|
||||
if(theU-anUinfium < aDelta)
|
||||
u = theU+aDelta;
|
||||
else
|
||||
u = theU-aDelta;
|
||||
|
||||
Pnt2d P1, P2;
|
||||
basisCurve->D0(Min(theU, u),P1);
|
||||
basisCurve->D0(Max(theU, u),P2);
|
||||
|
||||
Vec2d V1(P1,P2);
|
||||
Standard_Real aDirFactor = V.Dot(V1);
|
||||
|
||||
if(aDirFactor < 0.0)
|
||||
{
|
||||
theV1 = -V;
|
||||
V2 = -basisCurve->DN (theU, anIndex+1);
|
||||
V3 = -basisCurve->DN (theU, anIndex + 2);
|
||||
|
||||
IsDirectionChange = Standard_True;
|
||||
}
|
||||
else
|
||||
{
|
||||
theV1 = V;
|
||||
V2 = basisCurve->DN (theU, anIndex+1);
|
||||
V3 = basisCurve->DN (theU, anIndex + 2);
|
||||
}
|
||||
}//if(V1.Magnitude() <= aTol)
|
||||
|
||||
XY Ndir (theV1.Y(), -theV1.X());
|
||||
XY DNdir (V2.Y(), -V2.X());
|
||||
XY D2Ndir (V3.Y(), -V3.X());
|
||||
Standard_Real R2 = Ndir.SquareModulus();
|
||||
Standard_Real R = Sqrt (R2);
|
||||
Standard_Real R3 = R2 * R;
|
||||
Standard_Real R4 = R2 * R2;
|
||||
Standard_Real R5 = R3 * R2;
|
||||
Standard_Real Dr = Ndir.Dot (DNdir);
|
||||
Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
|
||||
if (R5 <= gp::Resolution())
|
||||
{
|
||||
//We try another computation but the stability is not very good
|
||||
//dixit ISG.
|
||||
if (R4 <= gp::Resolution())
|
||||
{
|
||||
Geom2d_UndefinedDerivative::Raise();
|
||||
}
|
||||
// V2 = P" (U) :
|
||||
Standard_Real R4 = R2 * R2;
|
||||
D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
|
||||
D2Ndir.Add (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
|
||||
D2Ndir.Multiply (offsetValue / R);
|
||||
|
||||
if(IsDirectionChange)
|
||||
V2=-V2;
|
||||
|
||||
V2.Add (Vec2d(D2Ndir));
|
||||
|
||||
// V1 = P' (U) :
|
||||
DNdir.Multiply(R);
|
||||
DNdir.Subtract (Ndir.Multiplied (Dr/R));
|
||||
DNdir.Multiply (offsetValue/R2);
|
||||
theV1.Add (Vec2d(DNdir));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Same computation as IICURV in EUCLID-IS because the stability is
|
||||
// better.
|
||||
// V2 = P" (U) :
|
||||
D2Ndir.Multiply (offsetValue/R);
|
||||
D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
|
||||
D2Ndir.Add (Ndir.Multiplied
|
||||
(offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))));
|
||||
|
||||
if(IsDirectionChange)
|
||||
V2=-V2;
|
||||
|
||||
V2.Add (Vec2d(D2Ndir));
|
||||
|
||||
// V1 = P' (U)
|
||||
DNdir.Multiply (offsetValue/R);
|
||||
DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
|
||||
theV1.Add (Vec2d(DNdir));
|
||||
}
|
||||
|
||||
//P (U) :
|
||||
D0(theU, P);
|
||||
CSLib_Offset::D2(theP, theV1, theV2, V3, offsetValue, IsDirectionChange, theP, theV1, theV2);
|
||||
}
|
||||
|
||||
|
||||
@@ -515,9 +288,9 @@ void Geom2d_OffsetCurve::D2 (const Standard_Real theU,
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_OffsetCurve::D3 (const Standard_Real theU,
|
||||
Pnt2d& P,
|
||||
Vec2d& theV1, Vec2d& V2, Vec2d& V3) const {
|
||||
|
||||
Pnt2d& theP,
|
||||
Vec2d& theV1, Vec2d& theV2, Vec2d& theV3) const
|
||||
{
|
||||
|
||||
// P(u) = p(u) + Offset * Ndir / R
|
||||
// with R = || p' ^ Z|| and Ndir = P' ^ Z
|
||||
@@ -532,149 +305,16 @@ void Geom2d_OffsetCurve::D3 (const Standard_Real theU,
|
||||
// (D3r/R2) * Ndir + (6.0 * Dr * Dr / R4) * Ndir +
|
||||
// (6.0 * Dr * D2r / R4) * Ndir - (15.0 * Dr* Dr* Dr /R6) * Ndir
|
||||
|
||||
const Standard_Real aTol = gp::Resolution();
|
||||
|
||||
Standard_Boolean IsDirectionChange = Standard_False;
|
||||
|
||||
basisCurve->D3 (theU, P, theV1, V2, V3);
|
||||
basisCurve->D3 (theU, theP, theV1, theV2, theV3);
|
||||
Vec2d V4 = basisCurve->DN (theU, 4);
|
||||
|
||||
if(theV1.Magnitude() <= aTol)
|
||||
{
|
||||
const Standard_Real anUinfium = basisCurve->FirstParameter();
|
||||
const Standard_Real anUsupremum = basisCurve->LastParameter();
|
||||
Standard_Boolean IsDirectionChange = Standard_False;
|
||||
if(theV1.SquareMagnitude() <= gp::Resolution())
|
||||
IsDirectionChange = AdjustDerivative(basisCurve, 4, theU, theV1, theV2, theV3, V4);
|
||||
|
||||
const Standard_Real DivisionFactor = 1.e-3;
|
||||
Standard_Real du;
|
||||
if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
|
||||
du = 0.0;
|
||||
else
|
||||
du = anUsupremum-anUinfium;
|
||||
|
||||
const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
|
||||
//Derivative is approximated by Taylor-series
|
||||
|
||||
Standard_Integer anIndex = 1; //Derivative order
|
||||
Vec2d V;
|
||||
|
||||
do
|
||||
{
|
||||
V = basisCurve->DN(theU,++anIndex);
|
||||
}
|
||||
while((V.Magnitude() <= aTol) && anIndex < maxDerivOrder);
|
||||
|
||||
Standard_Real u;
|
||||
|
||||
if(theU-anUinfium < aDelta)
|
||||
u = theU+aDelta;
|
||||
else
|
||||
u = theU-aDelta;
|
||||
|
||||
Pnt2d P1, P2;
|
||||
basisCurve->D0(Min(theU, u),P1);
|
||||
basisCurve->D0(Max(theU, u),P2);
|
||||
|
||||
Vec2d V1(P1,P2);
|
||||
Standard_Real aDirFactor = V.Dot(V1);
|
||||
|
||||
if(aDirFactor < 0.0)
|
||||
{
|
||||
theV1 = -V;
|
||||
V2 = -basisCurve->DN (theU, anIndex + 1);
|
||||
V3 = -basisCurve->DN (theU, anIndex + 2);
|
||||
V4 = -basisCurve->DN (theU, anIndex + 3);
|
||||
|
||||
IsDirectionChange = Standard_True;
|
||||
}
|
||||
else
|
||||
{
|
||||
theV1 = V;
|
||||
V2 = basisCurve->DN (theU, anIndex + 1);
|
||||
V3 = basisCurve->DN (theU, anIndex + 2);
|
||||
V4 = basisCurve->DN (theU, anIndex + 3);
|
||||
}
|
||||
}//if(V1.Magnitude() <= aTol)
|
||||
|
||||
XY Ndir (theV1.Y(), -theV1.X());
|
||||
XY DNdir (V2.Y(), -V2.X());
|
||||
XY D2Ndir (V3.Y(), -V3.X());
|
||||
XY D3Ndir (V4.Y(), -V4.X());
|
||||
Standard_Real R2 = Ndir.SquareModulus();
|
||||
Standard_Real R = Sqrt (R2);
|
||||
Standard_Real R3 = R2 * R;
|
||||
Standard_Real R4 = R2 * R2;
|
||||
Standard_Real R5 = R3 * R2;
|
||||
Standard_Real R6 = R3 * R3;
|
||||
Standard_Real R7 = R5 * R2;
|
||||
Standard_Real Dr = Ndir.Dot (DNdir);
|
||||
Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
|
||||
Standard_Real D3r = Ndir.Dot (D3Ndir) + 3.0 * DNdir.Dot (D2Ndir);
|
||||
|
||||
if (R7 <= gp::Resolution())
|
||||
{
|
||||
//We try another computation but the stability is not very good
|
||||
//dixit ISG.
|
||||
|
||||
if (R6 <= gp::Resolution())
|
||||
Geom2d_UndefinedDerivative::Raise();
|
||||
|
||||
// V3 = P"' (U) :
|
||||
D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R2));
|
||||
D3Ndir.Subtract (
|
||||
(DNdir.Multiplied ((3.0 * offsetValue) * ((D2r/R2) + (Dr*Dr)/R4))));
|
||||
D3Ndir.Add (Ndir.Multiplied (
|
||||
(offsetValue * (6.0*Dr*Dr/R4 + 6.0*Dr*D2r/R4 - 15.0*Dr*Dr*Dr/R6 - D3r))));
|
||||
D3Ndir.Multiply (offsetValue/R);
|
||||
|
||||
if(IsDirectionChange)
|
||||
V3=-V3;
|
||||
|
||||
V3.Add (Vec2d(D3Ndir));
|
||||
|
||||
|
||||
// V2 = P" (U) :
|
||||
Standard_Real R4 = R2 * R2;
|
||||
D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
|
||||
D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
|
||||
D2Ndir.Multiply (offsetValue / R);
|
||||
V2.Add (Vec2d(D2Ndir));
|
||||
// V1 = P' (U) :
|
||||
DNdir.Multiply(R);
|
||||
DNdir.Subtract (Ndir.Multiplied (Dr/R));
|
||||
DNdir.Multiply (offsetValue/R2);
|
||||
theV1.Add (Vec2d(DNdir));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Same computation as IICURV in EUCLID-IS because the stability is
|
||||
// better.
|
||||
// V3 = P"' (U) :
|
||||
D3Ndir.Multiply (offsetValue/R);
|
||||
D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R3));
|
||||
D3Ndir.Subtract (DNdir.Multiplied (
|
||||
((3.0 * offsetValue) * ((D2r/R3) + (Dr*Dr)/R5))) );
|
||||
D3Ndir.Add (Ndir.Multiplied (
|
||||
(offsetValue * (6.0*Dr*Dr/R5 + 6.0*Dr*D2r/R5 - 15.0*Dr*Dr*Dr/R7 - D3r))));
|
||||
|
||||
if(IsDirectionChange)
|
||||
V3=-V3;
|
||||
|
||||
V3.Add (Vec2d(D3Ndir));
|
||||
|
||||
// V2 = P" (U) :
|
||||
D2Ndir.Multiply (offsetValue/R);
|
||||
D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
|
||||
D2Ndir.Subtract (Ndir.Multiplied (
|
||||
offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))));
|
||||
V2.Add (Vec2d(D2Ndir));
|
||||
// V1 = P' (U) :
|
||||
DNdir.Multiply (offsetValue/R);
|
||||
DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
|
||||
theV1.Add (Vec2d(DNdir));
|
||||
}
|
||||
//P (U) :
|
||||
D0(theU, P);
|
||||
}
|
||||
CSLib_Offset::D3(theP, theV1, theV2, theV3, V4, offsetValue, IsDirectionChange,
|
||||
theP, theV1, theV2, theV3);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : DN
|
||||
@@ -709,10 +349,10 @@ Standard_RangeError_Raise_if (N < 1, "Exception: Geom2d_OffsetCurve::DN(). N<1."
|
||||
void Geom2d_OffsetCurve::Value (const Standard_Real theU,
|
||||
Pnt2d& theP, Pnt2d& thePbasis,
|
||||
Vec2d& theV1basis ) const
|
||||
{
|
||||
{
|
||||
basisCurve->D1(theU, thePbasis, theV1basis);
|
||||
D0(theU,theP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=======================================================================
|
||||
@@ -741,30 +381,8 @@ void Geom2d_OffsetCurve::D1 (const Standard_Real U,
|
||||
if (Index != 2) {
|
||||
V2 = basisCurve->DN (U, Index);
|
||||
}
|
||||
XY Ndir (V1.Y(), -V1.X());
|
||||
XY DNdir (V2.Y(), -V2.X());
|
||||
Standard_Real R2 = Ndir.SquareModulus();
|
||||
Standard_Real R = Sqrt (R2);
|
||||
Standard_Real R3 = R * R2;
|
||||
Standard_Real Dr = Ndir.Dot (DNdir);
|
||||
if (R3 <= gp::Resolution()) {
|
||||
//We try another computation but the stability is not very good.
|
||||
if (R2 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
|
||||
DNdir.Multiply(R);
|
||||
DNdir.Subtract (Ndir.Multiplied (Dr/R));
|
||||
DNdir.Multiply (offsetValue / R2);
|
||||
V1.Add (Vec2d(DNdir));
|
||||
}
|
||||
else {
|
||||
// Same computation as IICURV in EUCLID-IS because the stability is
|
||||
// better
|
||||
DNdir.Multiply (offsetValue/R);
|
||||
DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
|
||||
V1.Add (Vec2d(DNdir));
|
||||
}
|
||||
Ndir.Multiply (offsetValue/R);
|
||||
Ndir.Add (Pbasis.XY());
|
||||
P.SetXY (Ndir);
|
||||
|
||||
CSLib_Offset::D1(P, V1, V2, offsetValue, Standard_False, P, V1);
|
||||
}
|
||||
|
||||
|
||||
@@ -800,52 +418,8 @@ void Geom2d_OffsetCurve::D2 (const Standard_Real U,
|
||||
V2 = basisCurve->DN (U, Index);
|
||||
V3 = basisCurve->DN (U, Index + 1);
|
||||
}
|
||||
XY Ndir (V1.Y(), -V1.X());
|
||||
XY DNdir (V2.Y(), -V2.X());
|
||||
XY D2Ndir (V3.Y(), -V3.X());
|
||||
Standard_Real R2 = Ndir.SquareModulus();
|
||||
Standard_Real R = Sqrt (R2);
|
||||
Standard_Real R3 = R2 * R;
|
||||
Standard_Real R4 = R2 * R2;
|
||||
Standard_Real R5 = R3 * R2;
|
||||
Standard_Real Dr = Ndir.Dot (DNdir);
|
||||
Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
|
||||
if (R5 <= gp::Resolution()) {
|
||||
//We try another computation but the stability is not very good
|
||||
//dixit ISG.
|
||||
if (R4 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
|
||||
// V2 = P" (U) :
|
||||
Standard_Real R4 = R2 * R2;
|
||||
D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
|
||||
D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
|
||||
D2Ndir.Multiply (offsetValue / R);
|
||||
V2.Add (Vec2d(D2Ndir));
|
||||
// V1 = P' (U) :
|
||||
DNdir.Multiply(R);
|
||||
DNdir.Subtract (Ndir.Multiplied (Dr/R));
|
||||
DNdir.Multiply (offsetValue/R2);
|
||||
V1.Add (Vec2d(DNdir));
|
||||
}
|
||||
else {
|
||||
// Same computation as IICURV in EUCLID-IS because the stability is
|
||||
// better.
|
||||
// V2 = P" (U) :
|
||||
D2Ndir.Multiply (offsetValue/R);
|
||||
D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
|
||||
D2Ndir.Subtract (Ndir.Multiplied (
|
||||
offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))
|
||||
)
|
||||
);
|
||||
V2.Add (Vec2d(D2Ndir));
|
||||
// V1 = P' (U) :
|
||||
DNdir.Multiply (offsetValue/R);
|
||||
DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
|
||||
V1.Add (Vec2d(DNdir));
|
||||
}
|
||||
//P (U) :
|
||||
Ndir.Multiply (offsetValue/R);
|
||||
Ndir.Add (Pbasis.XY());
|
||||
P.SetXY (Ndir);
|
||||
|
||||
CSLib_Offset::D2(P, V1, V2, V3, offsetValue, Standard_False, P, V1, V2);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -961,3 +535,57 @@ GeomAbs_Shape Geom2d_OffsetCurve::GetBasisCurveContinuity() const
|
||||
{
|
||||
return myBasisCurveContinuity;
|
||||
}
|
||||
|
||||
|
||||
// ============= Auxiliary functions ===================
|
||||
Standard_Boolean AdjustDerivative(const Handle(Geom2d_Curve)& theCurve, Standard_Integer theMaxDerivative,
|
||||
Standard_Real theU, gp_Vec2d& theD1, gp_Vec2d& theD2,
|
||||
gp_Vec2d& theD3, gp_Vec2d& theD4)
|
||||
{
|
||||
static const Standard_Real aTol = gp::Resolution();
|
||||
|
||||
Standard_Boolean IsDirectionChange = Standard_False;
|
||||
const Standard_Real anUinfium = theCurve->FirstParameter();
|
||||
const Standard_Real anUsupremum = theCurve->LastParameter();
|
||||
|
||||
const Standard_Real DivisionFactor = 1.e-3;
|
||||
Standard_Real du;
|
||||
if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
|
||||
du = 0.0;
|
||||
else
|
||||
du = anUsupremum - anUinfium;
|
||||
|
||||
const Standard_Real aDelta = Max(du * DivisionFactor, MinStep);
|
||||
|
||||
//Derivative is approximated by Taylor-series
|
||||
Standard_Integer anIndex = 1; //Derivative order
|
||||
Vec2d V;
|
||||
|
||||
do
|
||||
{
|
||||
V = theCurve->DN(theU, ++anIndex);
|
||||
}
|
||||
while((V.SquareMagnitude() <= aTol) && anIndex < maxDerivOrder);
|
||||
|
||||
Standard_Real u;
|
||||
|
||||
if(theU-anUinfium < aDelta)
|
||||
u = theU+aDelta;
|
||||
else
|
||||
u = theU-aDelta;
|
||||
|
||||
Pnt2d P1, P2;
|
||||
theCurve->D0(Min(theU, u),P1);
|
||||
theCurve->D0(Max(theU, u),P2);
|
||||
|
||||
Vec2d V1(P1,P2);
|
||||
IsDirectionChange = V.Dot(V1) < 0.0;
|
||||
Standard_Real aSign = IsDirectionChange ? -1.0 : 1.0;
|
||||
|
||||
theD1 = V * aSign;
|
||||
gp_Vec2d* aDeriv[3] = {&theD2, &theD3, &theD4};
|
||||
for (Standard_Integer i = 1; i < theMaxDerivative; i++)
|
||||
*(aDeriv[i-1]) = theCurve->DN(theU, anIndex + i) * aSign;
|
||||
|
||||
return IsDirectionChange;
|
||||
}
|
||||
|
Reference in New Issue
Block a user