地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
5.2 KiB

/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_math.h"
#include "qwt_spline.h"
#include "qwt_curve_fitter.h"
//! Constructor
QwtCurveFitter::QwtCurveFitter()
{
}
//! Destructor
QwtCurveFitter::~QwtCurveFitter()
{
}
class QwtSplineCurveFitter::PrivateData
{
public:
PrivateData():
fitMode(QwtSplineCurveFitter::Auto),
splineSize(250) {
}
QwtSpline spline;
QwtSplineCurveFitter::FitMode fitMode;
int splineSize;
};
QwtSplineCurveFitter::QwtSplineCurveFitter()
{
d_data = new PrivateData;
}
QwtSplineCurveFitter::~QwtSplineCurveFitter()
{
delete d_data;
}
void QwtSplineCurveFitter::setFitMode(FitMode mode)
{
d_data->fitMode = mode;
}
QwtSplineCurveFitter::FitMode QwtSplineCurveFitter::fitMode() const
{
return d_data->fitMode;
}
void QwtSplineCurveFitter::setSpline(const QwtSpline &spline)
{
d_data->spline = spline;
d_data->spline.reset();
}
const QwtSpline &QwtSplineCurveFitter::spline() const
{
return d_data->spline;
}
QwtSpline &QwtSplineCurveFitter::spline()
{
return d_data->spline;
}
void QwtSplineCurveFitter::setSplineSize(int splineSize)
{
d_data->splineSize = qwtMax(splineSize, 10);
}
int QwtSplineCurveFitter::splineSize() const
{
return d_data->splineSize;
}
#if QT_VERSION < 0x040000
QwtArray<QwtDoublePoint> QwtSplineCurveFitter::fitCurve(
const QwtArray<QwtDoublePoint> & points) const
#else
QPolygonF QwtSplineCurveFitter::fitCurve(
const QPolygonF &points) const
#endif
{
const int size = (int)points.size();
if ( size <= 2 )
return points;
FitMode fitMode = d_data->fitMode;
if ( fitMode == Auto ) {
fitMode = Spline;
const QwtDoublePoint *p = points.data();
for ( int i = 1; i < size; i++ ) {
if ( p[i].x() <= p[i-1].x() ) {
fitMode = ParametricSpline;
break;
}
};
}
if ( fitMode == ParametricSpline )
return fitParametric(points);
else
return fitSpline(points);
}
#if QT_VERSION < 0x040000
QwtArray<QwtDoublePoint> QwtSplineCurveFitter::fitSpline(
const QwtArray<QwtDoublePoint> &points) const
#else
QPolygonF QwtSplineCurveFitter::fitSpline(
const QPolygonF &points) const
#endif
{
d_data->spline.setPoints(points);
if ( !d_data->spline.isValid() )
return points;
#if QT_VERSION < 0x040000
QwtArray<QwtDoublePoint> fittedPoints(d_data->splineSize);
#else
QPolygonF fittedPoints(d_data->splineSize);
#endif
const double x1 = points[0].x();
const double x2 = points[int(points.size() - 1)].x();
const double dx = x2 - x1;
const double delta = dx / (d_data->splineSize - 1);
for (int i = 0; i < d_data->splineSize; i++) {
QwtDoublePoint &p = fittedPoints[i];
const double v = x1 + i * delta;
const double sv = d_data->spline.value(v);
p.setX(qRound(v));
p.setY(qRound(sv));
}
d_data->spline.reset();
return fittedPoints;
}
#if QT_VERSION < 0x040000
QwtArray<QwtDoublePoint> QwtSplineCurveFitter::fitParametric(
const QwtArray<QwtDoublePoint> &points) const
#else
QPolygonF QwtSplineCurveFitter::fitParametric(
const QPolygonF &points) const
#endif
{
int i;
const int size = points.size();
#if QT_VERSION < 0x040000
QwtArray<QwtDoublePoint> fittedPoints(d_data->splineSize);
QwtArray<QwtDoublePoint> splinePointsX(size);
QwtArray<QwtDoublePoint> splinePointsY(size);
#else
QPolygonF fittedPoints(d_data->splineSize);
QPolygonF splinePointsX(size);
QPolygonF splinePointsY(size);
#endif
const QwtDoublePoint *p = points.data();
QwtDoublePoint *spX = splinePointsX.data();
QwtDoublePoint *spY = splinePointsY.data();
double param = 0.0;
for (i = 0; i < size; i++) {
const double x = p[i].x();
const double y = p[i].y();
if ( i > 0 ) {
const double delta = sqrt( qwtSqr(x - spX[i-1].y())
+ qwtSqr( y - spY[i-1].y() ) );
param += qwtMax(delta, 1.0);
}
spX[i].setX(param);
spX[i].setY(x);
spY[i].setX(param);
spY[i].setY(y);
}
d_data->spline.setPoints(splinePointsX);
if ( !d_data->spline.isValid() )
return points;
const double deltaX =
splinePointsX[size - 1].x() / (d_data->splineSize-1);
for (i = 0; i < d_data->splineSize; i++) {
const double dtmp = i * deltaX;
fittedPoints[i].setX(qRound(d_data->spline.value(dtmp)));
}
d_data->spline.setPoints(splinePointsY);
if ( !d_data->spline.isValid() )
return points;
const double deltaY =
splinePointsY[size - 1].x() / (d_data->splineSize-1);
for (i = 0; i < d_data->splineSize; i++) {
const double dtmp = i * deltaY;
fittedPoints[i].setY(qRound(d_data->spline.value(dtmp)));
}
return fittedPoints;
}