00001
00002
00003
00004
00005
00006
00007
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 }