14 #include <qpainterpath.h> 16 #define SLOPES_INCREMENTAL 0 42 const double y = value -
d_carry;
43 const double t =
d_sum + y;
45 d_carry = ( t -
d_sum ) - y;
49 static inline double sum3(
double d1,
double d2,
double d3 )
58 static inline double sum4(
double d1,
double d2,
double d3,
double d4 )
79 d_curvatures.resize( size );
80 d_cv = d_curvatures.data();
84 const QPointF &,
const QPointF &,
double b1,
double )
90 const QPointF &,
const QPointF &,
double,
double b2 )
92 d_cv[index] = 2.0 * b2;
96 const QPointF &,
const QPointF &,
double,
double b2 )
98 d_cv[d_curvatures.size() - 1] = 2.0 * b2;
102 const QPointF &,
const QPointF &,
double b1,
double )
104 d_cv[index] = 2.0 * b1;
109 d_cv[0] = d_cv[d_curvatures.size() - 1];
124 d_slopes.resize( size );
125 d_m = d_slopes.data();
129 const QPointF &p1,
const QPointF &p2,
double b1,
double b2 )
131 const double s = ( p2.y() - p1.y() ) / h;
132 d_m[0] = s - h * ( 2.0 * b1 + b2 ) / 3.0;
139 const QPointF &p1,
const QPointF &p2,
double b1,
double b2 )
141 #if SLOPES_INCREMENTAL 145 d_sum.add( ( b1 + b2 ) * h );
146 d_m[index] =
d_sum.value();
148 d_m[index] = d_m[index-1] + ( b1 + b2 ) * h;
151 const double s = ( p2.y() - p1.y() ) / h;
152 d_m[index] = s + h * ( b1 + 2.0 * b2 ) / 3.0;
157 const QPointF &p1,
const QPointF &p2,
double b1,
double b2 )
159 const double s = ( p2.y() - p1.y() ) / h;
160 d_m[d_slopes.size() - 1] = s + h * ( b1 + 2.0 * b2 ) / 3.0;
162 d_sum.add( d_m[d_slopes.size() - 1] );
167 const QPointF &p1,
const QPointF &p2,
double b1,
double b2 )
169 #if SLOPES_INCREMENTAL 173 d_sum.add( -( b1 + b2 ) * h );
174 d_m[index] =
d_sum.value();
176 d_m[index] = d_m[index+1] - ( b1 + b2 ) * h;
180 const double s = ( p2.y() - p1.y() ) / h;
181 d_m[index] = s - h * ( 2.0 * b1 + b2 ) / 3.0;
187 d_m[0] = d_m[d_slopes.size() - 1];
195 #if SLOPES_INCREMENTAL 217 inline void setup(
double p0 ,
double q0,
double r0 )
236 return ( r - q * x2 ) / p;
241 return ( r - p * x1 ) / q;
248 return ( r - k * eq.
r ) / ( p - k * eq.
p );
254 const double k = p / eq.
p;
255 return ( r - k * eq.
r ) / ( q - k * eq.
q );
269 inline Equation3(
const QPointF &p1,
const QPointF &p2,
const QPointF &p3 )
271 const double h1 = p2.x() - p1.x();
272 const double s1 = ( p2.y() - p1.y() ) / h1;
274 const double h2 = p3.x() - p2.x();
275 const double s2 = ( p3.y() - p2.y() ) / h2;
283 inline Equation3(
double cp,
double cq,
double du,
double dr ):
293 return ( p == c.
p ) && ( q == c.
q ) &&
294 ( u == c.
u ) && ( r == c.
r );
297 inline void setup(
double cp,
double cq,
double du,
double dr )
319 const double k = p / eq.
p;
320 return Equation2( q - k * eq.
q, u - k * eq.
u, r - k * eq.
r );
327 const double k = q / eq.
q;
328 return Equation2( p - k * eq.
p, u - k * eq.
u, r - k * eq.
r );
335 const double k = u / eq.
u;
336 return Equation2( p - k * eq.
p, q - k * eq.
q, r - k * eq.
r );
342 const double k = p / eq.
p;
350 const double k = u / eq.
q;
357 return ( r - q * x2 - u * x3 ) / p;
362 return ( r - u * x3 - p * x1 ) / q;
367 return ( r - p * x1 - q * x2 ) / u;
378 debug.nospace() <<
"EQ2(" << eq.
p <<
", " << eq.
q <<
", " << eq.
r <<
")";
379 return debug.space();
384 debug.nospace() <<
"EQ3(" << eq.
p <<
", " 385 << eq.
q <<
", " << eq.
u <<
", " << eq.
r <<
")";
386 return debug.space();
398 d_conditionsEQ[0].setup( p, q, u, r );
403 d_conditionsEQ[1].setup( p, q, u, r );
413 const int n = p.size();
417 if ( d_conditionsEQ[0].p == 0.0 ||
418 ( d_conditionsEQ[0].q == 0.0 && d_conditionsEQ[0].u != 0.0 ) )
423 if ( d_conditionsEQ[1].u == 0.0 ||
424 ( d_conditionsEQ[1].q == 0.0 && d_conditionsEQ[1].p != 0.0 ) )
429 const double h0 = p[1].x() - p[0].x();
430 const double h1 = p[2].x() - p[1].x();
431 const double hn = p[n-1].x() - p[n-2].x();
443 const Equation3 eqSpline0( p[0], p[1], p[2] );
444 const Equation2 eq0 = d_conditionsEQ[0].substituted1( eqSpline0 );
451 if ( d_conditionsEQ[0].normalized() == d_conditionsEQ[1].normalized() )
467 const double b0 = eqSpline0.
resolved1( b1, b2 );
469 d_store.storeFirst( h0, p[0], p[1], b0, b1 );
470 d_store.storeNext( 1, h0, p[0], p[1], b0, b1 );
471 d_store.storeNext( 2, h1, p[1], p[2], b1, b2 );
476 const Equation3 eqSplineN( p[n-3], p[n-2], p[n-1] );
477 const Equation2 eqN = d_conditionsEQ[1].substituted3( eqSplineN );
482 const Equation3 eqSplineR( p[n-4], p[n-3], p[n-2] );
484 eq = substituteSpline( p, eq );
487 const Equation3 eqSpline0( p[0], p[1], p[2] );
490 if ( d_conditionsEQ[0].u == 0.0 )
494 const Equation3 &eq0 = d_conditionsEQ[0];
500 const Equation2 eqX = d_conditionsEQ[0].substituted3( eq );
507 d_store.storeFirst( h0, p[0], p[1], b0, b1 );
508 d_store.storeNext( 1, h0, p[0], p[1], b0, b1 );
510 const double bn2 = resolveSpline( p, b1 );
513 const double bn0 = d_conditionsEQ[1].resolved3( bn2, bn1 );
515 const double hx = p[n-2].x() - p[n-3].x();
516 d_store.storeNext( n - 2, hx, p[n-3], p[n-2], bn2, bn1 );
517 d_store.storeNext( n - 1, hn, p[n-2], p[n-1], bn1, bn0 );
523 const int n = points.size();
525 d_eq.resize( n - 2 );
530 double slope2 = ( points[n-3].y() - points[n-4].y() ) / eq.
p;
532 for (
int i = n - 4; i > 1; i-- )
537 eq1.
p = points[i].x() - points[i-1].x();
538 const double slope1 = ( points[i].y() - points[i-1].y() ) / eq1.
p;
540 const double v = eq2.
p / eq2.
q;
542 eq1.
q = 2.0 * ( eq1.
p + eq2.
p ) - v * eq2.
p;
543 eq1.
r = 3.0 * ( slope2 - slope1 ) - v * eq2.
r;
553 const int n = points.size();
554 const QPointF *p = points.constData();
556 for (
int i = 2; i < n - 2; i++ )
559 const double b2 = d_eq[i].resolved2( b1 );
560 d_store.storeNext( i, d_eq[i].p, p[i-1], p[i], b1, b2 );
585 const int n = p.size();
587 if ( p[n-1].y() != p[0].y() )
592 const double h0 = p[1].x() - p[0].x();
593 const double s0 = ( p[1].y() - p[0].y() ) / h0;
597 const double h1 = p[2].x() - p[1].x();
598 const double s1 = ( p[2].y() - p[1].y() ) / h1;
600 const double b = 3.0 * ( s0 - s1 ) / ( h0 + h1 );
603 d_store.storeLast( h1, p[1], p[2], -b, b );
604 d_store.storePrevious( 1, h1, p[1], p[2], -b, b );
610 const double hn = p[n-1].x() - p[n-2].x();
613 substitute( p, eqn, eqX );
619 d_store.storeLast( hn, p[n-2], p[n-1], bn, b0 );
620 d_store.storePrevious( n - 2, hn, p[n-2], p[n-1], bn, b0 );
622 resolveSpline( p, b0, bn );
631 const int n = points.size();
633 const double hn = points[n-1].x() - points[n-2].x();
635 const Equation3 eqSpline0( points[0], points[1], points[2] );
637 QPointF( points[0].x() - hn, points[n-2].y() ), points[0], points[1] );
639 d_eq.resize( n - 1 );
646 double slope1 = ( points[2].y() - points[1].y() ) / d_eq[1].u;
660 for (
int i = 2; i < n - 1; i++ )
665 dq += eq1.
p * eq1.
p / eq1.
q;
666 dr += eq1.
p * eq1.
r / eq1.
q;
668 eq2.
u = points[i+1].x() - points[i].x();
669 const double slope2 = ( points[i+1].y() - points[i].y() ) / eq2.
u;
671 const double k = eq1.
u / eq1.
q;
674 eq2.
q = 2.0 * ( eq1.
u + eq2.
u ) - eq1.
u * k;
675 eq2.
r = 3.0 * ( slope2 - slope1 ) - eq1.
r * k;
682 eqn.
setup( d_eq[n-2].q, d_eq[n-2].p + eqSplineN.
p , d_eq[n-2].r );
685 eqX.
setup( d_eq[n-2].p + eqSplineN.
p, eqSplineN.
q - dq, eqSplineN.
r - dr );
690 const int n = points.size();
692 for (
int i = n - 3; i >= 1; i-- )
697 d_store.storePrevious( i, eq.
u, points[i], points[i+1], b, bi );
706 const int n = points.size();
708 bi = d_eq[0].resolved3( b0, bi );
710 for (
int i = 1; i < n - 2; i++ )
715 m[i+1] = m[i] + ( b + bi ) * d_eq[i].u;
724 const int n = points.size();
726 double h0 = ( points[1].x() - points[0].x() );
727 double s0 = ( points[1].y() - points[0].y() ) / h0;
729 m[1] = m[0] + ( b0 + b1 ) * h0;
731 for (
int i = 1; i < n - 1; i++ )
733 const double h1 = ( points[i+1].x() - points[i].x() );
734 const double s1 = ( points[i+1].y() - points[i].y() ) / h1;
736 const double r = 3.0 * ( s1 - s0 );
738 const double b2 = ( r - h0 * b0 - 2.0 * ( h0 + h1 ) * b1 ) / h1;
739 m[i+1] = m[i] + ( b1 + b2 ) * h1;
751 const int n = points.size();
753 double h2 = ( points[n-1].x() - points[n-2].x() );
754 double s2 = ( points[n-1].y() - points[n-2].y() ) / h2;
756 for (
int i = n - 2; i > 1; i-- )
758 const double h1 = ( points[i].x() - points[i-1].x() );
759 const double s1 = ( points[i].y() - points[i-1].y() ) / h1;
761 const double r = 3.0 * ( s2 - s1 );
762 const double k = 2.0 * ( h1 + h2 );
764 const double b0 = ( r - h2 * b2 - k * b1 ) / h1;
766 m[i-1] = m[i] - ( b0 + b1 ) * h1;
782 int conditionBegin,
double valueBegin,
int conditionEnd,
double valueEnd,
785 const int n = points.size();
787 const double h0 = points[1].x() - points[0].x();
788 const double s0 = ( points[1].y() - points[0].y() ) / h0;
790 const double hn = ( points[n-1].x() - points[n-2].x() );
791 const double sn = ( points[n-1].y() - points[n-2].y() ) / hn;
793 switch( conditionBegin )
808 eq[0].
setup( 2 * h0 / 3.0, h0 / 3.0, 0.0, s0 - valueBegin );
821 eq[0].
setup( 1.0, 0.0, 0.0, 0.5 * valueBegin );
836 eq[0].
setup( 1.0, -1.0, 0.0, -0.5 * valueBegin * h0 );
842 const double r0 = qBound( 0.0, valueBegin, 1.0 );
846 eq[0].
setup( 2 * h0 / 3.0, h0 / 3.0, 0.0, 0.0 );
850 eq[0].
setup( 1.0 + 2.0 / r0, 2.0 + 1.0 / r0, 0.0, 0.0 );
875 v0 = h0 / ( points[2].x() - points[1].x() );
878 eq[0].
setup( 1.0, -( 1.0 + v0 ), v0, 0.0 );
885 eq[0].
setup( 1.0, 0.0, 0.0, 0.0 );
890 switch( conditionEnd )
895 eq[1].
setup( 0.0, 1.0 / 3.0 * hn, 2.0 / 3.0 * hn, valueEnd - sn );
901 eq[1].
setup( 0.0, 0.0, 1.0, 0.5 * valueEnd );
907 eq[1].
setup( 0.0, 1.0, -1.0, -0.5 * valueEnd * hn );
912 const double rn = qBound( 0.0, valueEnd, 1.0 );
916 eq[1].
setup( 0.0, 1.0 / 3.0 * hn, 2.0 / 3.0 * hn, 0.0 );
920 eq[1].
setup( 0.0, 2.0 + 1.0 / rn, 1.0 + 2.0 / rn, 0.0 );
942 vn = hn / ( points[n-2].x() - points[n-3].x() );
945 eq[1].
setup( vn, -( 1.0 + vn ), 1.0, 0.0 );
952 eq[1].
setup( 0.0, 0.0, 1.0, 0.0 );
1016 if ( points.size() <= 2 )
1028 if ( points.size() == 3 )
1034 const double h0 = points[1].x() - points[0].x();
1035 const double h1 = points[2].x() - points[1].x();
1037 const double s0 = ( points[1].y() - points[0].y() ) / h0;
1038 const double s1 = ( points[2].y() - points[1].y() ) / h1;
1045 const double b = ( s1 - s0 ) / ( h0 + h1 );
1088 if ( points.size() <= 2 )
1100 if ( points.size() == 3 )
virtual ~QwtSplineCubic()
Destructor.
Equation2 substituted2(const Equation3 &eq) const
Equation2 normalized() const
void storeLast(double h, const QPointF &p1, const QPointF &p2, double b1, double b2)
static double sum3(double d1, double d2, double d3)
static double sum4(double d1, double d2, double d3, double d4)
Equation2 substituteSpline(const QPolygonF &points, const Equation2 &eq)
Equation2 substituted3(const Equation2 &eq) const
static void qwtSetupEndEquations(int conditionBegin, double valueBegin, int conditionEnd, double valueEnd, const QPolygonF &points, QwtSplineCubicP::Equation3 eq[2])
virtual QVector< QwtSplinePolynomial > polynomials(const QPolygonF &) const QWT_OVERRIDE
Calculate the interpolating polynomials for a non parametric spline.
void storeLast(double, const QPointF &, const QPointF &, double, double b2)
Equation3(double cp, double cq, double du, double dr)
void resolveSpline2(const QPolygonF &points, double b0, double bi, QVector< double > &m)
void storeFirst(double h, const QPointF &p1, const QPointF &p2, double b1, double b2)
void setup(double p0, double q0, double r0)
void setup(double cp, double cq, double du, double dr)
void resolve(const QPolygonF &p)
void storeNext(int index, double, const QPointF &, const QPointF &, double, double b2)
QVector< double > slopes() const
the condiation is at the end of the polynomial
void storeNext(int index, double h, const QPointF &p1, const QPointF &p2, double b1, double b2)
KahanSum(double value=0.0)
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
QVector< double > curvatures() const
virtual QPainterPath painterPath(const QPolygonF &) const QWT_OVERRIDE
Calculate an interpolated painter path.
Equation2 substituted3(const Equation3 &eq) const
virtual QVector< QLineF > bezierControlLines(const QPolygonF &points) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
the condiation is at the beginning of the polynomial
QDebug operator<<(QDebug debug, const QwtInterval &interval)
void resolve(const QPolygonF &p)
Equation2 substituted1(const Equation2 &eq) const
double resolved1(double x2) const
QVector< double > d_curvatures
Equation2 substituted1(const Equation3 &eq) const
void storePrevious(int index, double h, const QPointF &p1, const QPointF &p2, double b1, double b2)
bool operator==(const Equation3 &c) const
virtual uint locality() const QWT_OVERRIDE
void setStartCondition(double p, double q, double u, double r)
void setEndCondition(double p, double q, double u, double r)
void resolveSpline3(const QPolygonF &points, double b0, double b1, QVector< double > &m)
virtual QVector< double > slopes(const QPolygonF &) const QWT_OVERRIDE
Find the first derivative at the control points.
Equation2(double p0, double q0, double r0)
QVector< double > d_slopes
double resolved1(double x2, double x3) const
void storeFirst(double, const QPointF &, const QPointF &, double b1, double)
double resolveSpline(const QPolygonF &points, double b1)
double resolved2(double x1, double x3) const
double resolved3(double x1, double x2) const
Equation3 normalized() const
double resolved2(double x1) const
QVector< Equation2 > d_eq
virtual QVector< QwtSplinePolynomial > polynomials(const QPolygonF &) const QWT_OVERRIDE
Calculate the interpolating polynomials for a non parametric spline.
virtual QPainterPath painterPath(const QPolygonF &) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
virtual QVector< double > curvatures(const QPolygonF &) const QWT_OVERRIDE
Find the second derivative at the control points.
double resolved1(const Equation2 &eq) const
QwtSplineCubic()
Constructor The default setting is a non closing natural spline with no parametrization.
Equation3(const QPointF &p1, const QPointF &p2, const QPointF &p3)
QVector< Equation3 > d_eq
void resolveSpline4(const QPolygonF &points, double b2, double b1, QVector< double > &m)
void resolveSpline(const QPolygonF &points, double b0, double bi)
void substitute(const QPolygonF &points, Equation2 &eqn, Equation2 &eqX)
double resolved2(const Equation2 &eq) const
void storePrevious(int index, double, const QPointF &, const QPointF &, double b1, double)