1
0
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:
azv
2015-05-28 13:36:57 +03:00
committed by bugmaster
parent 9176540c64
commit 94f71cad33
137 changed files with 4104 additions and 2503 deletions

View File

@@ -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;

View File

@@ -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 ;
}

View File

@@ -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;
}

View File

@@ -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;
}