PDA

View Full Version : Curve could not pass the points



momo
11th February 2014, 08:07
Hi all,
I want to draw a curve in the plot, the value of the first point is relatively small and the value of the last one is relatively large,
I want to use QwtSplineCurveFitter to make the curve smoother, but the result shows that the curve could not pass the point,
can you help me to solve this problem?

this is my code:


#include <qapplication.h>
#include <qwt_plot.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_grid.h>
#include <qwt_curve_fitter.h>
#include <qwt_symbol.h>
#include <qwt_legend.h>
#include <qwt_scale_engine.h>

int main( int argc, char **argv )
{
QApplication a( argc, argv );

QwtPlot plot;
plot.setTitle( "Plot Demo" );
plot.setCanvasBackground( Qt::white );
plot.setAxisScale( QwtPlot::yLeft, 0, 100 );
plot.setAxisScale( QwtPlot::xBottom, 50.0, 0.0 );
plot.insertLegend( new QwtLegend() );
QwtPlotGrid *grid = new QwtPlotGrid();
grid->attach( &plot );

QwtPlotCurve *curve = new QwtPlotCurve();
curve->setTitle( "Some Points" );
curve->setPen( QPen( Qt::blue, 1 ) );
curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );

QwtSymbol *symbol = new QwtSymbol( QwtSymbol::Ellipse,
QBrush( Qt::yellow ), QPen( Qt::red, 1 ), QSize( 2, 2 ) );
curve->setSymbol( symbol );

curve->setCurveAttribute(QwtPlotCurve::Fitted);
QwtSplineCurveFitter *pCurveFitter = new QwtSplineCurveFitter;
pCurveFitter->setFitMode(QwtSplineCurveFitter::ParametricSpline) ;
curve->setCurveFitter(pCurveFitter);

QPolygonF points;
points << QPointF( 0.0, 2.58258 ) << QPointF( 0.995469, 6.45643 )
<< QPointF( 4.11356, 12.9129 ) << QPointF( 12.565, 19.3693 )
<< QPointF( 25.1777, 25.8257 ) << QPointF( 45.1747, 51.6515 )
<< QPointF( 50.5358, 77.4772) << QPointF( 53.477, 103.303)
<<QPointF( 54.8972, 129.129) << QPointF( 56.9157, 154.954)
<< QPointF( 60.1614, 206.606) << QPointF( 63.6644, 284.083)
<< QPointF( 66.3, 361.56) << QPointF( 68.3328, 439.038)
<< QPointF( 70.5758, 542.341) << QPointF( 74.1964, 800.598)
<<QPointF( 76.675, 1058.86) << QPointF(78.6658, 1317.11)
<< QPointF(81.0151, 1833.63) << QPointF(83.0936, 2608.4)
<< QPointF(84.9255, 3899.69) << QPointF(86.8342, 6482.26)
<< QPointF(87.3439, 8290.06);

curve->setSamples( points );

curve->attach( &plot );

plot.resize( 600, 400 );
plot.show();

return a.exec();
}


and the result picture is here:
10033

Uwe
11th February 2014, 17:57
Your x values seem to be increasing - so you don't need a ParametricSpline ?

Uwe

In SVN trunk you find a first implementation of a fitter using Bezier curves. You can try this one too and if you like it you can copy it to your code as the implementation is compatible with Qwt 6.1.

momo
12th February 2014, 02:10
Hi Uwe,
Thank you for your reply.
Now I deleted the following code:


curve->setCurveAttribute(QwtPlotCurve::Fitted);
// QwtSplineCurveFitter *pCurveFitter = new QwtSplineCurveFitter;
// pCurveFitter->setFitMode(QwtSplineCurveFitter::Auto);
// curve->setCurveFitter(pCurveFitter);

The curve is still not pass the point.
Is it Qwt's bug? Or is it my wrong way to use CurveAttribute and CurveFitter?

Momo

Uwe
14th February 2014, 10:59
Looks like a Qwt bug of splines in combination with an inverted x axis. I will have a look at it.

Added after 19 minutes:

The reason why it is broken for the inverted x axis is because of the QwtSplineCurveFitter::Auto mode, that decides a parametric spline interpolation when the x coordinates are not monotonic increasing. As the interpolation happens for the translated polygon ( paint device coordinates ) the points arr monotonic decreasing in your example.

An easy workaround for you might be:


QwtSplineCurveFitter *pCurveFitter = new QwtSplineCurveFitter;
pCurveFitter->setFitMode( QwtSplineCurveFitter::Spline );
curve->setCurveFitter( pCurveFitter );Uwe

momo
19th February 2014, 01:08
Thank you very much, Uwe. :D

Momo