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 }

Generated on Mon Feb 26 21:22:36 2007 for Qwt User's Guide by  doxygen 1.4.6