00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_spline.h"
00011 #include "qwt_spline_parametrization.h"
00012 #include "qwt_bezier.h"
00013 #include "qwt_math.h"
00014
00015 namespace QwtSplineC1P
00016 {
00017 struct param
00018 {
00019 param( const QwtSplineParametrization *p ):
00020 parameter( p )
00021 {
00022 }
00023
00024 inline double operator()( const QPointF &p1, const QPointF &p2 ) const
00025 {
00026 return parameter->valueIncrement( p1, p2 );
00027 }
00028
00029 const QwtSplineParametrization *parameter;
00030 };
00031
00032 struct paramY
00033 {
00034 inline double operator()( const QPointF &p1, const QPointF &p2 ) const
00035 {
00036 return QwtSplineParametrization::valueIncrementY( p1, p2 );
00037 }
00038 };
00039
00040 struct paramUniform
00041 {
00042 inline double operator()( const QPointF &p1, const QPointF &p2 ) const
00043 {
00044 return QwtSplineParametrization::valueIncrementUniform( p1, p2 );
00045 }
00046 };
00047
00048 struct paramCentripetal
00049 {
00050 inline double operator()( const QPointF &p1, const QPointF &p2 ) const
00051 {
00052 return QwtSplineParametrization::valueIncrementCentripetal( p1, p2 );
00053 }
00054 };
00055
00056 struct paramChordal
00057 {
00058 inline double operator()( const QPointF &p1, const QPointF &p2 ) const
00059 {
00060 return QwtSplineParametrization::valueIncrementChordal( p1, p2 );
00061 }
00062 };
00063
00064 struct paramManhattan
00065 {
00066 inline double operator()( const QPointF &p1, const QPointF &p2 ) const
00067 {
00068 return QwtSplineParametrization::valueIncrementManhattan( p1, p2 );
00069 }
00070 };
00071
00072 class PathStore
00073 {
00074 public:
00075 inline void init( int size )
00076 {
00077 Q_UNUSED(size);
00078 }
00079
00080 inline void start( double x1, double y1 )
00081 {
00082 path.moveTo( x1, y1 );
00083 }
00084
00085 inline void addCubic( double cx1, double cy1,
00086 double cx2, double cy2, double x2, double y2 )
00087 {
00088 path.cubicTo( cx1, cy1, cx2, cy2, x2, y2 );
00089 }
00090
00091 inline void end()
00092 {
00093 path.closeSubpath();
00094 }
00095
00096 QPainterPath path;
00097 };
00098
00099 class ControlPointsStore
00100 {
00101 public:
00102 inline ControlPointsStore():
00103 d_cp( NULL )
00104 {
00105 }
00106
00107 inline void init( int size )
00108 {
00109 controlPoints.resize( size );
00110 d_cp = controlPoints.data();
00111 }
00112
00113 inline void start( double x1, double y1 )
00114 {
00115 Q_UNUSED( x1 );
00116 Q_UNUSED( y1 );
00117 }
00118
00119 inline void addCubic( double cx1, double cy1,
00120 double cx2, double cy2, double x2, double y2 )
00121 {
00122 Q_UNUSED( x2 );
00123 Q_UNUSED( y2 );
00124
00125 QLineF &l = *d_cp++;
00126 l.setLine( cx1, cy1, cx2, cy2 );
00127 }
00128
00129 inline void end()
00130 {
00131 }
00132
00133 QVector<QLineF> controlPoints;
00134
00135 private:
00136 QLineF* d_cp;
00137 };
00138
00139 double slopeBoundary( int boundaryCondition, double boundaryValue,
00140 const QPointF &p1, const QPointF &p2, double slope1 )
00141 {
00142 const double dx = p2.x() - p1.x();
00143 const double dy = p2.y() - p1.y();
00144
00145 double m = 0.0;
00146
00147 switch( boundaryCondition )
00148 {
00149 case QwtSpline::Clamped1:
00150 {
00151 m = boundaryValue;
00152 break;
00153 }
00154 case QwtSpline::Clamped2:
00155 {
00156 const double c2 = 0.5 * boundaryValue;
00157 const double c1 = slope1;
00158
00159 m = 0.5 * ( 3.0 * dy / dx - c1 - c2 * dx );
00160 break;
00161 }
00162 case QwtSpline::Clamped3:
00163 {
00164 const double c3 = boundaryValue / 6.0;
00165 m = c3 * dx * dx + 2 * dy / dx - slope1;
00166 break;
00167 }
00168 case QwtSpline::LinearRunout:
00169 {
00170 const double s = dy / dx;
00171 const double r = qBound( 0.0, boundaryValue, 1.0 );
00172
00173 m = s - r * ( s - slope1 );
00174 break;
00175 }
00176 default:
00177 {
00178 m = dy / dx;
00179 }
00180 }
00181
00182 return m;
00183 }
00184 }
00185
00186 template< class SplineStore >
00187 static inline SplineStore qwtSplineC1PathParamX(
00188 const QwtSplineC1 *spline, const QPolygonF &points )
00189 {
00190 const int n = points.size();
00191
00192 const QVector<double> m = spline->slopes( points );
00193 if ( m.size() != n )
00194 return SplineStore();
00195
00196 const QPointF *pd = points.constData();
00197 const double *md = m.constData();
00198
00199 SplineStore store;
00200 store.init( m.size() - 1 );
00201 store.start( pd[0].x(), pd[0].y() );
00202
00203 for ( int i = 0; i < n - 1; i++ )
00204 {
00205 const double dx3 = ( pd[i+1].x() - pd[i].x() ) / 3.0;
00206
00207 store.addCubic( pd[i].x() + dx3, pd[i].y() + md[i] * dx3,
00208 pd[i+1].x() - dx3, pd[i+1].y() - md[i+1] * dx3,
00209 pd[i+1].x(), pd[i+1].y() );
00210 }
00211
00212 return store;
00213 }
00214
00215 template< class SplineStore >
00216 static inline SplineStore qwtSplineC1PathParamY(
00217 const QwtSplineC1 *spline, const QPolygonF &points )
00218 {
00219 const int n = points.size();
00220
00221 QPolygonF pointsFlipped( n );
00222 for ( int i = 0; i < n; i++ )
00223 {
00224 pointsFlipped[i].setX( points[i].y() );
00225 pointsFlipped[i].setY( points[i].x() );
00226 }
00227
00228 const QVector<double> m = spline->slopes( pointsFlipped );
00229 if ( m.size() != n )
00230 return SplineStore();
00231
00232 const QPointF *pd = pointsFlipped.constData();
00233 const double *md = m.constData();
00234
00235 SplineStore store;
00236 store.init( m.size() - 1 );
00237 store.start( pd[0].y(), pd[0].x() );
00238
00239 QVector<QLineF> lines( n );
00240 for ( int i = 0; i < n - 1; i++ )
00241 {
00242 const double dx3 = ( pd[i+1].x() - pd[i].x() ) / 3.0;
00243
00244 store.addCubic( pd[i].y() + md[i] * dx3, pd[i].x() + dx3,
00245 pd[i+1].y() - md[i+1] * dx3, pd[i+1].x() - dx3,
00246 pd[i+1].y(), pd[i+1].x() );
00247 }
00248
00249 return store;
00250 }
00251
00252 template< class SplineStore, class Param >
00253 static inline SplineStore qwtSplineC1PathParametric(
00254 const QwtSplineC1 *spline, const QPolygonF &points, Param param )
00255 {
00256 const bool isClosing = ( spline->boundaryType() == QwtSpline::ClosedPolygon );
00257 const int n = points.size();
00258
00259 QPolygonF pointsX, pointsY;
00260 pointsX.resize( isClosing ? n + 1 : n );
00261 pointsY.resize( isClosing ? n + 1 : n );
00262
00263 QPointF *px = pointsX.data();
00264 QPointF *py = pointsY.data();
00265 const QPointF *p = points.constData();
00266
00267 double t = 0.0;
00268
00269 px[0].rx() = py[0].rx() = t;
00270 px[0].ry() = p[0].x();
00271 py[0].ry() = p[0].y();
00272
00273 int numParamPoints = 1;
00274 for ( int i = 1; i < n; i++ )
00275 {
00276 const double td = param( points[i-1], points[i] );
00277 if ( td > 0.0 )
00278 {
00279 t += td;
00280
00281 px[numParamPoints].rx() = py[numParamPoints].rx() = t;
00282
00283 px[numParamPoints].ry() = p[i].x();
00284 py[numParamPoints].ry() = p[i].y();
00285
00286 numParamPoints++;
00287 }
00288 }
00289
00290 if ( isClosing )
00291 {
00292 const double td = param( points[n-1], points[0] );
00293
00294 if ( td > 0.0 )
00295 {
00296 t += td;
00297
00298 px[numParamPoints].rx() = py[numParamPoints].rx() = t;
00299
00300 px[numParamPoints].ry() = p[0].x();
00301 py[numParamPoints].ry() = p[0].y();
00302
00303 numParamPoints++;
00304 }
00305 }
00306
00307 if ( pointsX.size() != numParamPoints )
00308 {
00309 pointsX.resize( numParamPoints );
00310 pointsY.resize( numParamPoints );
00311 }
00312
00313 const QVector<double> slopesX = spline->slopes( pointsX );
00314 const QVector<double> slopesY = spline->slopes( pointsY );
00315
00316 const double *mx = slopesX.constData();
00317 const double *my = slopesY.constData();
00318
00319
00320 pointsX.clear();
00321 pointsY.clear();
00322
00323 SplineStore store;
00324 store.init( isClosing ? n : n - 1 );
00325 store.start( points[0].x(), points[0].y() );
00326
00327 int j = 0;
00328
00329 for ( int i = 0; i < n - 1; i++ )
00330 {
00331 const QPointF &p1 = p[i];
00332 const QPointF &p2 = p[i+1];
00333
00334 const double td = param( p1, p2 );
00335
00336 if ( td != 0.0 )
00337 {
00338 const double t3 = td / 3.0;
00339
00340 const double cx1 = p1.x() + mx[j] * t3;
00341 const double cy1 = p1.y() + my[j] * t3;
00342
00343 const double cx2 = p2.x() - mx[j+1] * t3;
00344 const double cy2 = p2.y() - my[j+1] * t3;
00345
00346 store.addCubic( cx1, cy1, cx2, cy2, p2.x(), p2.y() );
00347
00348 j++;
00349 }
00350 else
00351 {
00352
00353 store.addCubic( p1.x(), p1.y(), p2.x(), p2.y(), p2.x(), p2.y() );
00354 }
00355 }
00356
00357 if ( isClosing )
00358 {
00359 const QPointF &p1 = p[n-1];
00360 const QPointF &p2 = p[0];
00361
00362 const double td = param( p1, p2 );
00363
00364 if ( td != 0.0 )
00365 {
00366 const double t3 = td / 3.0;
00367
00368 const double cx1 = p1.x() + mx[j] * t3;
00369 const double cy1 = p1.y() + my[j] * t3;
00370
00371 const double cx2 = p2.x() - mx[0] * t3;
00372 const double cy2 = p2.y() - my[0] * t3;
00373
00374 store.addCubic( cx1, cy1, cx2, cy2, p2.x(), p2.y() );
00375 }
00376 else
00377 {
00378 store.addCubic( p1.x(), p1.y(), p2.x(), p2.y(), p2.x(), p2.y() );
00379 }
00380
00381 store.end();
00382 }
00383
00384 return store;
00385 }
00386
00387 template< QwtSplinePolynomial toPolynomial( const QPointF &, double, const QPointF &, double ) >
00388 static QPolygonF qwtPolygonParametric( double distance,
00389 const QPolygonF &points, const QVector<double> values, bool withNodes )
00390 {
00391 QPolygonF fittedPoints;
00392
00393 const QPointF *p = points.constData();
00394 const double *v = values.constData();
00395
00396 fittedPoints += p[0];
00397 double t = distance;
00398
00399 const int n = points.size();
00400
00401 for ( int i = 0; i < n - 1; i++ )
00402 {
00403 const QPointF &p1 = p[i];
00404 const QPointF &p2 = p[i+1];
00405
00406 const QwtSplinePolynomial polynomial = toPolynomial( p1, v[i], p2, v[i+1] );
00407
00408 const double l = p2.x() - p1.x();
00409
00410 while ( t < l )
00411 {
00412 fittedPoints += QPointF( p1.x() + t, p1.y() + polynomial.valueAt( t ) );
00413 t += distance;
00414 }
00415
00416 if ( withNodes )
00417 {
00418 if ( qFuzzyCompare( fittedPoints.last().x(), p2.x() ) )
00419 fittedPoints.last() = p2;
00420 else
00421 fittedPoints += p2;
00422 }
00423 else
00424 {
00425 t -= l;
00426 }
00427 }
00428
00429 return fittedPoints;
00430 }
00431
00432 class QwtSpline::PrivateData
00433 {
00434 public:
00435 PrivateData():
00436 boundaryType( QwtSpline::ConditionalBoundaries )
00437 {
00438 parametrization = new QwtSplineParametrization(
00439 QwtSplineParametrization::ParameterChordal );
00440
00441
00442
00443 boundaryConditions[0].type = QwtSpline::Clamped3;
00444 boundaryConditions[0].value = 0.0;
00445
00446 boundaryConditions[1].type = QwtSpline::Clamped3;
00447 boundaryConditions[1].value = 0.0;
00448 }
00449
00450 ~PrivateData()
00451 {
00452 delete parametrization;
00453 }
00454
00455 QwtSplineParametrization *parametrization;
00456 QwtSpline::BoundaryType boundaryType;
00457
00458 struct
00459 {
00460 int type;
00461 double value;
00462
00463 } boundaryConditions[2];
00464 };
00465
00494 QPolygonF QwtSpline::polygon( const QPolygonF &points, double tolerance ) const
00495 {
00496 if ( tolerance <= 0.0 )
00497 return QPolygonF();
00498
00499 const QPainterPath path = painterPath( points );
00500 const int n = path.elementCount();
00501 if ( n == 0 )
00502 return QPolygonF();
00503
00504 const QPainterPath::Element el = path.elementAt( 0 );
00505 if ( el.type != QPainterPath::MoveToElement )
00506 return QPolygonF();
00507
00508 QPointF p1( el.x, el.y );
00509
00510 QPolygonF polygon;
00511 QwtBezier bezier( tolerance );
00512
00513 for ( int i = 1; i < n; i += 3 )
00514 {
00515 const QPainterPath::Element el1 = path.elementAt( i );
00516 const QPainterPath::Element el2 = path.elementAt( i + 1 );
00517 const QPainterPath::Element el3 = path.elementAt( i + 2 );
00518
00519 const QPointF cp1( el1.x, el1.y );
00520 const QPointF cp2( el2.x, el2.y );
00521 const QPointF p2( el3.x, el3.y );
00522
00523 bezier.appendToPolygon( p1, cp1, cp2, p2, polygon );
00524
00525 p1 = p2;
00526 }
00527
00528 return polygon;
00529 }
00530
00538 QwtSpline::QwtSpline()
00539 {
00540 d_data = new PrivateData;
00541 }
00542
00544 QwtSpline::~QwtSpline()
00545 {
00546 delete d_data;
00547 }
00548
00562 uint QwtSpline::locality() const
00563 {
00564 return 0;
00565 }
00566
00574 void QwtSpline::setParametrization( int type )
00575 {
00576 if ( d_data->parametrization->type() != type )
00577 {
00578 delete d_data->parametrization;
00579 d_data->parametrization = new QwtSplineParametrization( type );
00580 }
00581 }
00582
00590 void QwtSpline::setParametrization( QwtSplineParametrization *parametrization )
00591 {
00592 if ( ( parametrization != NULL ) && ( d_data->parametrization != parametrization ) )
00593 {
00594 delete d_data->parametrization;
00595 d_data->parametrization = parametrization;
00596 }
00597 }
00598
00603 const QwtSplineParametrization *QwtSpline::parametrization() const
00604 {
00605 return d_data->parametrization;
00606 }
00607
00615 void QwtSpline::setBoundaryType( BoundaryType boundaryType )
00616 {
00617 d_data->boundaryType = boundaryType;
00618 }
00619
00624 QwtSpline::BoundaryType QwtSpline::boundaryType() const
00625 {
00626 return d_data->boundaryType;
00627 }
00628
00637 void QwtSpline::setBoundaryCondition( BoundaryPosition position, int condition )
00638 {
00639 if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
00640 d_data->boundaryConditions[position].type = condition;
00641 }
00642
00649 int QwtSpline::boundaryCondition( BoundaryPosition position ) const
00650 {
00651 if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
00652 return d_data->boundaryConditions[position].type;
00653
00654 return d_data->boundaryConditions[0].type;
00655 }
00656
00668 void QwtSpline::setBoundaryValue( BoundaryPosition position, double value )
00669 {
00670 if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
00671 d_data->boundaryConditions[position].value = value;
00672 }
00673
00680 double QwtSpline::boundaryValue( BoundaryPosition position ) const
00681 {
00682 if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
00683 return d_data->boundaryConditions[position].value;
00684
00685 return d_data->boundaryConditions[0].value;
00686 }
00687
00698 void QwtSpline::setBoundaryConditions(
00699 int condition, double valueBegin, double valueEnd )
00700 {
00701 setBoundaryCondition( QwtSpline::AtBeginning, condition );
00702 setBoundaryValue( QwtSpline::AtBeginning, valueBegin );
00703
00704 setBoundaryCondition( QwtSpline::AtEnd, condition );
00705 setBoundaryValue( QwtSpline::AtEnd, valueEnd );
00706 }
00707
00709 QwtSplineInterpolating::QwtSplineInterpolating()
00710 {
00711 }
00712
00714 QwtSplineInterpolating::~QwtSplineInterpolating()
00715 {
00716 }
00717
00746 QPainterPath QwtSplineInterpolating::painterPath( const QPolygonF &points ) const
00747 {
00748 const int n = points.size();
00749
00750 QPainterPath path;
00751 if ( n == 0 )
00752 return path;
00753
00754 if ( n == 1 )
00755 {
00756 path.moveTo( points[0] );
00757 return path;
00758 }
00759
00760 if ( n == 2 )
00761 {
00762 path.addPolygon( points );
00763 return path;
00764 }
00765
00766 const QVector<QLineF> controlLines = bezierControlLines( points );
00767 if ( controlLines.size() < n - 1 )
00768 return path;
00769
00770 const QPointF *p = points.constData();
00771 const QLineF *l = controlLines.constData();
00772
00773 path.moveTo( p[0] );
00774 for ( int i = 0; i < n - 1; i++ )
00775 path.cubicTo( l[i].p1(), l[i].p2(), p[i+1] );
00776
00777 if ( ( boundaryType() == QwtSpline::ClosedPolygon )
00778 && ( controlLines.size() >= n ) )
00779 {
00780 path.cubicTo( l[n-1].p1(), l[n-1].p2(), p[0] );
00781 path.closeSubpath();
00782 }
00783
00784 return path;
00785 }
00786
00803 QPolygonF QwtSplineInterpolating::polygon(
00804 const QPolygonF &points, double tolerance ) const
00805 {
00806 if ( tolerance <= 0.0 )
00807 return QPolygonF();
00808
00809 const QVector<QLineF> controlLines = bezierControlLines( points );
00810 if ( controlLines.isEmpty() )
00811 return QPolygonF();
00812
00813 const bool isClosed = boundaryType() == QwtSpline::ClosedPolygon;
00814
00815 QwtBezier bezier( tolerance );
00816
00817 const QPointF *p = points.constData();
00818 const QLineF *cl = controlLines.constData();
00819
00820 const int n = controlLines.size();
00821
00822 QPolygonF polygon;
00823
00824 for ( int i = 0; i < n - 1; i++ )
00825 {
00826 const QLineF &l = cl[i];
00827 bezier.appendToPolygon( p[i], l.p1(), l.p2(), p[i+1], polygon );
00828 }
00829
00830 const QPointF &pn = isClosed ? p[0] : p[n];
00831 const QLineF &l = cl[n-1];
00832
00833 bezier.appendToPolygon( p[n-1], l.p1(), l.p2(), pn, polygon );
00834
00835 return polygon;
00836 }
00837
00861 QPolygonF QwtSplineInterpolating::equidistantPolygon( const QPolygonF &points,
00862 double distance, bool withNodes ) const
00863 {
00864 if ( distance <= 0.0 )
00865 return QPolygonF();
00866
00867 const int n = points.size();
00868 if ( n <= 1 )
00869 return points;
00870
00871 if ( n == 2 )
00872 {
00873
00874 return points;
00875 }
00876
00877 QPolygonF path;
00878
00879 const QVector<QLineF> controlLines = bezierControlLines( points );
00880
00881 if ( controlLines.size() < n - 1 )
00882 return path;
00883
00884 path += points.first();
00885 double t = distance;
00886
00887 const QPointF *p = points.constData();
00888 const QLineF *cl = controlLines.constData();
00889
00890 const QwtSplineParametrization *param = parametrization();
00891
00892 for ( int i = 0; i < n - 1; i++ )
00893 {
00894 const double l = param->valueIncrement( p[i], p[i+1] );
00895
00896 while ( t < l )
00897 {
00898 path += QwtBezier::pointAt( p[i], cl[i].p1(),
00899 cl[i].p2(), p[i+1], t / l );
00900
00901 t += distance;
00902 }
00903
00904 if ( withNodes )
00905 {
00906 if ( qFuzzyCompare( path.last().x(), p[i+1].x() ) )
00907 path.last() = p[i+1];
00908 else
00909 path += p[i+1];
00910
00911 t = distance;
00912 }
00913 else
00914 {
00915 t -= l;
00916 }
00917 }
00918
00919 if ( ( boundaryType() == QwtSpline::ClosedPolygon )
00920 && ( controlLines.size() >= n ) )
00921 {
00922 const double l = param->valueIncrement( p[n-1], p[0] );
00923
00924 while ( t < l )
00925 {
00926 path += QwtBezier::pointAt( p[n-1], cl[n-1].p1(),
00927 cl[n-1].p2(), p[0], t / l );
00928
00929 t += distance;
00930 }
00931
00932 if ( qFuzzyCompare( path.last().x(), p[0].x() ) )
00933 path.last() = p[0];
00934 else
00935 path += p[0];
00936 }
00937
00938 return path;
00939 }
00940
00942 QwtSplineG1::QwtSplineG1()
00943 {
00944 }
00945
00947 QwtSplineG1::~QwtSplineG1()
00948 {
00949 }
00950
00960 QwtSplineC1::QwtSplineC1()
00961 {
00962 setParametrization( QwtSplineParametrization::ParameterX );
00963 }
00964
00966 QwtSplineC1::~QwtSplineC1()
00967 {
00968 }
00969
00977 double QwtSplineC1::slopeAtBeginning( const QPolygonF &points, double slopeNext ) const
00978 {
00979 if ( points.size() < 2 )
00980 return 0.0;
00981
00982 return QwtSplineC1P::slopeBoundary(
00983 boundaryCondition( QwtSpline::AtBeginning ),
00984 boundaryValue( QwtSpline::AtBeginning ),
00985 points[0], points[1], slopeNext );
00986 }
00987
00995 double QwtSplineC1::slopeAtEnd( const QPolygonF &points, double slopeBefore ) const
00996 {
00997 const int n = points.size();
00998
00999 const QPointF p1( points[n-1].x(), -points[n-1].y() );
01000 const QPointF p2( points[n-2].x(), -points[n-2].y() );
01001
01002 const int condition = boundaryCondition( QwtSpline::AtEnd );
01003
01004 double value = boundaryValue( QwtSpline::AtEnd );
01005 if ( condition != QwtSpline::LinearRunout )
01006 {
01007
01008
01009 value = -value;
01010 }
01011
01012 const double slope = QwtSplineC1P::slopeBoundary( condition, value, p1, p2, -slopeBefore );
01013 return -slope;
01014 }
01015
01041 QPainterPath QwtSplineC1::painterPath( const QPolygonF &points ) const
01042 {
01043 const int n = points.size();
01044 if ( n <= 2 )
01045 return QwtSplineInterpolating::painterPath( points );
01046
01047 using namespace QwtSplineC1P;
01048
01049 PathStore store;
01050 switch( parametrization()->type() )
01051 {
01052 case QwtSplineParametrization::ParameterX:
01053 {
01054 store = qwtSplineC1PathParamX<PathStore>( this, points );
01055 break;
01056 }
01057 case QwtSplineParametrization::ParameterY:
01058 {
01059 store = qwtSplineC1PathParamY<PathStore>( this, points );
01060 break;
01061 }
01062 case QwtSplineParametrization::ParameterUniform:
01063 {
01064 store = qwtSplineC1PathParametric<PathStore>(
01065 this, points, paramUniform() );
01066 break;
01067 }
01068 case QwtSplineParametrization::ParameterCentripetal:
01069 {
01070 store = qwtSplineC1PathParametric<PathStore>(
01071 this, points, paramCentripetal() );
01072 break;
01073 }
01074 case QwtSplineParametrization::ParameterChordal:
01075 {
01076 store = qwtSplineC1PathParametric<PathStore>(
01077 this, points, paramChordal() );
01078 break;
01079 }
01080 default:
01081 {
01082 store = qwtSplineC1PathParametric<PathStore>(
01083 this, points, param( parametrization() ) );
01084 }
01085 }
01086
01087 return store.path;
01088 }
01089
01099 QVector<QLineF> QwtSplineC1::bezierControlLines( const QPolygonF &points ) const
01100 {
01101 using namespace QwtSplineC1P;
01102
01103 const int n = points.size();
01104 if ( n <= 2 )
01105 return QVector<QLineF>();
01106
01107 ControlPointsStore store;
01108 switch( parametrization()->type() )
01109 {
01110 case QwtSplineParametrization::ParameterX:
01111 {
01112 store = qwtSplineC1PathParamX<ControlPointsStore>( this, points );
01113 break;
01114 }
01115 case QwtSplineParametrization::ParameterY:
01116 {
01117 store = qwtSplineC1PathParamY<ControlPointsStore>( this, points );
01118 break;
01119 }
01120 case QwtSplineParametrization::ParameterUniform:
01121 {
01122 store = qwtSplineC1PathParametric<ControlPointsStore>(
01123 this, points, paramUniform() );
01124 break;
01125 }
01126 case QwtSplineParametrization::ParameterCentripetal:
01127 {
01128 store = qwtSplineC1PathParametric<ControlPointsStore>(
01129 this, points, paramCentripetal() );
01130 break;
01131 }
01132 case QwtSplineParametrization::ParameterChordal:
01133 {
01134 store = qwtSplineC1PathParametric<ControlPointsStore>(
01135 this, points, paramChordal() );
01136 break;
01137 }
01138 default:
01139 {
01140 store = qwtSplineC1PathParametric<ControlPointsStore>(
01141 this, points, param( parametrization() ) );
01142 }
01143 }
01144
01145 return store.controlPoints;
01146 }
01147
01165 QPolygonF QwtSplineC1::equidistantPolygon( const QPolygonF &points,
01166 double distance, bool withNodes ) const
01167 {
01168 if ( parametrization()->type() == QwtSplineParametrization::ParameterX )
01169 {
01170 if ( points.size() > 2 )
01171 {
01172 const QVector<double> m = slopes( points );
01173 if ( m.size() != points.size() )
01174 return QPolygonF();
01175
01176 return qwtPolygonParametric<QwtSplinePolynomial::fromSlopes>(
01177 distance, points, m, withNodes );
01178 }
01179 }
01180
01181 return QwtSplineInterpolating::equidistantPolygon( points, distance, withNodes );
01182 }
01183
01199 QVector<QwtSplinePolynomial> QwtSplineC1::polynomials(
01200 const QPolygonF &points ) const
01201 {
01202 QVector<QwtSplinePolynomial> polynomials;
01203
01204 const QVector<double> m = slopes( points );
01205 if ( m.size() < 2 )
01206 return polynomials;
01207
01208 for ( int i = 1; i < m.size(); i++ )
01209 {
01210 polynomials += QwtSplinePolynomial::fromSlopes(
01211 points[i-1], m[i-1], points[i], m[i] );
01212 }
01213
01214 return polynomials;
01215 }
01216
01225 QwtSplineC2::QwtSplineC2()
01226 {
01227 }
01228
01230 QwtSplineC2::~QwtSplineC2()
01231 {
01232 }
01233
01246 QPainterPath QwtSplineC2::painterPath( const QPolygonF &points ) const
01247 {
01248
01249
01250
01251 return QwtSplineC1::painterPath( points );
01252 }
01253
01267 QVector<QLineF> QwtSplineC2::bezierControlLines( const QPolygonF &points ) const
01268 {
01269
01270
01271
01272 return QwtSplineC1::bezierControlLines( points );
01273 }
01274
01292 QPolygonF QwtSplineC2::equidistantPolygon( const QPolygonF &points,
01293 double distance, bool withNodes ) const
01294 {
01295 if ( parametrization()->type() == QwtSplineParametrization::ParameterX )
01296 {
01297 if ( points.size() > 2 )
01298 {
01299 const QVector<double> cv = curvatures( points );
01300 if ( cv.size() != points.size() )
01301 return QPolygonF();
01302
01303 return qwtPolygonParametric<QwtSplinePolynomial::fromCurvatures>(
01304 distance, points, cv, withNodes );
01305 }
01306 }
01307
01308 return QwtSplineInterpolating::equidistantPolygon( points, distance, withNodes );
01309 }
01310
01336 QVector<double> QwtSplineC2::slopes( const QPolygonF &points ) const
01337 {
01338 const QVector<double> curvatures = this->curvatures( points );
01339 if ( curvatures.size() < 2 )
01340 return QVector<double>();
01341
01342 QVector<double> slopes( curvatures.size() );
01343
01344 const double *cv = curvatures.constData();
01345 double *m = slopes.data();
01346
01347 const int n = points.size();
01348 const QPointF *p = points.constData();
01349
01350 QwtSplinePolynomial polynomial;
01351
01352 for ( int i = 0; i < n - 1; i++ )
01353 {
01354 polynomial = QwtSplinePolynomial::fromCurvatures( p[i], cv[i], p[i+1], cv[i+1] );
01355 m[i] = polynomial.c1;
01356 }
01357
01358 m[n-1] = polynomial.slopeAt( p[n-1].x() - p[n-2].x() );
01359
01360 return slopes;
01361 }
01362
01378 QVector<QwtSplinePolynomial> QwtSplineC2::polynomials( const QPolygonF &points ) const
01379 {
01380 QVector<QwtSplinePolynomial> polynomials;
01381
01382 const QVector<double> curvatures = this->curvatures( points );
01383 if ( curvatures.size() < 2 )
01384 return polynomials;
01385
01386 const QPointF *p = points.constData();
01387 const double *cv = curvatures.constData();
01388 const int n = curvatures.size();
01389
01390 for ( int i = 1; i < n; i++ )
01391 {
01392 polynomials += QwtSplinePolynomial::fromCurvatures(
01393 p[i-1], cv[i-1], p[i], cv[i] );
01394 }
01395
01396 return polynomials;
01397 }