1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-04 13:13:25 +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

@@ -28,7 +28,9 @@ uses
TColStd,
Geom2dAdaptor,
TColgp,
Precision
Precision,
BSplCLib,
BSplSLib
is
class Curve;

View File

@@ -33,7 +33,8 @@ uses Vec from gp,
BSplineCurve from Geom,
CurveType from GeomAbs,
Shape from GeomAbs,
HCurve from Adaptor3d
HCurve from Adaptor3d,
Cache from BSplCLib
raises NoSuchObject from Standard,
ConstructionError from Standard,
@@ -129,10 +130,26 @@ is
--- Purpose : Computes the point of parameter U on the curve
is redefined static;
ValueBSpline(me; U: Real) returns Pnt from gp
--- Purpose : Computes the point of parameter U on the B-spline curve
is private;
ValueOffset(me; U: Real) returns Pnt from gp
--- Purpose : Computes the point of parameter U on the offset curve
is private;
D0 (me; U : Real; P : out Pnt from gp)
--- Purpose : Computes the point of parameter U.
is redefined static;
D0BSpline(me; theU : Real; theP : out Pnt from gp)
--- Purpose : Computes the point of parameter U on the B-spline curve
is private;
D0Offset(me; theU : Real; theP : out Pnt from gp)
--- Purpose : Computes the point of parameter U on the offset curve
is private;
D1 (me; U : Real; P : out Pnt from gp ; V : out Vec from gp)
--- Purpose : Computes the point of parameter U on the curve
-- with its first derivative.
@@ -142,6 +159,16 @@ is
-- derivatives are computed on the current interval.
-- else the derivatives are computed on the basis curve.
is redefined static;
D1BSpline(me; theU : Real; theP : out Pnt from gp ; theV : out Vec from gp)
--- Purpose : Computes the point of parameter U on the B-spline curve
-- and its derivative
is private;
D1Offset(me; theU : Real; theP : out Pnt from gp ; theV : out Vec from gp)
--- Purpose : Computes the point of parameter U on the offset curve
-- and its derivative
is private;
D2 (me; U : Real; P : out Pnt from gp; V1, V2 : out Vec from gp)
--- Purpose :
@@ -154,6 +181,16 @@ is
-- else the derivatives are computed on the basis curve.
is redefined static;
D2BSpline(me; theU : Real; theP : out Pnt from gp; theV1, theV2 : out Vec from gp)
--- Purpose : Computes the point of parameter U on the B-spline curve
-- and its first and second derivatives
is private;
D2Offset(me; theU : Real; theP : out Pnt from gp; theV1, theV2 : out Vec from gp)
--- Purpose : Computes the point of parameter U on the offset curve
-- and its first and second derivatives
is private;
D3 (me; U : Real; P : out Pnt from gp; V1, V2, V3 : out Vec from gp)
--- Purpose :
-- Returns the point P of parameter U, the first, the second
@@ -164,6 +201,16 @@ is
-- derivatives are computed on the current interval.
-- else the derivatives are computed on the basis curve.
is redefined static;
D3BSpline(me; theU : Real; theP : out Pnt from gp; theV1, theV2, theV3 : out Vec from gp)
--- Purpose : Computes the point of parameter U on the B-spline curve
-- and its first, second and third derivatives
is private;
D3Offset(me; theU : Real; theP : out Pnt from gp; theV1, theV2, theV3 : out Vec from gp)
--- Purpose : Computes the point of parameter U on the offset curve
-- and its first, second and third derivatives
is private;
DN (me; U : Real; N : Integer) returns Vec from gp
--- Purpose :
@@ -179,6 +226,19 @@ is
is redefined static;
DNBSpline(me; theU : Real; N : Integer) returns Vec from gp
--- Purpose :
-- The returned vector gives the value of the derivative for the
-- order of derivation N.
is private;
DNOffset(me; theU : Real; N : Integer) returns Vec from gp
--- Purpose :
-- The returned vector gives the value of the derivative for the
-- order of derivation N.
is private;
Resolution(me; R3d :Real) returns Real
---Purpose : returns the parametric resolution
is redefined static;
@@ -279,6 +339,11 @@ is
load(me : in out; C : Curve from Geom; UFirst,ULast : Real)
is private;
RebuildCache(me; theParameter : Real)
---Purpose: Rebuilds B-spline cache
-- \param theParameter the value on the knot axis which identifies the caching span
is static private;
fields
@@ -286,6 +351,8 @@ fields
myTypeCurve : CurveType from GeomAbs ;
myFirst : Real from Standard ;
myLast : Real from Standard;
myCurveCache : Cache from BSplCLib;
myOffsetBaseCurveAdaptor : HCurve from Adaptor3d;
friends
class Surface from GeomAdaptor

View File

@@ -26,6 +26,7 @@
#include <GeomAdaptor_HCurve.hxx>
#include <Adaptor3d_HCurve.hxx>
#include <BSplCLib.hxx>
#include <BSplCLib_Cache.hxx>
#include <GeomAbs_Shape.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
@@ -48,10 +49,22 @@
#include <Standard_NullObject.hxx>
#include <Standard_NotImplemented.hxx>
#include <Geom_OffsetCurve.hxx>
#include <CSLib_Offset.hxx>
#define myBspl (*((Handle(Geom_BSplineCurve)*)&myCurve))
#define PosTol Precision::PConfusion()/2
static const int maxDerivOrder = 3;
static const Standard_Real MinStep = 1e-7;
static gp_Vec 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(Adaptor3d_HCurve)& theAdaptor, Standard_Integer theMaxDerivative, Standard_Real theU, gp_Vec& theD1,
gp_Vec& theD2 = dummyDerivative, gp_Vec& theD3 = dummyDerivative, gp_Vec& theD4 = dummyDerivative);
//=======================================================================
//function : LocalContinuity
//purpose : Computes the Continuity of a BSplineCurve
@@ -155,6 +168,15 @@ void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
}
else if ( TheType == STANDARD_TYPE(Geom_BSplineCurve)) {
myTypeCurve = GeomAbs_BSplineCurve;
// Create cache for B-spline
myCurveCache = new BSplCLib_Cache(myBspl->Degree(), myBspl->IsPeriodic(),
myBspl->KnotSequence(), myBspl->Poles(), myBspl->Weights());
}
else if ( TheType == STANDARD_TYPE(Geom_OffsetCurve)) {
myTypeCurve = GeomAbs_OtherCurve;
// Create nested adaptor for base curve
Handle(Geom_Curve) aBase = Handle(Geom_OffsetCurve)::DownCast(myCurve)->BasisCurve();
myOffsetBaseCurveAdaptor = new GeomAdaptor_HCurve(aBase);
}
else {
myTypeCurve = GeomAbs_OtherCurve;
@@ -510,6 +532,17 @@ Standard_Real GeomAdaptor_Curve::Period() const
return myCurve->LastParameter() - myCurve->FirstParameter();
}
//=======================================================================
//function : RebuildCache
//purpose :
//=======================================================================
void GeomAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
{
myCurveCache->BuildCache(theParameter, myBspl->Degree(),
myBspl->IsPeriodic(), myBspl->KnotSequence(),
myBspl->Poles(), myBspl->Weights());
}
//=======================================================================
//function : Value
//purpose :
@@ -517,22 +550,64 @@ Standard_Real GeomAdaptor_Curve::Period() const
gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
{
if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
(U==myFirst || U==myLast) ) {
if (myTypeCurve == GeomAbs_BSplineCurve)
return ValueBSpline(U);
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
return ValueOffset(U);
return myCurve->Value(U);
}
//=======================================================================
//function : ValueBSpline
//purpose :
//=======================================================================
gp_Pnt GeomAdaptor_Curve::ValueBSpline(const Standard_Real theU) const
{
if (theU == myFirst || theU == myLast)
{
Standard_Integer Ideb = 0, Ifin = 0;
if (U==myFirst) {
if (theU == myFirst) {
myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
if (U==myLast) {
if (theU == myLast) {
myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
return myBspl->LocalValue(U, Ideb, Ifin);
return myBspl->LocalValue(theU, Ideb, Ifin);
}
return myCurve->Value(U);
else if (!myCurveCache.IsNull()) // use cached B-spline data
{
if (!myCurveCache->IsCacheValid(theU))
RebuildCache(theU);
gp_Pnt aRes;
myCurveCache->D0(theU, aRes);
return aRes;
}
return myCurve->Value(theU);
}
//=======================================================================
//function : ValueOffset
//purpose :
//=======================================================================
gp_Pnt GeomAdaptor_Curve::ValueOffset(const Standard_Real theU) const
{
gp_Pnt aP;
gp_Vec aV;
myOffsetBaseCurveAdaptor->D1(theU, aP, aV);
Standard_Boolean IsDirectionChange = Standard_False;
if(aV.SquareMagnitude() <= gp::Resolution())
IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 1, theU, aV);
Handle(Geom_OffsetCurve) anOffC = Handle(Geom_OffsetCurve)::DownCast(myCurve);
Standard_Real anOffsetVal = anOffC->Offset();
const gp_Dir& anOffsetDir = anOffC->Direction();
CSLib_Offset::D0(aP, aV, anOffsetDir, anOffsetVal, IsDirectionChange, aP);
return aP;
}
//=======================================================================
@@ -542,24 +617,53 @@ gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
{
if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
(U==myFirst || U==myLast) ) {
if (myTypeCurve == GeomAbs_BSplineCurve)
D0BSpline(U, P);
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
D0Offset(U, P);
else
myCurve->D0(U, P);
}
//=======================================================================
//function : D0BSpline
//purpose :
//=======================================================================
void GeomAdaptor_Curve::D0BSpline(const Standard_Real theU, gp_Pnt& theP) const
{
if (theU == myFirst || theU == myLast)
{
Standard_Integer Ideb = 0, Ifin = 0;
if (U==myFirst) {
if (theU == myFirst) {
myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
if (U==myLast) {
if (theU == myLast) {
myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
myBspl->LocalD0( U, Ideb, Ifin, P);
myBspl->LocalD0(theU, Ideb, Ifin, theP);
return;
}
else {
myCurve->D0(U, P);
}
else if (!myCurveCache.IsNull()) // use cached B-spline data
{
if (!myCurveCache->IsCacheValid(theU))
RebuildCache(theU);
myCurveCache->D0(theU, theP);
return;
}
myCurve->D0(theU, theP);
}
//=======================================================================
//function : D0Offset
//purpose :
//=======================================================================
void GeomAdaptor_Curve::D0Offset(const Standard_Real theU, gp_Pnt& theP) const
{
theP = ValueOffset(theU);
}
//=======================================================================
@@ -569,52 +673,133 @@ void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const
{
if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
(U==myFirst || U==myLast) ) {
if (myTypeCurve == GeomAbs_BSplineCurve)
D1BSpline(U, P, V);
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
D1Offset(U, P, V);
else
myCurve->D1(U, P, V);
}
//=======================================================================
//function : D1BSpline
//purpose :
//=======================================================================
void GeomAdaptor_Curve::D1BSpline(const Standard_Real theU, gp_Pnt& theP, gp_Vec& theV) const
{
if (theU == myFirst || theU == myLast)
{
Standard_Integer Ideb = 0, Ifin = 0;
if (U==myFirst) {
if (theU == myFirst) {
myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
if (U==myLast) {
if (theU == myLast) {
myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
myBspl->LocalD1( U, Ideb, Ifin, P, V);
}
else {
myCurve->D1( U, P, V);
myBspl->LocalD1(theU, Ideb, Ifin, theP, theV);
return;
}
else if (!myCurveCache.IsNull()) // use cached B-spline data
{
if (!myCurveCache->IsCacheValid(theU))
RebuildCache(theU);
myCurveCache->D1(theU, theP, theV);
return;
}
myCurve->D1(theU, theP, theV);
}
//=======================================================================
//function : D1Offset
//purpose :
//=======================================================================
void GeomAdaptor_Curve::D1Offset(const Standard_Real theU, gp_Pnt& theP, gp_Vec& theV) const
{
gp_Vec aV2;
myOffsetBaseCurveAdaptor->D2 (theU, theP, theV, aV2);
Standard_Boolean IsDirectionChange = Standard_False;
if(theV.SquareMagnitude() <= gp::Resolution())
IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 2, theU, theV, aV2);
Handle(Geom_OffsetCurve) anOffC = Handle(Geom_OffsetCurve)::DownCast(myCurve);
Standard_Real anOffsetVal = anOffC->Offset();
const gp_Dir& anOffsetDir = anOffC->Direction();
CSLib_Offset::D1(theP, theV, aV2, anOffsetDir, anOffsetVal, IsDirectionChange, theP, theV);
}
//=======================================================================
//function : D2
//purpose :
//=======================================================================
void GeomAdaptor_Curve::D2(const Standard_Real U,
gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const
gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const
{
if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
(U==myFirst || U==myLast) ) {
if (myTypeCurve == GeomAbs_BSplineCurve)
D2BSpline(U, P, V1, V2);
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
D2Offset(U, P, V1, V2);
else
myCurve->D2(U, P, V1, V2);
}
//=======================================================================
//function : D2BSpline
//purpose :
//=======================================================================
void GeomAdaptor_Curve::D2BSpline(const Standard_Real theU, gp_Pnt& theP,
gp_Vec& theV1, gp_Vec& theV2) const
{
if (theU == myFirst || theU == myLast)
{
Standard_Integer Ideb = 0, Ifin = 0;
if (U==myFirst) {
if (theU == myFirst) {
myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
if (U==myLast) {
if (theU == myLast) {
myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
myBspl->LocalD2( U, Ideb, Ifin, P, V1, V2);
myBspl->LocalD2(theU, Ideb, Ifin, theP, theV1, theV2);
return;
}
else {
myCurve->D2( U, P, V1, V2);
else if (!myCurveCache.IsNull()) // use cached B-spline data
{
if (!myCurveCache->IsCacheValid(theU))
RebuildCache(theU);
myCurveCache->D2(theU, theP, theV1, theV2);
return;
}
myCurve->D2(theU, theP, theV1, theV2);
}
//=======================================================================
//function : D2Offset
//purpose :
//=======================================================================
void GeomAdaptor_Curve::D2Offset(const Standard_Real theU, gp_Pnt& theP,
gp_Vec& theV1, gp_Vec& theV2) const
{
gp_Vec V3;
myOffsetBaseCurveAdaptor->D3 (theU, theP, theV1, theV2, V3);
Standard_Boolean IsDirectionChange = Standard_False;
if(theV1.SquareMagnitude() <= gp::Resolution())
IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 3, theU, theV1, theV2, V3);
Handle(Geom_OffsetCurve) anOffC = Handle(Geom_OffsetCurve)::DownCast(myCurve);
Standard_Real anOffsetVal = anOffC->Offset();
const gp_Dir& anOffsetDir = anOffC->Direction();
CSLib_Offset::D2(theP, theV1, theV2, V3, anOffsetDir, anOffsetVal, IsDirectionChange, theP, theV1, theV2);
}
//=======================================================================
@@ -623,27 +808,71 @@ void GeomAdaptor_Curve::D2(const Standard_Real U,
//=======================================================================
void GeomAdaptor_Curve::D3(const Standard_Real U,
gp_Pnt& P, gp_Vec& V1,
gp_Vec& V2, gp_Vec& V3) const
gp_Pnt& P, gp_Vec& V1,
gp_Vec& V2, gp_Vec& V3) const
{
if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
(U==myFirst || U==myLast) ) {
if (myTypeCurve == GeomAbs_BSplineCurve)
D3BSpline(U, P, V1, V2, V3);
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
D3Offset(U, P, V1, V2, V3);
else
myCurve->D3(U, P, V1, V2, V3);
}
//=======================================================================
//function : D3BSpline
//purpose :
//=======================================================================
void GeomAdaptor_Curve::D3BSpline(const Standard_Real theU,
gp_Pnt& theP, gp_Vec& theV1,
gp_Vec& theV2, gp_Vec& theV3) const
{
if (theU == myFirst || theU == myLast)
{
Standard_Integer Ideb = 0, Ifin = 0;
if (U==myFirst) {
if (theU == myFirst) {
myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
if (U==myLast) {
if (theU == myLast) {
myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
myBspl->LocalD3( U, Ideb, Ifin, P, V1, V2, V3);
myBspl->LocalD3(theU, Ideb, Ifin, theP, theV1, theV2, theV3);
return;
}
else {
myCurve->D3( U, P, V1, V2, V3);
else if (!myCurveCache.IsNull()) // use cached B-spline data
{
if (!myCurveCache->IsCacheValid(theU))
RebuildCache(theU);
myCurveCache->D3(theU, theP, theV1, theV2, theV3);
return;
}
myCurve->D3(theU, theP, theV1, theV2, theV3);
}
//=======================================================================
//function : D3Offset
//purpose :
//=======================================================================
void GeomAdaptor_Curve::D3Offset(const Standard_Real theU,
gp_Pnt& theP, gp_Vec& theV1,
gp_Vec& theV2, gp_Vec& theV3) const
{
myOffsetBaseCurveAdaptor->D3 (theU, theP, theV1, theV2, theV3);
gp_Vec V4 = myOffsetBaseCurveAdaptor->DN(theU, 4);
Standard_Boolean IsDirectionChange = Standard_False;
if(theV1.SquareMagnitude() <= gp::Resolution())
IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 4, theU, theV1, theV2, theV3, V4);
Handle(Geom_OffsetCurve) anOffC = Handle(Geom_OffsetCurve)::DownCast(myCurve);
Standard_Real anOffsetVal = anOffC->Offset();
const gp_Dir& anOffsetDir = anOffC->Direction();
CSLib_Offset::D3(theP, theV1, theV2, theV3, V4, anOffsetDir, anOffsetVal, IsDirectionChange,
theP, theV1, theV2, theV3);
}
//=======================================================================
@@ -652,10 +881,21 @@ void GeomAdaptor_Curve::D3(const Standard_Real U,
//=======================================================================
gp_Vec GeomAdaptor_Curve::DN(const Standard_Real U,
const Standard_Integer N) const
const Standard_Integer N) const
{
if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
(U==myFirst || U==myLast) ) {
if (myTypeCurve == GeomAbs_BSplineCurve)
return DNBSpline(U, N);
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
return DNOffset(U, N);
return myCurve->DN(U, N);
}
gp_Vec GeomAdaptor_Curve::DNBSpline(const Standard_Real U,
const Standard_Integer N) const
{
if ((U==myFirst || U==myLast))
{
Standard_Integer Ideb = 0, Ifin = 0;
if (U==myFirst) {
myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
@@ -668,10 +908,31 @@ gp_Vec GeomAdaptor_Curve::DN(const Standard_Real U,
if (Ideb>=Ifin) Ideb = Ifin-1;
}
return myBspl->LocalDN( U, Ideb, Ifin, N);
}
else {
return myCurve->DN( U, N);
}
return myCurve->DN( U, N);
}
gp_Vec GeomAdaptor_Curve::DNOffset(const Standard_Real U,
const Standard_Integer N) const
{
gp_Pnt aPnt;
gp_Vec aVec, aVN;
switch (N)
{
case 1:
D1Offset(U, aPnt, aVN);
break;
case 2:
D2Offset(U, aPnt, aVec, aVN);
break;
case 3:
D3Offset(U, aPnt, aVec, aVec, aVN);
break;
default:
aVN = myCurve->DN(U, N);
}
return aVN;
}
//=======================================================================
@@ -857,3 +1118,56 @@ Handle(Geom_BSplineCurve) GeomAdaptor_Curve::BSpline() const
return *((Handle(Geom_BSplineCurve)*)&myCurve);
}
// ============= Auxiliary functions ===================
Standard_Boolean AdjustDerivative(const Handle(Adaptor3d_HCurve)& theAdaptor, Standard_Integer theMaxDerivative,
Standard_Real theU, gp_Vec& theD1, gp_Vec& theD2,
gp_Vec& theD3, gp_Vec& theD4)
{
static const Standard_Real aTol = gp::Resolution();
Standard_Boolean IsDirectionChange = Standard_False;
const Standard_Real anUinfium = theAdaptor->FirstParameter();
const Standard_Real anUsupremum = theAdaptor->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
gp_Vec V;
do
{
V = theAdaptor->DN(theU, ++anIndex);
}
while((V.SquareMagnitude() <= aTol) && anIndex < maxDerivOrder);
Standard_Real u;
if(theU-anUinfium < aDelta)
u = theU+aDelta;
else
u = theU-aDelta;
gp_Pnt P1, P2;
theAdaptor->D0(Min(theU, u), P1);
theAdaptor->D0(Max(theU, u), P2);
gp_Vec V1(P1, P2);
IsDirectionChange = V.Dot(V1) < 0.0;
Standard_Real aSign = IsDirectionChange ? -1.0 : 1.0;
theD1 = V * aSign;
gp_Vec* aDeriv[3] = {&theD2, &theD3, &theD4};
for (Standard_Integer i = 1; i < theMaxDerivative; i++)
*(aDeriv[i-1]) = theAdaptor->DN(theU, anIndex + i) * aSign;
return IsDirectionChange;
}

View File

@@ -38,7 +38,8 @@ uses
Shape from GeomAbs,
Curve from GeomAdaptor,
HCurve from Adaptor3d,
HSurface from Adaptor3d
HSurface from Adaptor3d,
Cache from BSplSLib
raises
NoSuchObject from Standard,
@@ -386,6 +387,12 @@ is
TolV : Real = 0.0)
is private;
RebuildCache(me; theU, theV : Real)
---Purpose: Rebuilds B-spline cache
-- \param theU first parameter to identify the span for caching
-- \param theV second parameter to identify the span for caching
is static private;
fields
mySurface : Surface from Geom;
@@ -395,5 +402,6 @@ fields
myVFirst : Real from Standard;
myVLast : Real from Standard;
myTolU, myTolV : Real from Standard;
mySurfaceCache : Cache from BSplSLib;
end Surface;

View File

@@ -51,6 +51,7 @@
#include <gp_Lin.hxx>
#include <gp_Trsf.hxx>
#include <BSplCLib.hxx>
#include <BSplSLib_Cache.hxx>
#include <Precision.hxx>
#include <Standard_NoSuchObject.hxx>
#include <Standard_NullObject.hxx>
@@ -131,7 +132,7 @@ void GeomAdaptor_Surface::load(const Handle(Geom_Surface)& S,
mySurfaceType = GeomAbs_BezierSurface;
else if (TheType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
Load((*((Handle(Geom_RectangularTrimmedSurface)*)&S))->BasisSurface(),
UFirst,ULast,VFirst,VLast);
UFirst,ULast,VFirst,VLast);
}
else if ( TheType == STANDARD_TYPE(Geom_Plane))
mySurfaceType = GeomAbs_Plane;
@@ -149,7 +150,12 @@ void GeomAdaptor_Surface::load(const Handle(Geom_Surface)& S,
mySurfaceType = GeomAbs_SurfaceOfExtrusion;
else if ( TheType == STANDARD_TYPE(Geom_BSplineSurface)) {
mySurfaceType = GeomAbs_BSplineSurface;
myBspl = *((Handle(Geom_BSplineSurface)*)&S);
myBspl = *((Handle(Geom_BSplineSurface)*)&mySurface);
// Create cache for B-spline
mySurfaceCache = new BSplSLib_Cache(
myBspl->UDegree(), myBspl->IsUPeriodic(), myBspl->UKnotSequence(),
myBspl->VDegree(), myBspl->IsVPeriodic(), myBspl->VKnotSequence(),
myBspl->Poles(), myBspl->Weights());
}
else if ( TheType == STANDARD_TYPE(Geom_OffsetSurface))
mySurfaceType = GeomAbs_OffsetSurface;
@@ -599,6 +605,19 @@ Standard_Real GeomAdaptor_Surface::VPeriod() const
return mySurface->VPeriod();
}
//=======================================================================
//function : RebuildCache
//purpose :
//=======================================================================
void GeomAdaptor_Surface::RebuildCache(const Standard_Real theU,
const Standard_Real theV) const
{
mySurfaceCache->BuildCache(theU, theV,
myBspl->UDegree(), myBspl->IsUPeriodic(), myBspl->UKnotSequence(),
myBspl->VDegree(), myBspl->IsVPeriodic(), myBspl->VKnotSequence(),
myBspl->Poles(), myBspl->Weights());
}
//=======================================================================
//function : Value
//purpose :
@@ -607,6 +626,15 @@ Standard_Real GeomAdaptor_Surface::VPeriod() const
gp_Pnt GeomAdaptor_Surface::Value(const Standard_Real U,
const Standard_Real V) const
{
if (mySurfaceType == GeomAbs_BSplineSurface && !mySurfaceCache.IsNull())
{
if (!mySurfaceCache->IsCacheValid(U, V))
RebuildCache(U, V);
gp_Pnt P;
mySurfaceCache->D0(U, V, P);
return P;
}
return mySurface->Value(U,V);
}
@@ -618,6 +646,14 @@ gp_Pnt GeomAdaptor_Surface::Value(const Standard_Real U,
void GeomAdaptor_Surface::D0(const Standard_Real U,
const Standard_Real V, gp_Pnt& P) const
{
if (mySurfaceType == GeomAbs_BSplineSurface && !mySurfaceCache.IsNull())
{
if (!mySurfaceCache->IsCacheValid(U, V))
RebuildCache(U, V);
mySurfaceCache->D0(U, V, P);
return;
}
mySurface->D0(U,V,P);
}
@@ -629,11 +665,11 @@ void GeomAdaptor_Surface::D0(const Standard_Real U,
void GeomAdaptor_Surface::D1(const Standard_Real U,
const Standard_Real V,
gp_Pnt& P,
gp_Vec& D1U,
gp_Vec& D1V ) const
gp_Pnt& P,
gp_Vec& D1U,
gp_Vec& D1V ) const
{
Standard_Integer Ideb,Ifin,IVdeb,IVfin,USide=0,VSide=0;
Standard_Integer Ideb, Ifin, IVdeb, IVfin, USide=0, VSide=0;
Standard_Real u = U, v = V;
if (Abs(U-myUFirst) <= myTolU) {USide= 1; u = myUFirst;}
else if (Abs(U-myULast) <= myTolU) {USide= -1; u = myULast;}
@@ -641,39 +677,42 @@ void GeomAdaptor_Surface::D1(const Standard_Real U,
else if (Abs(V-myVLast) <= myTolV) {VSide= -1; v = myVLast;}
switch(mySurfaceType) {
case GeomAbs_BSplineSurface:
{
if((USide==0)&&(VSide==0)){
myBspl->D1(u,v,P,D1U,D1V);
}
else {
if(IfUVBound(u,v,Ideb,Ifin,IVdeb,IVfin,USide,VSide))
myBspl->LocalD1 (u, v, Ideb, Ifin,IVdeb ,IVfin ,P ,D1U,D1V);
else myBspl->D1(u,v,P,D1U,D1V);
}
break;
case GeomAbs_BSplineSurface:
if ((USide != 0 || VSide != 0) &&
IfUVBound(u, v, Ideb, Ifin, IVdeb, IVfin, USide, VSide))
myBspl->LocalD1(u, v, Ideb, Ifin, IVdeb, IVfin, P, D1U, D1V);
else if (!mySurfaceCache.IsNull())
{
if (!mySurfaceCache->IsCacheValid(U, V))
RebuildCache(U, V);
mySurfaceCache->D1(U, V, P, D1U, D1V);
}
case GeomAbs_SurfaceOfExtrusion :
if(USide==0) myExtSurf->D1(u,v,P,D1U,D1V);
else myExtSurf->LocalD1(u,v,USide,P,D1U,D1V);
break;
case GeomAbs_SurfaceOfRevolution :
if(VSide==0) myRevSurf->D1 (u, v, P,D1U,D1V );
else myRevSurf->LocalD1 (u, v, VSide, P,D1U,D1V );
break;
case GeomAbs_OffsetSurface :
{
if((USide==0)&&(VSide==0)) myOffSurf->D1 (u, v,P,D1U,D1V );
else myOffSurf->LocalD1 (u, v, USide, VSide ,P,D1U,D1V );
break;
}
default :
mySurface->D1(u,v,P,D1U,D1V);
else
myBspl->D1(u, v, P, D1U, D1V);
break;
case GeomAbs_SurfaceOfExtrusion:
if (USide==0)
myExtSurf->D1(u, v, P, D1U, D1V);
else
myExtSurf->LocalD1(u, v, USide, P, D1U, D1V);
break;
case GeomAbs_SurfaceOfRevolution:
if (VSide==0)
myRevSurf->D1(u, v, P, D1U, D1V);
else
myRevSurf->LocalD1(u, v, VSide, P, D1U, D1V);
break;
case GeomAbs_OffsetSurface:
if (USide==0 && VSide==0)
myOffSurf->D1(u, v, P, D1U, D1V);
else
myOffSurf->LocalD1(u, v, USide, VSide, P, D1U, D1V);
break;
default:
mySurface->D1(u, v, P, D1U, D1V);
}
}
@@ -683,50 +722,56 @@ void GeomAdaptor_Surface::D1(const Standard_Real U,
//=======================================================================
void GeomAdaptor_Surface::D2(const Standard_Real U,
const Standard_Real V, gp_Pnt& P,
gp_Vec& D1U, gp_Vec& D1V, gp_Vec& D2U,
gp_Vec& D2V, gp_Vec& D2UV) const
const Standard_Real V,
gp_Pnt& P,
gp_Vec& D1U,
gp_Vec& D1V,
gp_Vec& D2U,
gp_Vec& D2V,
gp_Vec& D2UV) const
{
Standard_Integer Ideb,Ifin,IVdeb,IVfin,USide=0,VSide=0;
Standard_Integer Ideb, Ifin, IVdeb, IVfin, USide=0, VSide=0;
Standard_Real u = U, v = V;
if (Abs(U-myUFirst) <= myTolU) {USide= 1; u = myUFirst;}
else if (Abs(U-myULast) <= myTolU) {USide= -1; u = myULast;}
if (Abs(V-myVFirst) <= myTolV) {VSide= 1; v = myVFirst;}
else if (Abs(V-myVLast) <= myTolV) {VSide= -1; v = myVLast;}
switch(mySurfaceType)
switch(mySurfaceType) {
case GeomAbs_BSplineSurface:
if((USide != 0 || VSide != 0) &&
IfUVBound(u, v, Ideb, Ifin, IVdeb, IVfin, USide, VSide))
myBspl->LocalD2(u, v, Ideb, Ifin, IVdeb, IVfin, P, D1U, D1V, D2U, D2V, D2UV);
else if (!mySurfaceCache.IsNull())
{
case GeomAbs_BSplineSurface:
if((USide==0)&&(VSide==0)) myBspl->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
else{
if(IfUVBound(u,v,Ideb,Ifin,IVdeb,IVfin,USide,VSide))
myBspl->LocalD2 (u, v, Ideb, Ifin,IVdeb ,IVfin ,P ,D1U,D1V,D2U,D2V,D2UV);
else myBspl->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
}
break;
case GeomAbs_SurfaceOfExtrusion :
if(USide==0) myExtSurf->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
else myExtSurf->LocalD2(u,v,USide,P,D1U,D1V,D2U,D2V,D2UV);
break;
case GeomAbs_SurfaceOfRevolution :
if(VSide==0) myRevSurf->D2 (u, v, P,D1U,D1V,D2U,D2V,D2UV );
else myRevSurf->LocalD2 (u, v, VSide, P,D1U,D1V,D2U,D2V,D2UV );
break;
case GeomAbs_OffsetSurface :
{
if((USide==0)&&(VSide==0)) myOffSurf->D2 (u, v,P,D1U,D1V,D2U,D2V,D2UV );
else myOffSurf->LocalD2 (u, v, USide, VSide ,P,D1U,D1V,D2U,D2V,D2UV );
break;
}
default : { mySurface->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
break;}
if (!mySurfaceCache->IsCacheValid(U, V))
RebuildCache(U, V);
mySurfaceCache->D2(U, V, P, D1U, D1V, D2U, D2V, D2UV);
}
else myBspl->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
break;
case GeomAbs_SurfaceOfExtrusion :
if(USide==0) myExtSurf->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
else myExtSurf->LocalD2(u,v,USide,P,D1U,D1V,D2U,D2V,D2UV);
break;
case GeomAbs_SurfaceOfRevolution :
if(VSide==0) myRevSurf->D2 (u, v, P,D1U,D1V,D2U,D2V,D2UV );
else myRevSurf->LocalD2 (u, v, VSide, P,D1U,D1V,D2U,D2V,D2UV );
break;
case GeomAbs_OffsetSurface :
{
if((USide==0)&&(VSide==0)) myOffSurf->D2 (u, v,P,D1U,D1V,D2U,D2V,D2UV );
else myOffSurf->LocalD2 (u, v, USide, VSide ,P,D1U,D1V,D2U,D2V,D2UV );
break;
}
default : { mySurface->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
break;}
}
}