# qwt_curve_fitter.cpp

    00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
    00002  * Qwt Widget Library
    00003  * Copyright (C) 1997   Josef Wilgen
    00004  * Copyright (C) 2002   Uwe Rathmann
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the Qwt License, Version 1.0
    00008  *****************************************************************************/
    00009
    00010 #include "qwt_math.h"
    00011 #include "qwt_spline.h"
    00012 #include "qwt_curve_fitter.h"
    00013
    00015 QwtCurveFitter::QwtCurveFitter()
    00016 {
    00017 }
    00018
    00020 QwtCurveFitter::~QwtCurveFitter()
    00021 {
    00022 }
    00023
    00024 class QwtSplineCurveFitter::PrivateData
    00025 {
    00026 public:
    00027     PrivateData():
    00028         fitMode(QwtSplineCurveFitter::Auto),
    00029         splineSize(250)
    00030     {
    00031     }
    00032
    00033     QwtSpline spline;
    00034     QwtSplineCurveFitter::FitMode fitMode;
    00035     int splineSize;
    00036 };
    00037
    00038 QwtSplineCurveFitter::QwtSplineCurveFitter()
    00039 {
    00040     d_data = new PrivateData;
    00041 }
    00042
    00043 QwtSplineCurveFitter::~QwtSplineCurveFitter()
    00044 {
    00045     delete d_data;
    00046 }
    00047
    00048 void QwtSplineCurveFitter::setFitMode(FitMode mode)
    00049 {
    00050     d_data->fitMode = mode;
    00051 }
    00052
    00053 QwtSplineCurveFitter::FitMode QwtSplineCurveFitter::fitMode() const
    00054 {
    00055     return d_data->fitMode;
    00056 }
    00057
    00058 void QwtSplineCurveFitter::setSpline(const QwtSpline &spline)
    00059 {
    00060     d_data->spline = spline;
    00061     d_data->spline.reset();
    00062 }
    00063
    00064 const QwtSpline &QwtSplineCurveFitter::spline() const
    00065 {
    00066     return d_data->spline;
    00067 }
    00068
    00069 QwtSpline &QwtSplineCurveFitter::spline()
    00070 {
    00071     return d_data->spline;
    00072 }
    00073
    00074 void QwtSplineCurveFitter::setSplineSize(int splineSize)
    00075 {
    00076     d_data->splineSize = qwtMax(splineSize, 10);
    00077 }
    00078
    00079 int QwtSplineCurveFitter::splineSize() const
    00080 {
    00081     return d_data->splineSize;
    00082 }
    00083
    00084 #if QT_VERSION < 0x040000
    00085 QwtArray<QwtDoublePoint> QwtSplineCurveFitter::fitCurve(
    00086     const QwtArray<QwtDoublePoint> & points) const
    00087 #else
    00088 QPolygonF QwtSplineCurveFitter::fitCurve(
    00089     const QPolygonF &points) const
    00090 #endif
    00091 {
    00092     const int size = (int)points.size();
    00093     if ( size <= 2 )
    00094         return points;
    00095
    00096     FitMode fitMode = d_data->fitMode;
    00097     if ( fitMode == Auto )
    00098     {
    00099         fitMode = Spline;
    00100
    00101         const QwtDoublePoint *p = points.data();
    00102         for ( int i = 1; i < size; i++ )
    00103         {
    00104             if ( p[i].x() <= p[i-1].x() )
    00105             {
    00106                 fitMode = ParametricSpline;
    00107                 break;
    00108             }
    00109         };
    00110     }
    00111
    00112     if ( fitMode == ParametricSpline )
    00113         return fitParametric(points);
    00114     else
    00115         return fitSpline(points);
    00116 }
    00117
    00118 #if QT_VERSION < 0x040000
    00119 QwtArray<QwtDoublePoint> QwtSplineCurveFitter::fitSpline(
    00120     const QwtArray<QwtDoublePoint> &points) const
    00121 #else
    00122 QPolygonF QwtSplineCurveFitter::fitSpline(
    00123     const QPolygonF &points) const
    00124 #endif
    00125 {
    00126     d_data->spline.setPoints(points);
    00127     if ( !d_data->spline.isValid() )
    00128         return points;
    00129
    00130 #if QT_VERSION < 0x040000
    00131     QwtArray<QwtDoublePoint> fittedPoints(d_data->splineSize);
    00132 #else
    00133     QPolygonF fittedPoints(d_data->splineSize);
    00134 #endif
    00135
    00136     const double x1 = points[0].x();
    00137     const double x2 = points[int(points.size() - 1)].x();
    00138     const double dx = x2 - x1;
    00139     const double delta = dx / (d_data->splineSize - 1);
    00140
    00141     for (int i = 0; i < d_data->splineSize; i++)
    00142     {
    00143         QwtDoublePoint &p = fittedPoints[i];
    00144
    00145         const double v = x1 + i * delta;
    00146         const double sv = d_data->spline.value(v);
    00147
    00148         p.setX(qRound(v));
    00149         p.setY(qRound(sv));
    00150     }
    00151     d_data->spline.reset();
    00152
    00153     return fittedPoints;
    00154 }
    00155
    00156 #if QT_VERSION < 0x040000
    00157 QwtArray<QwtDoublePoint> QwtSplineCurveFitter::fitParametric(
    00158     const QwtArray<QwtDoublePoint> &points) const
    00159 #else
    00160 QPolygonF QwtSplineCurveFitter::fitParametric(
    00161     const QPolygonF &points) const
    00162 #endif
    00163 {
    00164     int i;
    00165     const int size = points.size();
    00166
    00167 #if QT_VERSION < 0x040000
    00168     QwtArray<QwtDoublePoint> fittedPoints(d_data->splineSize);
    00169     QwtArray<QwtDoublePoint> splinePointsX(size);
    00170     QwtArray<QwtDoublePoint> splinePointsY(size);
    00171 #else
    00172     QPolygonF fittedPoints(d_data->splineSize);
    00173     QPolygonF splinePointsX(size);
    00174     QPolygonF splinePointsY(size);
    00175 #endif
    00176
    00177     const QwtDoublePoint *p = points.data();
    00178     QwtDoublePoint *spX = splinePointsX.data();
    00179     QwtDoublePoint *spY = splinePointsY.data();
    00180
    00181     double param = 0.0;
    00182     for (i = 0; i < size; i++)
    00183     {
    00184         const double x = p[i].x();
    00185         const double y = p[i].y();
    00186         if ( i > 0 )
    00187         {
    00188             const double delta = sqrt( qwtSqr(x - spX[i-1].y())
    00189                       + qwtSqr( y - spY[i-1].y() ) );
    00190             param += qwtMax(delta, 1.0);
    00191         }
    00192         spX[i].setX(param);
    00193         spX[i].setY(x);
    00194         spY[i].setX(param);
    00195         spY[i].setY(y);
    00196     }
    00197
    00198     d_data->spline.setPoints(splinePointsX);
    00199     if ( !d_data->spline.isValid() )
    00200         return points;
    00201
    00202     const double deltaX =
    00203         splinePointsX[size - 1].x() / (d_data->splineSize-1);
    00204     for (i = 0; i < d_data->splineSize; i++)
    00205     {
    00206         const double dtmp = i * deltaX;
    00207         fittedPoints[i].setX(qRound(d_data->spline.value(dtmp)));
    00208     }
    00209
    00210     d_data->spline.setPoints(splinePointsY);
    00211     if ( !d_data->spline.isValid() )
    00212         return points;
    00213
    00214     const double deltaY =
    00215         splinePointsY[size - 1].x() / (d_data->splineSize-1);
    00216     for (i = 0; i < d_data->splineSize; i++)
    00217     {
    00218         const double dtmp = i * deltaY;
    00219         fittedPoints[i].setY(qRound(d_data->spline.value(dtmp)));
    00220     }
    00221
    00222     return fittedPoints;
    00223 }