Go to the documentation of this file.00001 #include "qwt_spline_basis.h"
00002 #include "qwt_spline_parametrization.h"
00003
00004 #if 0
00005 static QPolygonF qwtBasisUniformKnots( const QPolygonF& points )
00006 {
00007 const int n = points.size();
00008
00009 if ( n < 3 )
00010 return points;
00011
00012 QVector<double> u( n - 2 );
00013 QVector<double> kx( n - 2 );
00014 QVector<double> ky( n - 2 );
00015
00016 u[n-3] = 4.0;
00017 kx[n-3] = 6.0 * points[n-2].x() - points[n-1].x();
00018 ky[n-3] = 6.0 * points[n-2].y() - points[n-1].y();
00019
00020 for ( int i = n - 4; i >= 0; i-- )
00021 {
00022 u[i] = 4.0 - 1.0 / u[i+1];
00023 kx[i] = 6.0 * points[i+1].x() - kx[i+1] / u[i+1];
00024 ky[i] = 6.0 * points[i+1].y() - ky[i+1] / u[i+1];
00025 }
00026
00027 QVector<QPointF> knots( n );
00028
00029 knots[0] = points[0];
00030
00031 for ( int i = 1; i < n - 1; i++ )
00032 {
00033 knots[i].rx() = ( kx[i-1] - knots[i-1].x() ) / u[i-1];
00034 knots[i].ry() = ( ky[i-1] - knots[i-1].y() ) / u[i-1];
00035 }
00036
00037 knots[n-1] = points[n-1];
00038
00039 return knots;
00040 }
00041 #endif
00042
00043 static inline void qwtSplineBezierControlPoints( const QwtSplineParametrization *param,
00044 const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4,
00045 QPointF &cp1, QPointF &cp2 )
00046 {
00047 const double t1 = param->valueIncrement( p1, p2 );
00048 const double t2 = param->valueIncrement( p2, p3 );
00049 const double t3 = param->valueIncrement( p3, p4 );
00050
00051 const double t123 = t1 + t2 + t3;
00052
00053 cp1 = ( t2 + t3 ) / t123 * p2 + t1 / t123 * p3;
00054 cp2 = ( t3 * p2 + ( t1 + t2 ) * p3 ) / t123;
00055 }
00056
00057 static QPainterPath qwtSplineBasisPathUniform( const QPolygonF& points,
00058 QwtSpline::BoundaryType boundaryType )
00059 {
00060 const int n = points.size();
00061 const QPointF *pd = points.constData();
00062
00063 QPainterPath path;
00064
00065 QPointF cp1 = ( 2.0 * pd[0] + pd[1] ) / 3.0;;
00066
00067 if ( boundaryType == QwtSpline::ConditionalBoundaries )
00068 {
00069 path.moveTo( pd[0] );
00070 }
00071 else
00072 {
00073 const QPointF cpN = ( pd[n-1] + 2.0 * pd[0] ) / 3.0;
00074 path.moveTo( 0.5 * ( cpN + cp1 ) );
00075 }
00076
00077 for ( int i = 1; i < n - 1; i++ )
00078 {
00079 const QPointF cp2 = ( pd[i-1] + 2.0 * pd[i] ) / 3.0;
00080 const QPointF cp3 = ( 2.0 * pd[i] + pd[i+1] ) / 3.0;
00081
00082 path.cubicTo( cp1, cp2, 0.5 * ( cp2 + cp3 ) );
00083
00084 cp1 = cp3;
00085 }
00086
00087 if ( boundaryType == QwtSpline::ConditionalBoundaries )
00088 {
00089 const QPointF cp2 = ( pd[n-2] + 2.0 * pd[n-1] ) / 3.0;
00090 path.cubicTo( cp1, cp2, pd[n-1] );
00091 }
00092 else
00093 {
00094 const QPointF cp2 = ( pd[n-2] + 2.0 * pd[n-1] ) / 3.0;
00095 const QPointF cp3 = ( 2.0 * pd[n-1] + pd[0] ) / 3.0;
00096
00097 path.cubicTo( cp1, cp2, 0.5 * ( cp2 + cp3 ) );
00098
00099 if ( boundaryType == QwtSpline::ClosedPolygon )
00100 {
00101 const QPointF cp4 = ( pd[n-1] + 2.0 * pd[0] ) / 3.0;
00102 const QPointF cp5 = ( 2.0 * pd[0] + pd[1] ) / 3.0;
00103
00104 path.cubicTo( cp3, cp4, 0.5 * ( cp4 + cp5 ) );
00105 }
00106 }
00107
00108 return path;
00109 }
00110
00111 static QPainterPath qwtSplineBasisPath( const QPolygonF &points,
00112 const QwtSplineParametrization *param,
00113 QwtSpline::BoundaryType boundaryType )
00114 {
00115 const int n = points.size();
00116 const QPointF *pd = points.constData();
00117
00118 QPointF p0;
00119
00120 double t1 = param->valueIncrement( pd[0], pd[1] );
00121 double t2 = param->valueIncrement( pd[1], pd[2] );
00122
00123 double t0;
00124 if ( boundaryType == QwtSpline::ConditionalBoundaries )
00125 t0 = t1;
00126 else
00127 t0 = param->valueIncrement( pd[n-1], pd[0] );
00128
00129 double t012 = t0 + t1 + t2;
00130 QPointF cp1 = ( ( t1 + t2 ) * pd[0] + t0 * pd[1] ) / t012;
00131
00132 if ( boundaryType == QwtSpline::ConditionalBoundaries )
00133 {
00134 p0 = pd[0];
00135 }
00136 else
00137 {
00138 const double tN = param->valueIncrement( pd[n-2], pd[n-1] );
00139 const QPointF cpN = ( t1 * pd[n-1] + ( tN + t0 ) * pd[0] ) / ( tN + t0 + t1 );
00140
00141 p0 = ( t1 * cpN + t0 * cp1 ) / ( t0 + t1 );
00142 }
00143
00144 QPainterPath path;
00145 path.moveTo( p0 );
00146
00147 for ( int i = 1; i < n - 2; i++ )
00148 {
00149 const double t3 = param->valueIncrement( pd[i+1], pd[i+2] );
00150 const double t123 = t1 + t2 + t3;
00151
00152 const QPointF cp2 = ( t2 * pd[i-1] + ( t0 + t1 ) * pd[i] ) / t012;
00153 const QPointF cp3 = ( ( t2 + t3 ) * pd[i] + t1 * pd[i+1] ) / t123;
00154
00155 const QPointF p2 = ( t2 * cp2 + t1 * cp3 ) / ( t1 + t2 );
00156
00157 path.cubicTo( cp1, cp2, p2 );
00158
00159 cp1 = cp3;
00160
00161 t0 = t1;
00162 t1 = t2;
00163 t2 = t3;
00164 t012 = t123;
00165 }
00166
00167 {
00168 double t3;
00169 if ( boundaryType == QwtSpline::ConditionalBoundaries )
00170 t3 = t2;
00171 else
00172 t3 = param->valueIncrement( pd[n-1], pd[0] );
00173
00174 const double t123 = t1 + t2 + t3;
00175
00176 const QPointF cp2 = ( t2 * pd[n-3] + ( t0 + t1 ) * pd[n-2] ) / t012;
00177 const QPointF cp3 = ( ( t2 + t3 ) * pd[n-2] + t1 * pd[n-1] ) / t123;
00178
00179 const QPointF p2 = ( t2 * cp2 + t1 * cp3 ) / ( t1 + t2 );
00180
00181 path.cubicTo( cp1, cp2, p2 );
00182
00183 cp1 = cp3;
00184
00185 t0 = t1;
00186 t1 = t2;
00187 t2 = t3;
00188 t012 = t123;
00189 }
00190
00191 const QPointF cp2 = ( t2 * pd[n-2] + ( t0 + t1 ) * pd[n-1] ) / t012;
00192
00193 if ( boundaryType == QwtSpline::ConditionalBoundaries )
00194 {
00195 path.cubicTo( cp1, cp2, pd[n-1] );
00196 }
00197 else
00198 {
00199 const double t3 = param->valueIncrement( pd[0], pd[1] );
00200 const double t123 = t1 + t2 + t3;
00201
00202 const QPointF cp3 = ( t2 + t3 ) / t123 * pd[n-1] + t1 / t123 * pd[0];
00203 const QPointF cp4 = ( t3 * pd[n-1] + ( t1 + t2 ) * pd[0] ) / t123;
00204
00205 const QPointF pN = ( t2 * cp2 + t1 * cp3 ) / ( t1 + t2 );
00206
00207 path.cubicTo( cp1, cp2, pN );
00208 path.cubicTo( cp3, cp4, p0 );
00209 }
00210
00211 return path;
00212 }
00213
00215 QwtSplineBasis::QwtSplineBasis()
00216 {
00217 }
00218
00220 QwtSplineBasis::~QwtSplineBasis()
00221 {
00222 }
00223
00225 uint QwtSplineBasis::locality() const
00226 {
00227 return 2;
00228 }
00229
00237 QPainterPath QwtSplineBasis::painterPath( const QPolygonF &points ) const
00238 {
00239 if ( points.size() < 4 )
00240 return QPainterPath();
00241
00242 QPainterPath path;
00243
00244 switch( parametrization()->type() )
00245 {
00246 case QwtSplineParametrization::ParameterUniform:
00247 {
00248 path = qwtSplineBasisPathUniform( points, boundaryType() );
00249 break;
00250 }
00251 default:
00252 {
00253 path = qwtSplineBasisPath( points, parametrization(), boundaryType() );
00254 }
00255 }
00256
00257 return path;
00258 }