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:
@@ -26,6 +26,7 @@
|
||||
#include <Geom2dAdaptor_HCurve.hxx>
|
||||
#include <Adaptor2d_HCurve2d.hxx>
|
||||
#include <BSplCLib.hxx>
|
||||
#include <BSplCLib_Cache.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <TColgp_Array1OfPnt2d.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
@@ -42,6 +43,9 @@
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2d_Parabola.hxx>
|
||||
#include <Geom2d_Hyperbola.hxx>
|
||||
#include <Geom2d_UndefinedValue.hxx>
|
||||
#include <Geom2d_UndefinedDerivative.hxx>
|
||||
#include <CSLib_Offset.hxx>
|
||||
//#include <Geom2dConvert_BSplineCurveKnotSplitting.hxx>
|
||||
|
||||
#include <Standard_OutOfRange.hxx>
|
||||
@@ -52,6 +56,17 @@
|
||||
#define myBspl (*((Handle(Geom2d_BSplineCurve)*)&myCurve))
|
||||
#define PosTol Precision::PConfusion()/2
|
||||
|
||||
static const int maxDerivOrder = 3;
|
||||
static const Standard_Real MinStep = 1e-7;
|
||||
|
||||
static gp_Vec2d dummyDerivative; // used as empty value for unused derivatives in AdjustDerivative
|
||||
|
||||
// Recalculate derivatives in the singular point
|
||||
// Returns true is the direction of derivatives is changed
|
||||
static Standard_Boolean AdjustDerivative(const Handle(Adaptor2d_HCurve2d)& theAdaptor, Standard_Integer theMaxDerivative,
|
||||
Standard_Real theU, gp_Vec2d& theD1, gp_Vec2d& theD2 = dummyDerivative,
|
||||
gp_Vec2d& theD3 = dummyDerivative, gp_Vec2d& theD4 = dummyDerivative);
|
||||
|
||||
//=======================================================================
|
||||
//function : LocalContinuity
|
||||
//purpose : Computes the Continuity of a BSplineCurve
|
||||
@@ -197,6 +212,16 @@ void Geom2dAdaptor_Curve::load(const Handle(Geom2d_Curve)& C,
|
||||
}
|
||||
else if ( TheType == STANDARD_TYPE(Geom2d_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(Geom2d_OffsetCurve))
|
||||
{
|
||||
myTypeCurve = GeomAbs_OtherCurve;
|
||||
// Create nested adaptor for base curve
|
||||
Handle(Geom2d_Curve) aBase = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->BasisCurve();
|
||||
myOffsetBaseCurveAdaptor = new Geom2dAdaptor_HCurve(aBase);
|
||||
}
|
||||
else {
|
||||
myTypeCurve = GeomAbs_OtherCurve;
|
||||
@@ -218,7 +243,7 @@ GeomAbs_Shape Geom2dAdaptor_Curve::Continuity() const
|
||||
if (myTypeCurve == GeomAbs_BSplineCurve) {
|
||||
return LocalContinuity(myFirst, myLast);
|
||||
}
|
||||
else if (myCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))){
|
||||
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)){
|
||||
GeomAbs_Shape S =
|
||||
(*((Handle(Geom2d_OffsetCurve)*)&myCurve))->GetBasisCurveContinuity();
|
||||
switch(S){
|
||||
@@ -330,7 +355,7 @@ Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (myCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))){
|
||||
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)){
|
||||
GeomAbs_Shape BaseS=GeomAbs_C0;
|
||||
switch(S){
|
||||
case GeomAbs_G1:
|
||||
@@ -342,9 +367,7 @@ Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
|
||||
case GeomAbs_C2: BaseS = GeomAbs_C3; break;
|
||||
default: BaseS = GeomAbs_CN;
|
||||
}
|
||||
Geom2dAdaptor_Curve C
|
||||
((*((Handle(Geom2d_OffsetCurve)*)&myCurve))->BasisCurve());
|
||||
myNbIntervals = C.NbIntervals(BaseS);
|
||||
myNbIntervals = myOffsetBaseCurveAdaptor->NbIntervals(BaseS);
|
||||
}
|
||||
|
||||
return myNbIntervals;
|
||||
@@ -447,7 +470,7 @@ void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (myCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))){
|
||||
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)){
|
||||
GeomAbs_Shape BaseS=GeomAbs_C0;
|
||||
switch(S){
|
||||
case GeomAbs_G1:
|
||||
@@ -459,10 +482,8 @@ void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
|
||||
case GeomAbs_C2: BaseS = GeomAbs_C3; break;
|
||||
default: BaseS = GeomAbs_CN;
|
||||
}
|
||||
Geom2dAdaptor_Curve C
|
||||
((*((Handle(Geom2d_OffsetCurve)*)&myCurve))->BasisCurve());
|
||||
myNbIntervals = C.NbIntervals(BaseS);
|
||||
C.Intervals(T, BaseS);
|
||||
myNbIntervals = myOffsetBaseCurveAdaptor->NbIntervals(BaseS);
|
||||
myOffsetBaseCurveAdaptor->Intervals(T, BaseS);
|
||||
}
|
||||
|
||||
T( T.Lower() ) = myFirst;
|
||||
@@ -525,6 +546,17 @@ Standard_Real Geom2dAdaptor_Curve::Period() const
|
||||
return myCurve->LastParameter() - myCurve->FirstParameter();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : RebuildCache
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void Geom2dAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
|
||||
{
|
||||
myCurveCache->BuildCache(theParameter, myBspl->Degree(),
|
||||
myBspl->IsPeriodic(), myBspl->KnotSequence(),
|
||||
myBspl->Poles(), myBspl->Weights());
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Value
|
||||
//purpose :
|
||||
@@ -532,24 +564,65 @@ Standard_Real Geom2dAdaptor_Curve::Period() const
|
||||
|
||||
gp_Pnt2d Geom2dAdaptor_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(Geom2d_OffsetCurve))
|
||||
return ValueOffset(U);
|
||||
|
||||
return myCurve->Value(U);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ValueBSpline
|
||||
//purpose : Computes the point of parameter U on the B-spline curve
|
||||
//=======================================================================
|
||||
gp_Pnt2d Geom2dAdaptor_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);
|
||||
}
|
||||
else {
|
||||
return myCurve->Value( U);
|
||||
else if (!myCurveCache.IsNull()) // use cached B-spline data
|
||||
{
|
||||
if (!myCurveCache->IsCacheValid(theU))
|
||||
RebuildCache(theU);
|
||||
gp_Pnt2d aRes;
|
||||
myCurveCache->D0(theU, aRes);
|
||||
return aRes;
|
||||
}
|
||||
return myCurve->Value(theU);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ValueOffset
|
||||
//purpose : Computes the point of parameter U on the offset curve
|
||||
//=======================================================================
|
||||
gp_Pnt2d Geom2dAdaptor_Curve::ValueOffset(const Standard_Real theU) const
|
||||
{
|
||||
gp_Pnt2d aP;
|
||||
gp_Vec2d aD1;
|
||||
myOffsetBaseCurveAdaptor->D1(theU, aP, aD1);
|
||||
Standard_Boolean isDirectionChange = Standard_False;
|
||||
const Standard_Real aTol = gp::Resolution();
|
||||
if(aD1.SquareMagnitude() <= aTol)
|
||||
isDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 1, theU, aD1);
|
||||
|
||||
Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
|
||||
CSLib_Offset::D0(aP, aD1, anOffset, isDirectionChange, aP);
|
||||
return aP;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -559,24 +632,59 @@ gp_Pnt2d Geom2dAdaptor_Curve::Value(const Standard_Real U) const
|
||||
|
||||
void Geom2dAdaptor_Curve::D0(const Standard_Real U, gp_Pnt2d& P) const
|
||||
{
|
||||
if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
|
||||
(U==myFirst || U==myLast) ) {
|
||||
if (myTypeCurve == GeomAbs_BSplineCurve)
|
||||
{
|
||||
D0BSpline(U, P);
|
||||
return;
|
||||
}
|
||||
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
|
||||
{
|
||||
D0Offset(U, P);
|
||||
return;
|
||||
}
|
||||
|
||||
myCurve->D0(U, P);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : D0BSpline
|
||||
//purpose : Computes the point of parameter theU on the B-spline curve
|
||||
//=======================================================================
|
||||
void Geom2dAdaptor_Curve::D0BSpline(const Standard_Real theU, gp_Pnt2d& 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 : Computes the point of parameter theU on the offset curve
|
||||
//=======================================================================
|
||||
void Geom2dAdaptor_Curve::D0Offset(const Standard_Real theU, gp_Pnt2d& theP) const
|
||||
{
|
||||
theP = ValueOffset(theU);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -584,27 +692,75 @@ void Geom2dAdaptor_Curve::D0(const Standard_Real U, gp_Pnt2d& P) const
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void Geom2dAdaptor_Curve::D1(const Standard_Real U,
|
||||
gp_Pnt2d& P, gp_Vec2d& V) const
|
||||
void Geom2dAdaptor_Curve::D1(const Standard_Real U,
|
||||
gp_Pnt2d& P, gp_Vec2d& V) const
|
||||
{
|
||||
if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
|
||||
(U==myFirst || U==myLast) ) {
|
||||
if (myTypeCurve == GeomAbs_BSplineCurve)
|
||||
{
|
||||
D1BSpline(U, P, V);
|
||||
return;
|
||||
}
|
||||
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
|
||||
{
|
||||
D1Offset(U, P, V);
|
||||
return;
|
||||
}
|
||||
|
||||
myCurve->D1(U, P, V);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : D1BSpline
|
||||
//purpose : Computes the point of parameter theU on the B-spline curve and its derivative
|
||||
//=======================================================================
|
||||
void Geom2dAdaptor_Curve::D1BSpline(const Standard_Real theU, gp_Pnt2d& theP, gp_Vec2d& 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 : Computes the point of parameter theU on the offset curve and its derivative
|
||||
//=======================================================================
|
||||
void Geom2dAdaptor_Curve::D1Offset(const Standard_Real theU, gp_Pnt2d& theP, gp_Vec2d& theV) 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))
|
||||
|
||||
gp_Vec2d V2;
|
||||
myOffsetBaseCurveAdaptor->D2 (theU, theP, theV, V2);
|
||||
|
||||
Standard_Boolean IsDirectionChange = Standard_False;
|
||||
if(theV.SquareMagnitude() <= gp::Resolution())
|
||||
IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 2, theU, theV, V2);
|
||||
|
||||
Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
|
||||
CSLib_Offset::D1(theP, theV, V2, anOffset, IsDirectionChange, theP, theV);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -613,26 +769,78 @@ void Geom2dAdaptor_Curve::D1(const Standard_Real U,
|
||||
//=======================================================================
|
||||
|
||||
void Geom2dAdaptor_Curve::D2(const Standard_Real U,
|
||||
gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
|
||||
gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
|
||||
{
|
||||
if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
|
||||
(U==myFirst || U==myLast) ) {
|
||||
if (myTypeCurve == GeomAbs_BSplineCurve)
|
||||
{
|
||||
D2BSpline(U, P, V1, V2);
|
||||
return;
|
||||
}
|
||||
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
|
||||
{
|
||||
D2Offset(U, P, V1, V2);
|
||||
return;
|
||||
}
|
||||
|
||||
myCurve->D2(U, P, V1, V2);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : D2BSpline
|
||||
//purpose : Computes the point of parameter theU on the B-spline curve and its first and second derivatives
|
||||
//=======================================================================
|
||||
void Geom2dAdaptor_Curve::D2BSpline(const Standard_Real theU, gp_Pnt2d& theP,
|
||||
gp_Vec2d& theV1, gp_Vec2d& 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 : Computes the point of parameter theU on the offset curve and its first and second derivatives
|
||||
//=======================================================================
|
||||
void Geom2dAdaptor_Curve::D2Offset(const Standard_Real theU, gp_Pnt2d& theP,
|
||||
gp_Vec2d& theV1, gp_Vec2d& theV2) 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))
|
||||
|
||||
// P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
|
||||
// Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
|
||||
|
||||
gp_Vec2d 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);
|
||||
|
||||
Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
|
||||
CSLib_Offset::D2(theP, theV1, theV2, V3, anOffset, IsDirectionChange, theP, theV1, theV2);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -641,27 +849,86 @@ void Geom2dAdaptor_Curve::D2(const Standard_Real U,
|
||||
//=======================================================================
|
||||
|
||||
void Geom2dAdaptor_Curve::D3(const Standard_Real U,
|
||||
gp_Pnt2d& P, gp_Vec2d& V1,
|
||||
gp_Vec2d& V2, gp_Vec2d& V3) const
|
||||
gp_Pnt2d& P, gp_Vec2d& V1,
|
||||
gp_Vec2d& V2, gp_Vec2d& V3) const
|
||||
{
|
||||
if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
|
||||
(U==myFirst || U==myLast) ) {
|
||||
if (myTypeCurve == GeomAbs_BSplineCurve)
|
||||
{
|
||||
D3BSpline(U, P, V1, V2, V3);
|
||||
return;
|
||||
}
|
||||
else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
|
||||
{
|
||||
D3Offset(U, P, V1, V2, V3);
|
||||
return;
|
||||
}
|
||||
|
||||
myCurve->D3(U, P, V1, V2, V3);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : D3BSpline
|
||||
//purpose : Computes the point of parameter theU on the B-spline curve and its 1st - 3rd derivatives
|
||||
//=======================================================================
|
||||
void Geom2dAdaptor_Curve::D3BSpline(const Standard_Real theU, gp_Pnt2d& theP,
|
||||
gp_Vec2d& theV1, gp_Vec2d& theV2, gp_Vec2d& 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 : Computes the point of parameter theU on the offset curve and its 1st - 3rd derivatives
|
||||
//=======================================================================
|
||||
void Geom2dAdaptor_Curve::D3Offset(const Standard_Real theU, gp_Pnt2d& theP,
|
||||
gp_Vec2d& theV1, gp_Vec2d& theV2, gp_Vec2d& theV3) 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))
|
||||
|
||||
// P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
|
||||
// Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
|
||||
|
||||
//P"'(u) = p"'(u) + (Offset / R) * (D3Ndir - (3.0 * Dr/R**2 ) * D2Ndir -
|
||||
// (3.0 * D2r / R2) * DNdir) + (3.0 * Dr * Dr / R4) * DNdir -
|
||||
// (D3r/R2) * Ndir + (6.0 * Dr * Dr / R4) * Ndir +
|
||||
// (6.0 * Dr * D2r / R4) * Ndir - (15.0 * Dr* Dr* Dr /R6) * Ndir
|
||||
|
||||
Standard_Boolean IsDirectionChange = Standard_False;
|
||||
|
||||
myOffsetBaseCurveAdaptor->D3 (theU, theP, theV1, theV2, theV3);
|
||||
gp_Vec2d V4 = myOffsetBaseCurveAdaptor->DN (theU, 4);
|
||||
|
||||
if(theV1.SquareMagnitude() <= gp::Resolution())
|
||||
IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 4, theU, theV1, theV2, theV3, V4);
|
||||
|
||||
Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
|
||||
CSLib_Offset::D3(theP, theV1, theV2, theV3, V4, anOffset, IsDirectionChange,
|
||||
theP, theV1, theV2, theV3);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -670,10 +937,21 @@ void Geom2dAdaptor_Curve::D3(const Standard_Real U,
|
||||
//=======================================================================
|
||||
|
||||
gp_Vec2d Geom2dAdaptor_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(Geom2d_OffsetCurve))
|
||||
return DNOffset(U, N);
|
||||
|
||||
return myCurve->DN(U, N);
|
||||
}
|
||||
|
||||
gp_Vec2d Geom2dAdaptor_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);
|
||||
@@ -686,10 +964,32 @@ gp_Vec2d Geom2dAdaptor_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_Vec2d Geom2dAdaptor_Curve::DNOffset(const Standard_Real U,
|
||||
const Standard_Integer N) const
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d 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;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -906,3 +1206,57 @@ Standard_Integer Geom2dAdaptor_Curve::NbSamples() const
|
||||
{
|
||||
return nbPoints(myCurve);
|
||||
}
|
||||
|
||||
|
||||
// ============= Auxiliary functions ===================
|
||||
Standard_Boolean AdjustDerivative(const Handle(Adaptor2d_HCurve2d)& theAdaptor, 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 = 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_Vec2d V;
|
||||
|
||||
do
|
||||
{
|
||||
V = theAdaptor->DN(theU, ++anIndex);
|
||||
}
|
||||
while((V.Magnitude() <= aTol) && anIndex < maxDerivOrder);
|
||||
|
||||
Standard_Real u;
|
||||
|
||||
if(theU-anUinfium < aDelta)
|
||||
u = theU+aDelta;
|
||||
else
|
||||
u = theU-aDelta;
|
||||
|
||||
gp_Pnt2d P1, P2;
|
||||
theAdaptor->D0(Min(theU, u),P1);
|
||||
theAdaptor->D0(Max(theU, u),P2);
|
||||
|
||||
gp_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]) = theAdaptor->DN(theU, anIndex + i) * aSign;
|
||||
|
||||
return IsDirectionChange;
|
||||
}
|
||||
|
Reference in New Issue
Block a user