#define No_Standard_RangeError
#define No_Standard_OutOfRange
-#include <Geom2dAdaptor_Curve.ixx>
-#include <Geom2d_OffsetCurve.hxx>
-#include <Geom2dAdaptor_HCurve.hxx>
+
#include <Adaptor2d_HCurve2d.hxx>
#include <BSplCLib.hxx>
-#include <GeomAbs_Shape.hxx>
-#include <TColgp_Array1OfPnt2d.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TColStd_Array1OfInteger.hxx>
-#include <TColStd_HArray1OfInteger.hxx>
-#include <Precision.hxx>
-#include <gp.hxx>
-#include <Geom2d_TrimmedCurve.hxx>
-#include <Geom2d_Circle.hxx>
-#include <Geom2d_Line.hxx>
-#include <Geom2d_TrimmedCurve.hxx>
+#include <BSplCLib_Cache.hxx>
+#include <CSLib_Offset.hxx>
#include <Geom2d_BezierCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
+#include <Geom2d_Circle.hxx>
+#include <Geom2d_Curve.hxx>
#include <Geom2d_Ellipse.hxx>
-#include <Geom2d_Parabola.hxx>
#include <Geom2d_Hyperbola.hxx>
-//#include <Geom2dConvert_BSplineCurveKnotSplitting.hxx>
-
-#include <Standard_OutOfRange.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2d_OffsetCurve.hxx>
+#include <Geom2d_Parabola.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
+#include <Geom2d_UndefinedDerivative.hxx>
+#include <Geom2d_UndefinedValue.hxx>
+#include <Geom2dAdaptor_Curve.hxx>
+#include <Geom2dAdaptor_HCurve.hxx>
+#include <GeomAbs_Shape.hxx>
+#include <gp.hxx>
+#include <gp_Circ2d.hxx>
+#include <gp_Elips2d.hxx>
+#include <gp_Hypr2d.hxx>
+#include <gp_Lin2d.hxx>
+#include <gp_Parab2d.hxx>
+#include <gp_Pnt2d.hxx>
+#include <gp_Vec2d.hxx>
+#include <Precision.hxx>
+#include <Standard_ConstructionError.hxx>
+#include <Standard_DomainError.hxx>
#include <Standard_NoSuchObject.hxx>
-#include <Standard_NullObject.hxx>
#include <Standard_NotImplemented.hxx>
+#include <Standard_NullObject.hxx>
+#include <Standard_OutOfRange.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_HArray1OfInteger.hxx>
-#define myBspl (*((Handle(Geom2d_BSplineCurve)*)&myCurve))
-#define PosTol Precision::PConfusion()/2
+//#include <Geom2dConvert_BSplineCurveKnotSplitting.hxx>
+static const Standard_Real PosTol = Precision::PConfusion() / 2;
+
+static const Standard_Integer 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
const {
Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
- Standard_Integer Nb = myBspl->NbKnots();
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
+ Standard_Integer Nb = aBspl->NbKnots();
Standard_Integer Index1 = 0;
Standard_Integer Index2 = 0;
Standard_Real newFirst, newLast;
TColStd_Array1OfReal TK(1,Nb);
TColStd_Array1OfInteger TM(1,Nb);
- myBspl->Knots(TK);
- myBspl->Multiplicities(TM);
- BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U1,myBspl->IsPeriodic(),
+ aBspl->Knots(TK);
+ aBspl->Multiplicities(TM);
+ BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,U1,aBspl->IsPeriodic(),
1,Nb,Index1,newFirst);
- BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U2,myBspl->IsPeriodic(),
+ BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,U2,aBspl->IsPeriodic(),
1,Nb,Index2,newLast);
if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) {
if (Index1 < Nb)Index1++;
Index2--;
Standard_Integer MultMax;
// attention aux courbes peridiques.
- if ( (myBspl->IsPeriodic()) && (Index1 == Nb) )
+ if ( (aBspl->IsPeriodic()) && (Index1 == Nb) )
Index1 = 1;
if ( Index2 - Index1 <= 0) {
for(Standard_Integer i = Index1+1;i<=Index2;i++) {
if ( TM(i)>MultMax) MultMax=TM(i);
}
- MultMax = myBspl->Degree() - MultMax;
+ MultMax = aBspl->Degree() - MultMax;
}
if ( MultMax <= 0) {
return GeomAbs_C0;
if ( myCurve != C) {
myCurve = C;
+ myCurveCache = Handle(BSplCLib_Cache)();
Handle(Standard_Type) TheType = C->DynamicType();
if ( TheType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
- Load((*((Handle(Geom2d_TrimmedCurve)*)&C))->BasisCurve(),
+ Load(Handle(Geom2d_TrimmedCurve)::DownCast (C)->BasisCurve(),
UFirst,ULast);
}
else if ( TheType == STANDARD_TYPE(Geom2d_Circle)) {
}
else if ( TheType == STANDARD_TYPE(Geom2d_BezierCurve)) {
myTypeCurve = GeomAbs_BezierCurve;
+ // Create cache for Bezier
+ Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast(myCurve);
+ Standard_Integer aDeg = aBezier->Degree();
+ TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
+ myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
+ aBezier->Poles(), aBezier->Weights());
}
else if ( TheType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
myTypeCurve = GeomAbs_BSplineCurve;
+ // Create cache for B-spline
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
+ myCurveCache = new BSplCLib_Cache(aBspl->Degree(), aBspl->IsPeriodic(),
+ aBspl->KnotSequence(), aBspl->Poles(), aBspl->Weights());
+ }
+ else if ( TheType == STANDARD_TYPE(Geom2d_OffsetCurve))
+ {
+ myTypeCurve = GeomAbs_OffsetCurve;
+ // 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;
if (myTypeCurve == GeomAbs_BSplineCurve) {
return LocalContinuity(myFirst, myLast);
}
- else if (myCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))){
+ else if (myTypeCurve == GeomAbs_OffsetCurve){
GeomAbs_Shape S =
- (*((Handle(Geom2d_OffsetCurve)*)&myCurve))->GetBasisCurveContinuity();
+ Handle(Geom2d_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
switch(S){
case GeomAbs_CN: return GeomAbs_CN;
case GeomAbs_C3: return GeomAbs_C2;
Standard_Integer myNbIntervals = 1;
Standard_Integer NbSplit;
if (myTypeCurve == GeomAbs_BSplineCurve) {
- Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
- Standard_Integer LastIndex = myBspl->LastUKnotIndex();
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
+ Standard_Integer FirstIndex = aBspl->FirstUKnotIndex();
+ Standard_Integer LastIndex = aBspl->LastUKnotIndex();
TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
if ( S > Continuity()) {
Standard_Integer Cont;
if ( S == GeomAbs_C1) Cont = 1;
else if ( S == GeomAbs_C2) Cont = 2;
else if ( S == GeomAbs_C3) Cont = 3;
- else Cont = myBspl->Degree();
- Standard_Integer Degree = myBspl->Degree();
- Standard_Integer NbKnots = myBspl->NbKnots();
+ else Cont = aBspl->Degree();
+ Standard_Integer Degree = aBspl->Degree();
+ Standard_Integer NbKnots = aBspl->NbKnots();
TColStd_Array1OfInteger Mults (1, NbKnots);
- myBspl->Multiplicities (Mults);
+ aBspl->Multiplicities (Mults);
NbSplit = 1;
Standard_Integer Index = FirstIndex;
Inter (NbSplit) = Index;
Standard_Integer NbInt = NbSplit-1;
- Standard_Integer Nb = myBspl->NbKnots();
+ Standard_Integer Nb = aBspl->NbKnots();
Standard_Integer Index1 = 0;
Standard_Integer Index2 = 0;
Standard_Real newFirst, newLast;
TColStd_Array1OfReal TK(1,Nb);
TColStd_Array1OfInteger TM(1,Nb);
- myBspl->Knots(TK);
- myBspl->Multiplicities(TM);
- BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
- myBspl->IsPeriodic(),
+ aBspl->Knots(TK);
+ aBspl->Multiplicities(TM);
+ BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myFirst,
+ aBspl->IsPeriodic(),
1,Nb,Index1,newFirst);
- BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
- myBspl->IsPeriodic(),
+ BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myLast,
+ aBspl->IsPeriodic(),
1,Nb,Index2,newLast);
// On decale eventuellement les indices
}
}
}
- else if (myCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))){
+ else if (myTypeCurve == GeomAbs_OffsetCurve){
GeomAbs_Shape BaseS=GeomAbs_C0;
switch(S){
case GeomAbs_G1:
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;
Standard_Integer myNbIntervals = 1;
Standard_Integer NbSplit;
if (myTypeCurve == GeomAbs_BSplineCurve) {
- Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
- Standard_Integer LastIndex = myBspl->LastUKnotIndex();
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
+ Standard_Integer FirstIndex = aBspl->FirstUKnotIndex();
+ Standard_Integer LastIndex = aBspl->LastUKnotIndex();
TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
if ( S > Continuity()) {
Standard_Integer Cont;
if ( S == GeomAbs_C1) Cont = 1;
else if ( S == GeomAbs_C2) Cont = 2;
else if ( S == GeomAbs_C3) Cont = 3;
- else Cont = myBspl->Degree();
- Standard_Integer Degree = myBspl->Degree();
- Standard_Integer NbKnots = myBspl->NbKnots();
+ else Cont = aBspl->Degree();
+ Standard_Integer Degree = aBspl->Degree();
+ Standard_Integer NbKnots = aBspl->NbKnots();
TColStd_Array1OfInteger Mults (1, NbKnots);
- myBspl->Multiplicities (Mults);
+ aBspl->Multiplicities (Mults);
NbSplit = 1;
Standard_Integer Index = FirstIndex;
Inter (NbSplit) = Index;
Inter (NbSplit) = Index;
Standard_Integer NbInt = NbSplit-1;
- Standard_Integer Nb = myBspl->NbKnots();
+ Standard_Integer Nb = aBspl->NbKnots();
Standard_Integer Index1 = 0;
Standard_Integer Index2 = 0;
Standard_Real newFirst, newLast;
TColStd_Array1OfReal TK(1,Nb);
TColStd_Array1OfInteger TM(1,Nb);
- myBspl->Knots(TK);
- myBspl->Multiplicities(TM);
- BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
- myBspl->IsPeriodic(),
+ aBspl->Knots(TK);
+ aBspl->Multiplicities(TM);
+ BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myFirst,
+ aBspl->IsPeriodic(),
1,Nb,Index1,newFirst);
- BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
- myBspl->IsPeriodic(),
+ BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myLast,
+ aBspl->IsPeriodic(),
1,Nb,Index2,newLast);
}
}
}
- else if (myCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))){
+ else if (myTypeCurve == GeomAbs_OffsetCurve){
GeomAbs_Shape BaseS=GeomAbs_C0;
switch(S){
case GeomAbs_G1:
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;
return myCurve->LastParameter() - myCurve->FirstParameter();
}
+//=======================================================================
+//function : RebuildCache
+//purpose :
+//=======================================================================
+void Geom2dAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
+{
+ if (myTypeCurve == GeomAbs_BezierCurve)
+ {
+ Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast(myCurve);
+ Standard_Integer aDeg = aBezier->Degree();
+ TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
+ myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
+ aBezier->Poles(), aBezier->Weights());
+ }
+ else if (myTypeCurve == GeomAbs_BSplineCurve)
+ {
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
+ myCurveCache->BuildCache(theParameter, aBspl->Degree(),
+ aBspl->IsPeriodic(), aBspl->KnotSequence(),
+ aBspl->Poles(), aBspl->Weights());
+ }
+}
+
//=======================================================================
//function : Value
//purpose :
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 (myTypeCurve == GeomAbs_OffsetCurve)
+ return ValueOffset(U);
+ else if (myTypeCurve == GeomAbs_BezierCurve)
+ { // use cached data
+ gp_Pnt2d aRes;
+ myCurveCache->D0(U, aRes);
+ return aRes;
+ }
+
+ 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)
+ {
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
Standard_Integer Ideb = 0, Ifin = 0;
- if (U==myFirst) {
- myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
+ if (theU == myFirst)
+ {
+ aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
- if (U==myLast) {
- myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
- if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
+ if (theU == myLast)
+ {
+ aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
+ if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
- return myBspl->LocalValue(U, Ideb, Ifin);
+ return aBspl->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;
}
//=======================================================================
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);
+ else if (myTypeCurve == GeomAbs_OffsetCurve)
+ D0Offset(U, P);
+ else if (myTypeCurve == GeomAbs_BezierCurve) // use cached data
+ myCurveCache->D0(U, P);
+ else
+ 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)
+ {
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
Standard_Integer Ideb = 0, Ifin = 0;
- if (U==myFirst) {
- myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
+ if (theU == myFirst) {
+ aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
- if (U==myLast) {
- myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
- if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
+ if (theU == myLast) {
+ aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
+ if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
- myBspl->LocalD0( U, Ideb, Ifin, P);
+ aBspl->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);
}
//=======================================================================
//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)
+ D1BSpline(U, P, V);
+ else if (myTypeCurve == GeomAbs_OffsetCurve)
+ D1Offset(U, P, V);
+ else if (myTypeCurve == GeomAbs_BezierCurve) // use cached data
+ myCurveCache->D1(U, P, V);
+ else
+ 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 ( (myTypeCurve == GeomAbs_BSplineCurve)&&
- (U==myFirst || U==myLast) ) {
+ if (theU == myFirst || theU == myLast)
+ {
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
Standard_Integer Ideb = 0, Ifin = 0;
- if (U==myFirst) {
- myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
+ if (theU == myFirst) {
+ aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
- if (U==myLast) {
- myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
- if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
+ if (theU == myLast) {
+ aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
+ if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
- myBspl->LocalD1( U, Ideb, Ifin, P, V);
- }
- else {
- myCurve->D1( U, P, V);
+ aBspl->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);
}
//=======================================================================
//=======================================================================
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);
+ else if (myTypeCurve == GeomAbs_OffsetCurve)
+ D2Offset(U, P, V1, V2);
+ else if (myTypeCurve == GeomAbs_BezierCurve) // use cached data
+ myCurveCache->D2(U, P, V1, V2);
+ else
+ 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)
+ {
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
Standard_Integer Ideb = 0, Ifin = 0;
- if (U==myFirst) {
- myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
+ if (theU == myFirst) {
+ aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
- if (U==myLast) {
- myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
- if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
+ if (theU == myLast) {
+ aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
+ if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
- myBspl->LocalD2( U, Ideb, Ifin, P, V1, V2);
+ aBspl->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);
}
//=======================================================================
//=======================================================================
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);
+ else if (myTypeCurve == GeomAbs_OffsetCurve)
+ D3Offset(U, P, V1, V2, V3);
+ else if (myTypeCurve == GeomAbs_BezierCurve) // use cached data
+ myCurveCache->D3(U, P, V1, V2, V3);
+ else
+ 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)
+ {
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
Standard_Integer Ideb = 0, Ifin = 0;
- if (U==myFirst) {
- myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
+ if (theU == myFirst) {
+ aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
- if (U==myLast) {
- myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
- if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
+ if (theU == myLast) {
+ aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
+ if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
- myBspl->LocalD3( U, Ideb, Ifin, P, V1, V2, V3);
+ aBspl->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);
}
//=======================================================================
//=======================================================================
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 (myTypeCurve == GeomAbs_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)
+ {
+ Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
Standard_Integer Ideb = 0, Ifin = 0;
if (U==myFirst) {
- myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
+ aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
if (Ideb<1) Ideb=1;
if (Ideb>=Ifin) Ifin = Ideb+1;
}
if (U==myLast) {
- myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
- if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
+ aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
+ if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
if (Ideb>=Ifin) Ideb = Ifin-1;
}
- return myBspl->LocalDN( U, Ideb, Ifin, N);
- }
- else {
- return myCurve->DN( U, N);
+ return aBspl->LocalDN( U, Ideb, Ifin, 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;
}
//=======================================================================
case GeomAbs_Line :
return Ruv;
case GeomAbs_Circle: {
- Standard_Real R = (*((Handle(Geom2d_Circle)*)&myCurve))->Circ2d().Radius();
+ Standard_Real R = Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d().Radius();
if ( R > Ruv/2.)
return 2*ASin(Ruv/(2*R));
else
return 2*M_PI;
}
case GeomAbs_Ellipse: {
- return Ruv / (*((Handle(Geom2d_Ellipse)*)&myCurve))->MajorRadius();
+ return Ruv / Handle(Geom2d_Ellipse)::DownCast (myCurve)->MajorRadius();
}
case GeomAbs_BezierCurve: {
Standard_Real res;
- (*((Handle(Geom2d_BezierCurve)*)&myCurve))->Resolution(Ruv,res);
+ Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Resolution(Ruv,res);
return res;
}
case GeomAbs_BSplineCurve: {
Standard_Real res;
- (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->Resolution(Ruv,res);
+ Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Resolution(Ruv,res);
return res;
}
default:
gp_Lin2d Geom2dAdaptor_Curve::Line() const
{
Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
- return (*((Handle(Geom2d_Line)*)&myCurve))->Lin2d();
+ return Handle(Geom2d_Line)::DownCast (myCurve)->Lin2d();
}
//=======================================================================
gp_Circ2d Geom2dAdaptor_Curve::Circle() const
{
Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
- return (*((Handle(Geom2d_Circle)*)&myCurve))->Circ2d();
+ return Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d();
}
//=======================================================================
gp_Elips2d Geom2dAdaptor_Curve::Ellipse() const
{
Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
- return (*((Handle(Geom2d_Ellipse)*)&myCurve))->Elips2d();
+ return Handle(Geom2d_Ellipse)::DownCast (myCurve)->Elips2d();
}
//=======================================================================
gp_Hypr2d Geom2dAdaptor_Curve::Hyperbola() const
{
Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
- return (*((Handle(Geom2d_Hyperbola)*)&myCurve))->Hypr2d();
+ return Handle(Geom2d_Hyperbola)::DownCast (myCurve)->Hypr2d();
}
//=======================================================================
gp_Parab2d Geom2dAdaptor_Curve::Parabola() const
{
Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
- return (*((Handle(Geom2d_Parabola)*)&myCurve))->Parab2d();
+ return Handle(Geom2d_Parabola)::DownCast (myCurve)->Parab2d();
}
//=======================================================================
Standard_Integer Geom2dAdaptor_Curve::Degree() const
{
if (myTypeCurve == GeomAbs_BezierCurve)
- return (*((Handle(Geom2d_BezierCurve)*)&myCurve))->Degree();
+ return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Degree();
else if (myTypeCurve == GeomAbs_BSplineCurve)
- return (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->Degree();
+ return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Degree();
else
Standard_NoSuchObject::Raise();
// portage WNT
Standard_Boolean Geom2dAdaptor_Curve::IsRational() const {
switch( myTypeCurve) {
case GeomAbs_BSplineCurve:
- return (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->IsRational();
+ return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->IsRational();
case GeomAbs_BezierCurve:
- return (*((Handle(Geom2d_BezierCurve)*)&myCurve))->IsRational();
+ return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->IsRational();
default:
return Standard_False;
}
Standard_Integer Geom2dAdaptor_Curve::NbPoles() const
{
if (myTypeCurve == GeomAbs_BezierCurve)
- return (*((Handle(Geom2d_BezierCurve)*)&myCurve))->NbPoles();
+ return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->NbPoles();
else if (myTypeCurve == GeomAbs_BSplineCurve)
- return (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->NbPoles();
+ return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->NbPoles();
else
Standard_NoSuchObject::Raise();
// portage WNT
Standard_Integer Geom2dAdaptor_Curve::NbKnots() const {
if ( myTypeCurve != GeomAbs_BSplineCurve)
Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::NbKnots");
- return (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->NbKnots();
+ return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->NbKnots();
}
Handle(Geom2d_BezierCurve) Geom2dAdaptor_Curve::Bezier() const
{
- return *((Handle(Geom2d_BezierCurve)*)&myCurve);
+ return Handle(Geom2d_BezierCurve)::DownCast (myCurve);
}
//=======================================================================
Handle(Geom2d_BSplineCurve) Geom2dAdaptor_Curve::BSpline() const
{
- return *((Handle(Geom2d_BSplineCurve)*)&myCurve);
+ return Handle(Geom2d_BSplineCurve)::DownCast (myCurve);
}
static Standard_Integer nbPoints(const Handle(Geom2d_Curve)& theCurve)
nbs = 2;
else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BezierCurve)))
{
- nbs = 3 + (*((Handle(Geom2d_BezierCurve)*)&theCurve))->NbPoles();
+ nbs = 3 + Handle(Geom2d_BezierCurve)::DownCast (theCurve)->NbPoles();
}
else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BSplineCurve))) {
- nbs = (*((Handle(Geom2d_BSplineCurve)*)&theCurve))->NbKnots();
- nbs*= (*((Handle(Geom2d_BSplineCurve)*)&theCurve))->Degree();
+ nbs = Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->NbKnots();
+ nbs*= Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->Degree();
if(nbs < 2.0) nbs=2;
}
else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
{
- Handle(Geom2d_Curve) aCurve = (*((Handle(Geom2d_OffsetCurve)*)&theCurve))->BasisCurve();
+ Handle(Geom2d_Curve) aCurve = Handle(Geom2d_OffsetCurve)::DownCast (theCurve)->BasisCurve();
return Max(nbs, nbPoints(aCurve));
}
else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
{
- Handle(Geom2d_Curve) aCurve = (*((Handle(Geom2d_TrimmedCurve)*)&theCurve))->BasisCurve();
+ Handle(Geom2d_Curve) aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
return Max(nbs, nbPoints(aCurve));
}
if(nbs>300)
{
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;
+}