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

@@ -104,6 +104,8 @@ uses TColStd, gp, TColgp, math, GeomAbs
is
imported transient class Cache;
imported EvaluatorFunction ;
@@ -2063,6 +2065,30 @@ is
-- If rational computes the homogeneous Taylor expension
-- for the numerator and stores it in CachePoles
BuildCache(theParameter : Real;
theSpanDomain : Real;
thePeriodicFlag : Boolean ;
theDegree : Integer;
theFlatKnots : Array1OfReal from TColStd ;
thePoles : Array1OfPnt from TColgp;
theWeights : Array1OfReal from TColStd ;
theCacheArray : in out Array2OfReal from TColStd) ;
---Purpose: Perform the evaluation of the Taylor expansion
-- of the Bspline normalized between 0 and 1.
-- Structure of result optimized for BSplCLib_Cache.
BuildCache(theParameter : Real;
theSpanDomain : Real;
thePeriodicFlag : Boolean ;
theDegree : Integer;
theFlatKnots : Array1OfReal from TColStd ;
thePoles : Array1OfPnt2d from TColgp;
theWeights : Array1OfReal from TColStd ;
theCacheArray : in out Array2OfReal from TColStd) ;
---Purpose: Perform the evaluation of the Taylor expansion
-- of the Bspline normalized between 0 and 1.
-- Structure of result optimized for BSplCLib_Cache.
PolesCoefficients(Poles : Array1OfPnt2d from TColgp;
CachePoles : in out Array1OfPnt2d from TColgp);
---Warning: To be used for Beziercurves ONLY!!!
@@ -2454,6 +2480,7 @@ is
-- all u1 and u0 in the domain of the curve f(u)
-- | u1 - u0 | < UTolerance and
-- we have |f (u1) - f (u0)| < Tolerance3D
end BSplCLib;

View File

@@ -73,6 +73,7 @@ void BSplCLib::Hunt (const Array1OfReal& XX,
{
// replaced by simple dichotomy (RLE)
Ilc = XX.Lower();
if (XX.Length() <= 1) return;
const Standard_Real *px = &XX(Ilc);
px -= Ilc;

View File

@@ -0,0 +1,362 @@
// Copyright (c) 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.
#include <BSplCLib_Cache.hxx>
#include <BSplCLib.hxx>
#include <NCollection_LocalArray.hxx>
#include <TColgp_HArray1OfPnt.hxx>
#include <TColgp_HArray1OfPnt2d.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <TColStd_HArray2OfReal.hxx>
IMPLEMENT_STANDARD_HANDLE(BSplCLib_Cache, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT(BSplCLib_Cache, Standard_Transient)
//! Converts handle of array of Standard_Real into the pointer to Standard_Real
static Standard_Real* ConvertArray(const Handle_TColStd_HArray2OfReal& theHArray)
{
const TColStd_Array2OfReal& anArray = theHArray->Array2();
return (Standard_Real*) &(anArray(anArray.LowerRow(), anArray.LowerCol()));
}
BSplCLib_Cache::BSplCLib_Cache()
{
myPolesWeights.Nullify();
myIsRational = Standard_False;
mySpanStart = 0.0;
mySpanLength = 0.0;
mySpanIndex = 0;
myDegree = 0;
myFlatKnots.Nullify();
}
BSplCLib_Cache::BSplCLib_Cache(const Standard_Integer& theDegree,
const Standard_Boolean& thePeriodic,
const TColStd_Array1OfReal& theFlatKnots,
const TColgp_Array1OfPnt2d& thePoles2d,
const TColStd_Array1OfReal& theWeights)
{
Standard_Real aCacheParam = theFlatKnots.Value(theFlatKnots.Lower() + theDegree);
BuildCache(aCacheParam, theDegree, thePeriodic,
theFlatKnots, thePoles2d, theWeights);
}
BSplCLib_Cache::BSplCLib_Cache(const Standard_Integer& theDegree,
const Standard_Boolean& thePeriodic,
const TColStd_Array1OfReal& theFlatKnots,
const TColgp_Array1OfPnt& thePoles,
const TColStd_Array1OfReal& theWeights)
{
Standard_Real aCacheParam = theFlatKnots.Value(theFlatKnots.Lower() + theDegree);
BuildCache(aCacheParam, theDegree, thePeriodic,
theFlatKnots, thePoles, theWeights);
}
Standard_Boolean BSplCLib_Cache::IsCacheValid(Standard_Real theParameter) const
{
Standard_Real aNewParam = theParameter;
if (!myFlatKnots.IsNull())
PeriodicNormalization(myFlatKnots->Array1(), aNewParam);
Standard_Real aDelta = aNewParam - mySpanStart;
return (aDelta >= 0.0 && (aDelta < mySpanLength || mySpanIndex == mySpanIndexMax));
}
void BSplCLib_Cache::PeriodicNormalization(const TColStd_Array1OfReal& theFlatKnots,
Standard_Real& theParameter) const
{
Standard_Real aPeriod = theFlatKnots.Value(theFlatKnots.Upper() - myDegree) -
theFlatKnots.Value(myDegree + 1) ;
if (theParameter < theFlatKnots.Value(myDegree + 1))
{
Standard_Real aScale = IntegerPart(
(theFlatKnots.Value(myDegree + 1) - theParameter) / aPeriod);
theParameter += aPeriod * (aScale + 1.0);
}
if (theParameter > theFlatKnots.Value(theFlatKnots.Upper() - myDegree))
{
Standard_Real aScale = IntegerPart(
(theParameter - theFlatKnots.Value(theFlatKnots.Upper() - myDegree)) / aPeriod);
theParameter -= aPeriod * (aScale + 1.0);
}
}
void BSplCLib_Cache::BuildCache(const Standard_Real& theParameter,
const Standard_Integer& theDegree,
const Standard_Boolean& thePeriodic,
const TColStd_Array1OfReal& theFlatKnots,
const TColgp_Array1OfPnt2d& thePoles2d,
const TColStd_Array1OfReal& theWeights)
{
// Normalize theParameter for periodical B-splines
Standard_Real aNewParam = theParameter;
if (thePeriodic)
{
PeriodicNormalization(theFlatKnots, aNewParam);
myFlatKnots = new TColStd_HArray1OfReal(1, theFlatKnots.Length());
myFlatKnots->ChangeArray1() = theFlatKnots;
}
else if (!myFlatKnots.IsNull()) // Periodical curve became non-periodical
myFlatKnots.Nullify();
// Change the size of cached data if needed
myIsRational = (&theWeights != NULL);
Standard_Integer aPWColNumber = myIsRational ? 3 : 2;
if (theDegree > myDegree)
myPolesWeights = new TColStd_HArray2OfReal(1, theDegree + 1, 1, aPWColNumber);
myDegree = theDegree;
mySpanIndex = 0;
BSplCLib::LocateParameter(theDegree, theFlatKnots, BSplCLib::NoMults(),
aNewParam, thePeriodic, mySpanIndex, aNewParam);
mySpanStart = theFlatKnots.Value(mySpanIndex);
mySpanLength = theFlatKnots.Value(mySpanIndex + 1) - mySpanStart;
mySpanIndexMax = theFlatKnots.Length() - 1 - theDegree;
// Calculate new cache data
BSplCLib::BuildCache(mySpanStart, mySpanLength, thePeriodic, theDegree,
theFlatKnots, thePoles2d, theWeights,
myPolesWeights->ChangeArray2());
}
void BSplCLib_Cache::BuildCache(const Standard_Real& theParameter,
const Standard_Integer& theDegree,
const Standard_Boolean& thePeriodic,
const TColStd_Array1OfReal& theFlatKnots,
const TColgp_Array1OfPnt& thePoles,
const TColStd_Array1OfReal& theWeights)
{
// Create list of knots with repetitions and normalize theParameter for periodical B-splines
Standard_Real aNewParam = theParameter;
if (thePeriodic)
{
PeriodicNormalization(theFlatKnots, aNewParam);
myFlatKnots = new TColStd_HArray1OfReal(1, theFlatKnots.Length());
myFlatKnots->ChangeArray1() = theFlatKnots;
}
else if (!myFlatKnots.IsNull()) // Periodical curve became non-periodical
myFlatKnots.Nullify();
// Change the size of cached data if needed
myIsRational = (&theWeights != NULL);
Standard_Integer aPWColNumber = myIsRational ? 4 : 3;
if (theDegree > myDegree)
myPolesWeights = new TColStd_HArray2OfReal(1, theDegree + 1, 1, aPWColNumber);
myDegree = theDegree;
mySpanIndex = 0;
BSplCLib::LocateParameter(theDegree, theFlatKnots, BSplCLib::NoMults(),
aNewParam, thePeriodic, mySpanIndex, aNewParam);
mySpanStart = theFlatKnots.Value(mySpanIndex);
mySpanLength = theFlatKnots.Value(mySpanIndex + 1) - mySpanStart;
mySpanIndexMax = theFlatKnots.Length() - 1 - theDegree;
// Calculate new cache data
BSplCLib::BuildCache(mySpanStart, mySpanLength, thePeriodic, theDegree,
theFlatKnots, thePoles, theWeights,
myPolesWeights->ChangeArray2());
}
void BSplCLib_Cache::CalculateDerivative(const Standard_Real& theParameter,
const Standard_Integer& theDerivative,
Standard_Real& theDerivArray) const
{
Standard_Real aNewParameter = theParameter;
if (!myFlatKnots.IsNull()) // B-spline is periodical
PeriodicNormalization(myFlatKnots->Array1(), aNewParameter);
aNewParameter = (aNewParameter - mySpanStart) / mySpanLength;
Standard_Real* aPolesArray = ConvertArray(myPolesWeights);
Standard_Integer aDimension = myPolesWeights->RowLength(); // number of columns
// Temporary container. The maximal size of this container is defined by:
// 1) maximal derivative for cache evaluation, which is 3, plus one row for function values,
// 2) and maximal dimension of the point, which is 3, plus one column for weights.
Standard_Real aTmpContainer[16];
// When the PLib::RationaDerivative needs to be called, use temporary container
Standard_Real* aPntDeriv = myIsRational ? aTmpContainer : &theDerivArray;
// When the degree of curve is lesser than the requested derivative,
// nullify array cells corresponding to greater derivatives
Standard_Integer aDerivative = theDerivative;
if (myDegree < theDerivative)
{
aDerivative = myDegree;
for (Standard_Integer ind = myDegree * aDimension; ind < (theDerivative + 1) * aDimension; ind++)
{
aPntDeriv[ind] = 0.0;
(&theDerivArray)[ind] = 0.0; // should be cleared separately, because aPntDeriv may look to another memory area
}
}
PLib::EvalPolynomial(aNewParameter, aDerivative, myDegree, aDimension,
aPolesArray[0], aPntDeriv[0]);
// Unnormalize derivatives since those are computed normalized
Standard_Real aFactor = 1.0;
for (Standard_Integer deriv = 1; deriv <= aDerivative; deriv++)
{
aFactor /= mySpanLength;
for (Standard_Integer ind = 0; ind < aDimension; ind++)
aPntDeriv[aDimension * deriv + ind] *= aFactor;
}
if (myIsRational) // calculate derivatives divided by weights derivatives
PLib::RationalDerivative(aDerivative, aDerivative, aDimension - 1, aPntDeriv[0], theDerivArray);
}
void BSplCLib_Cache::D0(const Standard_Real& theParameter, gp_Pnt2d& thePoint) const
{
Standard_Real aNewParameter = theParameter;
if (!myFlatKnots.IsNull()) // B-spline is periodical
PeriodicNormalization(myFlatKnots->Array1(), aNewParameter);
aNewParameter = (aNewParameter - mySpanStart) / mySpanLength;
Standard_Real* aPolesArray = ConvertArray(myPolesWeights);
Standard_Real aPoint[4];
Standard_Integer aDimension = myPolesWeights->RowLength(); // number of columns
PLib::NoDerivativeEvalPolynomial(aNewParameter, myDegree,
aDimension, myDegree * aDimension,
aPolesArray[0], aPoint[0]);
thePoint.SetCoord(aPoint[0], aPoint[1]);
if (myIsRational)
thePoint.ChangeCoord().Divide(aPoint[2]);
}
void BSplCLib_Cache::D0(const Standard_Real& theParameter, gp_Pnt& thePoint) const
{
Standard_Real aNewParameter = theParameter;
if (!myFlatKnots.IsNull()) // B-spline is periodical
PeriodicNormalization(myFlatKnots->Array1(), aNewParameter);
aNewParameter = (aNewParameter - mySpanStart) / mySpanLength;
Standard_Real* aPolesArray = ConvertArray(myPolesWeights);
Standard_Real aPoint[4];
Standard_Integer aDimension = myPolesWeights->RowLength(); // number of columns
PLib::NoDerivativeEvalPolynomial(aNewParameter, myDegree,
aDimension, myDegree * aDimension,
aPolesArray[0], aPoint[0]);
thePoint.SetCoord(aPoint[0], aPoint[1], aPoint[2]);
if (myIsRational)
thePoint.ChangeCoord().Divide(aPoint[3]);
}
void BSplCLib_Cache::D1(const Standard_Real& theParameter, gp_Pnt2d& thePoint, gp_Vec2d& theTangent) const
{
Standard_Integer aDimension = myPolesWeights->RowLength(); // number of columns
Standard_Real aPntDeriv[8]; // result storage (point and derivative coordinates)
this->CalculateDerivative(theParameter, 1, aPntDeriv[0]);
if (myIsRational) // the size of aPntDeriv was changed by PLib::RationalDerivative
aDimension -= 1;
thePoint.SetCoord(aPntDeriv[0], aPntDeriv[1]);
theTangent.SetCoord(aPntDeriv[aDimension], aPntDeriv[aDimension + 1]);
}
void BSplCLib_Cache::D1(const Standard_Real& theParameter, gp_Pnt& thePoint, gp_Vec& theTangent) const
{
Standard_Integer aDimension = myPolesWeights->RowLength(); // number of columns
Standard_Real aPntDeriv[8]; // result storage (point and derivative coordinates)
this->CalculateDerivative(theParameter, 1, aPntDeriv[0]);
if (myIsRational) // the size of aPntDeriv was changed by PLib::RationalDerivative
aDimension -= 1;
thePoint.SetCoord(aPntDeriv[0], aPntDeriv[1], aPntDeriv[2]);
theTangent.SetCoord(aPntDeriv[aDimension], aPntDeriv[aDimension + 1], aPntDeriv[aDimension + 2]);
}
void BSplCLib_Cache::D2(const Standard_Real& theParameter, gp_Pnt2d& thePoint, gp_Vec2d& theTangent, gp_Vec2d& theCurvature) const
{
Standard_Integer aDimension = myPolesWeights->RowLength(); // number of columns
Standard_Real aPntDeriv[12]; // result storage (point and derivatives coordinates)
this->CalculateDerivative(theParameter, 2, aPntDeriv[0]);
if (myIsRational) // the size of aPntDeriv was changed by PLib::RationalDerivative
aDimension -= 1;
thePoint.SetCoord(aPntDeriv[0], aPntDeriv[1]);
theTangent.SetCoord(aPntDeriv[aDimension], aPntDeriv[aDimension + 1]);
theCurvature.SetCoord(aPntDeriv[aDimension<<1], aPntDeriv[(aDimension<<1) + 1]);
}
void BSplCLib_Cache::D2(const Standard_Real& theParameter, gp_Pnt& thePoint, gp_Vec& theTangent, gp_Vec& theCurvature) const
{
Standard_Integer aDimension = myPolesWeights->RowLength(); // number of columns
Standard_Real aPntDeriv[12]; // result storage (point and derivatives coordinates)
this->CalculateDerivative(theParameter, 2, aPntDeriv[0]);
if (myIsRational) // the size of aPntDeriv was changed by PLib::RationalDerivative
aDimension -= 1;
thePoint.SetCoord(aPntDeriv[0], aPntDeriv[1], aPntDeriv[2]);
theTangent.SetCoord(aPntDeriv[aDimension], aPntDeriv[aDimension + 1], aPntDeriv[aDimension + 2]);
theCurvature.SetCoord(aPntDeriv[aDimension<<1], aPntDeriv[(aDimension<<1) + 1], aPntDeriv[(aDimension<<1) + 2]);
}
void BSplCLib_Cache::D3(const Standard_Real& theParameter,
gp_Pnt2d& thePoint,
gp_Vec2d& theTangent,
gp_Vec2d& theCurvature,
gp_Vec2d& theTorsion) const
{
Standard_Integer aDimension = myPolesWeights->RowLength(); // number of columns
Standard_Real aPntDeriv[16]; // result storage (point and derivatives coordinates)
this->CalculateDerivative(theParameter, 3, aPntDeriv[0]);
if (myIsRational) // the size of aPntDeriv was changed by PLib::RationalDerivative
aDimension -= 1;
thePoint.SetCoord(aPntDeriv[0], aPntDeriv[1]);
theTangent.SetCoord(aPntDeriv[aDimension], aPntDeriv[aDimension + 1]);
Standard_Integer aShift = aDimension << 1;
theCurvature.SetCoord(aPntDeriv[aShift], aPntDeriv[aShift + 1]);
aShift += aDimension;
theTorsion.SetCoord(aPntDeriv[aShift], aPntDeriv[aShift + 1]);
}
void BSplCLib_Cache::D3(const Standard_Real& theParameter,
gp_Pnt& thePoint,
gp_Vec& theTangent,
gp_Vec& theCurvature,
gp_Vec& theTorsion) const
{
Standard_Integer aDimension = myPolesWeights->RowLength(); // number of columns
Standard_Real aPntDeriv[16]; // result storage (point and derivatives coordinates)
this->CalculateDerivative(theParameter, 3, aPntDeriv[0]);
if (myIsRational) // the size of aPntDeriv was changed by PLib::RationalDerivative
aDimension -= 1;
thePoint.SetCoord(aPntDeriv[0], aPntDeriv[1], aPntDeriv[2]);
theTangent.SetCoord(aPntDeriv[aDimension], aPntDeriv[aDimension + 1], aPntDeriv[aDimension + 2]);
Standard_Integer aShift = aDimension << 1;
theCurvature.SetCoord(aPntDeriv[aShift], aPntDeriv[aShift + 1], aPntDeriv[aShift + 2]);
aShift += aDimension;
theTorsion.SetCoord(aPntDeriv[aShift], aPntDeriv[aShift + 1], aPntDeriv[aShift + 2]);
}

View File

@@ -0,0 +1,182 @@
// Copyright (c) 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.
#ifndef _BSplCLib_Cache_Headerfile
#define _BSplCLib_Cache_Headerfile
#include <Standard.hxx>
#include <Standard_Macro.hxx>
#include <Standard_DefineHandle.hxx>
#include <Standard_Transient.hxx>
#include <Handle_TColStd_HArray1OfReal.hxx>
#include <Handle_TColStd_HArray2OfReal.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec2d.hxx>
#include <gp_Vec.hxx>
class Handle(BSplCLib_Cache);
class TColStd_Array1OfReal;
class TColgp_Array1OfPnt;
class TColgp_Array1OfPnt2d;
#ifndef NOWEIGHTS_CURVE
#define NOWEIGHTS_CURVE (*((TColStd_Array1OfReal*) NULL))
#endif
//! \brief A cache class for B-spline curves.
//!
//! Defines all data, that can be cached on a span of B-spline curve.
//! The data should be recalculated in going from span to span.
class BSplCLib_Cache : public Standard_Transient
{
public:
//! Default constructor
Standard_EXPORT BSplCLib_Cache();
//! Constructor for caching of 2D curves
//! \param theDegree degree of the B-spline
//! \param thePeriodic identify the B-spline is periodic
//! \param theFlatKnots knots of B-spline curve (with repetitions)
//! \param thePoles2d array of poles of 2D B-spline
//! \param theWeights array of weights of corresponding poles
Standard_EXPORT BSplCLib_Cache(const Standard_Integer& theDegree,
const Standard_Boolean& thePeriodic,
const TColStd_Array1OfReal& theFlatKnots,
const TColgp_Array1OfPnt2d& thePoles2d,
const TColStd_Array1OfReal& theWeights = NOWEIGHTS_CURVE);
//! Constructor for caching of 3D curves
//! \param theDegree degree of the B-spline
//! \param thePeriodic identify the B-spline is periodic
//! \param theFlatKnots knots of B-spline curve (with repetitions)
//! \param thePoles array of poles of 3D B-spline
//! \param theWeights array of weights of corresponding poles
Standard_EXPORT BSplCLib_Cache(const Standard_Integer& theDegree,
const Standard_Boolean& thePeriodic,
const TColStd_Array1OfReal& theFlatKnots,
const TColgp_Array1OfPnt& thePoles,
const TColStd_Array1OfReal& theWeights = NOWEIGHTS_CURVE);
//! Verifies validity of the cache using flat parameter of the point
//! \param theParameter parameter of the point placed in the span
Standard_EXPORT Standard_Boolean IsCacheValid(Standard_Real theParameter) const;
//! Recomputes the cache data for 2D curves. Does not verify validity of the cache
//! \param theParameter the value on the knot's axis to identify the span
//! \param theDegree degree of the B-spline
//! \param thePeriodic identify the B-spline is periodic
//! \param theFlatKnots knots of B-spline curve (with repetitions)
//! \param thePoles2d array of poles of 2D B-spline
//! \param theWeights array of weights of corresponding poles
Standard_EXPORT void BuildCache(const Standard_Real& theParameter,
const Standard_Integer& theDegree,
const Standard_Boolean& thePeriodic,
const TColStd_Array1OfReal& theFlatKnots,
const TColgp_Array1OfPnt2d& thePoles2d,
const TColStd_Array1OfReal& theWeights = NOWEIGHTS_CURVE);
//! Recomputes the cache data for 3D curves. Does not verify validity of the cache
//! \param theParameter the value on the knot's axis to identify the span
//! \param theDegree degree of the B-spline
//! \param thePeriodic identify the B-spline is periodic
//! \param theFlatKnots knots of B-spline curve (with repetitions)
//! \param thePoles array of poles of 3D B-spline
//! \param theWeights array of weights of corresponding poles
Standard_EXPORT void BuildCache(const Standard_Real& theParameter,
const Standard_Integer& theDegree,
const Standard_Boolean& thePeriodic,
const TColStd_Array1OfReal& theFlatKnots,
const TColgp_Array1OfPnt& thePoles,
const TColStd_Array1OfReal& theWeights = NOWEIGHTS_CURVE);
//! Calculates the point on B-spline in the selected point
//! \param[in] theParameter parameter of calculation of the value
//! \param[out] thePoint the result of calculation (the point on B-spline)
Standard_EXPORT void D0(const Standard_Real& theParameter, gp_Pnt2d& thePoint) const;
Standard_EXPORT void D0(const Standard_Real& theParameter, gp_Pnt& thePoint) const;
//! Calculates the point on B-spline and its first derivative in the selected point
//! \param[in] theParameter parameter of calculation of the value
//! \param[out] thePoint the result of calculation (the point on B-spline)
//! \param[out] theTangent tangent vector (first derivatives) for B-spline in the calculated point
Standard_EXPORT void D1(const Standard_Real& theParameter, gp_Pnt2d& thePoint, gp_Vec2d& theTangent) const;
Standard_EXPORT void D1(const Standard_Real& theParameter, gp_Pnt& thePoint, gp_Vec& theTangent) const;
//! Calculates the point on B-spline and two derivatives in the selected point
//! \param[in] theParameter parameter of calculation of the value
//! \param[out] thePoint the result of calculation (the point on B-spline)
//! \param[out] theTangent tangent vector (1st derivatives) for B-spline in the calculated point
//! \param[out] theCurvature curvature vector (2nd derivatives) for B-spline in the calculated point
Standard_EXPORT void D2(const Standard_Real& theParameter,
gp_Pnt2d& thePoint,
gp_Vec2d& theTangent,
gp_Vec2d& theCurvature) const;
Standard_EXPORT void D2(const Standard_Real& theParameter,
gp_Pnt& thePoint,
gp_Vec& theTangent,
gp_Vec& theCurvature) const;
//! Calculates the point on B-spline and three derivatives in the selected point
//! \param[in] theParameter parameter of calculation of the value
//! \param[out] thePoint the result of calculation (the point on B-spline)
//! \param[out] theTangent tangent vector (1st derivatives) for B-spline in the calculated point
//! \param[out] theCurvature curvature vector (2nd derivatives) for B-spline in the calculated point
//! \param[out] theTorsion second curvature vector (3rd derivatives) for B-spline in the calculated point
Standard_EXPORT void D3(const Standard_Real& theParameter,
gp_Pnt2d& thePoint,
gp_Vec2d& theTangent,
gp_Vec2d& theCurvature,
gp_Vec2d& theTorsion) const;
Standard_EXPORT void D3(const Standard_Real& theParameter,
gp_Pnt& thePoint,
gp_Vec& theTangent,
gp_Vec& theCurvature,
gp_Vec& theTorsion) const;
DEFINE_STANDARD_RTTI(BSplCLib_Cache)
protected:
//! Normalizes the parameter for periodical B-splines
//! \param theFlatKnots knots with repetitions
//! \param theParameter the value to be normalized into the knots array
void PeriodicNormalization(const TColStd_Array1OfReal& theFlatKnots, Standard_Real& theParameter) const;
//! Fills array of derivatives in the selected point of the B-spline
//! \param[in] theParameter parameter of the calculation
//! \param[in] theDerivative maximal derivative to be calculated (computes all derivatives lesser than specified)
//! \param[out] theDerivArray result array of derivatives (with size (theDerivative+1)*(PntDim+1),
//! where PntDim = 2 or 3 is a dimension of B-spline curve)
void CalculateDerivative(const Standard_Real& theParameter,
const Standard_Integer& theDerivative,
Standard_Real& theDerivArray) const;
private:
Handle(TColStd_HArray2OfReal) myPolesWeights; ///< array of poles and weights of calculated cache
// the array has following structure:
// x1 y1 [z1] [w1]
// x2 y2 [z2] [w2] etc
// for 2D-curves there is no z conponent, for non-rational curves there is no weight
Standard_Boolean myIsRational; ///< identifies the rationality of B-spline
Standard_Real mySpanStart; ///< parameter for the first point of the span
Standard_Real mySpanLength; ///< length of the span
Standard_Integer mySpanIndex; ///< index of the span on B-spline curve
Standard_Integer mySpanIndexMax; ///< maximal number of spans on B-spline curve
Standard_Integer myDegree; ///< degree of B-spline
Handle(TColStd_HArray1OfReal) myFlatKnots; ///< knots of B-spline (used for periodic normalization of parameters, exists only for periodical splines)
};
DEFINE_STANDARD_HANDLE(BSplCLib_Cache, Standard_Transient)
#endif

View File

@@ -19,6 +19,7 @@
// xab : 12-Mar-96 : added MovePointAndTangent
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array2OfReal.hxx>
#include <gp_Vec2d.hxx>
#include <Standard_ConstructionError.hxx>
#include <PLib.hxx>
@@ -1089,6 +1090,65 @@ void BSplCLib::BuildCache
}
}
void BSplCLib::BuildCache(const Standard_Real theParameter,
const Standard_Real theSpanDomain,
const Standard_Boolean thePeriodicFlag,
const Standard_Integer theDegree,
const TColStd_Array1OfReal& theFlatKnots,
const Array1OfPoints& thePoles,
const TColStd_Array1OfReal& theWeights,
TColStd_Array2OfReal& theCacheArray)
{
Standard_Real aParam = theParameter;
Standard_Integer anIndex = 0;
Standard_Integer aDimension;
Standard_Boolean isRational;
BSplCLib_DataContainer dc(theDegree);
PrepareEval(aParam,
anIndex,
aDimension,
isRational,
theDegree,
thePeriodicFlag,
thePoles,
theWeights,
theFlatKnots,
(BSplCLib::NoMults()),
dc);
//
// Watch out : PrepareEval checks if locally the Bspline is polynomial
// therefore rational flag could be set to False even if there are
// Weights. The Dimension is set accordingly.
//
Standard_Integer aCacheShift = // helps to store weights when PrepareEval did not found that the curve is locally polynomial
(&theWeights != NULL && !isRational) ? aDimension + 1 : aDimension;
BSplCLib::Bohm(aParam, theDegree, theDegree, *dc.knots, aDimension, *dc.poles);
Standard_Real aCoeff = 1.0;
Standard_Real* aCache = (Standard_Real *) &(theCacheArray(theCacheArray.LowerRow(), theCacheArray.LowerCol()));
Standard_Real* aPolyCoeffs = dc.poles;
for (Standard_Integer i = 0; i <= theDegree; i++)
{
for (Standard_Integer j = 0; j< aDimension; j++)
aCache[j] = aPolyCoeffs[j] * aCoeff;
aCoeff *= theSpanDomain / (i+1);
aPolyCoeffs += aDimension;
aCache += aDimension;
if (aCacheShift > aDimension)
{
aCache[0] = 0.0;
aCache++;
}
}
if (aCacheShift > aDimension)
theCacheArray.SetValue(theCacheArray.LowerRow(), theCacheArray.LowerCol() + aCacheShift - 1, 1.0);
}
//=======================================================================
//function : Interpolate
//purpose :

View File

@@ -4,4 +4,5 @@ BSplCLib_3.cxx
BSplCLib_BzSyntaxes.cxx
BSplCLib_CurveComputation.gxx
BSplCLib_EvaluatorFunction.hxx
BSplCLib_Cache.hxx
BSplCLib_Cache.cxx