PDA

View Full Version : Qwt spline fitter - it doesn't work as expected



giaur
29th November 2009, 17:55
Hello,

I need to use spline interpolation for data display in my program. There is QwtSplineCurveFitter class - documentation says, thar it uses spline to fit curve, but the results are not acceptable (or I have missed something?):

Code to fit curve between 5 points:



QwtPlotCurve *curve1 = new QwtPlotCurve("Curve 1");

QPolygonF polygon;

polygon << QPointF(-1, -3);
polygon << QPointF(1, 5);
polygon << QPointF(2, 16);
polygon << QPointF(3, 8);
polygon << QPointF(4, 13);

QwtSplineCurveFitter fitter;
fitter.setFitMode(fitter.ParametricSpline);
curve1->setData(fitter.fitCurve(polygon));
curve1->attach(ui->plot);

ui->plot->replot();



And this is the result:

http://img39.imageshack.us/img39/9307/50459265.png

Without using fitter class:

http://img4.imageshack.us/img4/2774/96823651.png

OS: Debian Sid
Qwt: 5.2.0-1 (libqwt5-qt4)

What's wrong there? Interpolation seems to be not working at all or spline resolution is very low but I can't see any method to increase it?

Uwe
30th November 2009, 10:03
Guess you want to interpolate the points after they have been translated to widget coordinates. QwtPlotCurve does this for you, when:


curve->setStyle(QwtPlotCurve::Lines);
curve->setCurveAttribute(QwtPlotCurve::Fitted, true);

If you want to pass an individual fitter:


QwtSplineCurveFitter *fitter = new QwtSplineCurveFitter();
fitter->setFitMode(fitter.ParametricSpline);
fitter->setSplineSize(...);
curve->setCurveFitter(fitter);

Uwe

giaur
30th November 2009, 18:56
It works, but there is no interpolation when using custom fitter...

giaur
30th November 2009, 22:39
Ok, I'm going to write interpolation method from scratch, because built-in fitter is not enough for me (it's quite poor i think), but anyway, thanks for response

Uwe
1st December 2009, 07:17
Ok, I'm going to write interpolation method from scratch, because built-in fitter is not enough for me (it's quite poor i think), but anyway, thanks for response

As far as I can see you didn't succeed to use the QwtCurveFitter API ( guess you missed to enable the QwtPlotCurve::Fitted attribute, or didn't adjust the spline size.) . If frustration about this is the reason for your "poor", well ...

If your statement is because you have checked the implementation, please elaborate, why spline interpolation ( this is a very common way of interpolation ) isn't a solution for you situation.

QwtCurveFitter is an abstract API and you can implement any other fitting algorithm as well ( f.e. in 5.3 you find an implementation of the Douglas/Peucker algorithm ). So if you know other/better strategies for curve fitting I'm interested to add them to the Qwt lib.

Uwe

giaur
1st December 2009, 09:46
What about Cardinal/Cubic Spline? The cubic spline is used in OpenOffice and it works quite good. I tested cardinal spline also, and results was much better than default qwt fitter


QwtCurveFitter is an abstract API and you can implement any other fitting algorithm as well

It sounds good - can you provide simple example how to do this?

Uwe
2nd December 2009, 08:40
What about Cardinal/Cubic Spline? The cubic spline is used in OpenOffice and it works quite good.
QwtSplineCurveFitter is an implementation of a cubic spline - are you sure, that you successfully enabled spline interpolation for your curve ?

You didn't explain why you want to have curve interpolation. If your motivation is to paint smoother curves it's obvious, that interpolation needs to be done for the translated points ( in widget coordinates ) - not for the points in application coordinates.


It sounds good - can you provide simple example how to do this?
If you want to interpolate the translated points (see above) you must derive from QwtCurveFitter and implement YourFitter::fitCurve(). Please send me the code of your cardinal spline class or something else if you think it is valuable for others.

But initializing your curve with your individual fitter requires the same steps you have to do for QwtSplineCurveFitter. So I recommend to check if the bad results of the interpolation are really because of the implemented interpolation algorithm. If true I would be interested in your curve points for further investigations.

Maybe it helps to check the curvdemo2 example, that shows how to enable interpolation ( don't forget the QwtPlotCurve::Fitted attribute).

Uwe

giaur
2nd December 2009, 17:20
So I recommend to check if the bad results of the interpolation are really because of the implemented interpolation algorithm.
I'm sure they are.

I've made simple test. My data points are:
0, 17
1, 16.5
2, 8
4, 3
5, 12
8, 14.5

And look at the plot screenshot:
http://img691.imageshack.us/img691/4927/spline.png

Legend:
- blue: without spline
- green: parametric spline (built in)
- red: cardinal spline, tangentStrength=0.35

Built-in cubic spline (entirely unacceptable for me):
http://img412.imageshack.us/img412/1267/spline3.png

And, finally - cubic spline from open office for the same points:

http://img101.imageshack.us/img101/27/spline2.png

I'm not really sure what alghoritm exactly is used in Open Office, but this is much better, than your cubic spline implementation, and it seems to be better, than cardinal spline I used.

Uwe
2nd December 2009, 18:17
I tried your points with the following code:


#include <qapplication.h>
#include <qwt_plot.h>
#include <qwt_plot_curve.h>
#include <qwt_curve_fitter.h>
#include <qwt_symbol.h>

int main(int argc, char **argv)
{
const QColor color(35, 70, 106);

QApplication a(argc, argv);

QwtPlot plot;
plot.setCanvasBackground(Qt::white);
plot.resize(600,400);
plot.show();

const double x[] = { 0, 1, 2, 4, 5, 8 };
const double y[] = { 17, 16.5, 8, 3, 12, 14.5 };

// Insert new curves
QwtPlotCurve *curve = new QwtPlotCurve();
curve->setStyle(QwtPlotCurve::Lines);
curve->setCurveAttribute(QwtPlotCurve::Fitted, true);

QwtSymbol symbol;
symbol.setStyle(QwtSymbol::Rect);
symbol.setSize(10, 10);
symbol.setBrush(color);

curve->setSymbol(symbol);

QwtSplineCurveFitter *fitter = new QwtSplineCurveFitter();
fitter->setFitMode(QwtSplineCurveFitter::ParametricSpline) ;
fitter->setSplineSize(100);
curve->setCurveFitter(fitter);

curve->setRenderHint(QwtPlotItem::RenderAntialiased);
curve->setPen(QPen(color, 3));

curve->setData(x, y, 6);
curve->attach(&plot);

return a.exec();
}

The result is different compared to the OpenOffice curve, but what exactly makes you so unhappy with it ?

Uwe

PS: You can play with the spline size parameter. IMHO the curve looks better with a value of 50.

giaur
2nd December 2009, 18:59
Ok, parametric spline is quite good - it looks the same as on my screenshot. But there is still some effect which I neew to minimalize - I need only edges round, and minimal curve peeks. For cardinal spline, there is parametr called tangentStrength and I can play with it to get bes results.

I simply need the situation, when maximum/minimum data point is curve maximum/minimum (ideally) and cardinal spline in my screen looks better here