PDA

View Full Version : Newbie : QwtCurveFitter and retrieve curve data



sapym
21st June 2010, 17:24
Hello,

I'm sorry if I'm raising a stupid qusetion but I ran throught the forum and could not find any answer that enables me to solve my problem...

I'm trying to use Qwt in order to create a widget that will enable me to interpolate a Gamma curve and modify some points...

So thanks to the event_filter example I was abble to copy the canvaspicker that makes the modification of points possible...

But now that I have my curve... how can I retrieve all the values ?




Plot::Plot(QWidget *parent):
QwtPlot(parent)
{
tab_x[0] = 0; (----) to tab_x[10] = 4096;
tab_y[0] = gamma(Tab_x[0]) = 0 to tab_y[10] = gamma(Tab_x[10]) (= 1024)

setAxisScale(QwtPlot::xBottom, 0.0, 4200,100);
setAxisScale(QwtPlot::yLeft, 0.0, 1050.0,100);

axisScaleDraw(QwtPlot::xBottom)->setLabelRotation(90);
axisScaleDraw(QwtPlot::xBottom)->setLabelAlignment(Qt::AlignRight);
setAxisFont(QwtPlot::xBottom,QFont("MS Shell Dlg 2",9));

curve = new QwtPlotCurve();

curve->setStyle(QwtPlotCurve::Lines);
curve->setCurveAttribute(QwtPlotCurve::Fitted, true);
curve->setPen(QColor(Qt::red));
curve->setSymbol(QwtSymbol(QwtSymbol::Cross,Qt::gray,QCol or(Qt::red), QSize(8, 8)));

curveFitter = new QwtSplineCurveFitter();
curveFitter->setFitMode(curveFitter->ParametricSpline);
curveFitter->setSplineSize(100);
curve->setCurveFitter(curveFitter);

curve->setData(tab_x, tab_y, sizeof(tab_x) / sizeof(tab_x[0]));
curve->attach(this);

replot();
}


Thansk a lot for any help....I'm turning crazy ....(and sorry if it is stupid)

Uwe
21st June 2010, 18:56
But now that I have my curve... how can I retrieve all the values ?

Which values ?

Obviously your points can be found in tab_x/tab_y. When painting these points are translated into widget ( canvas ) coordinates and your fitter adds additional points (also in screen coordinates) to smooth your curve. All translated points are temporary only and are recalculated each time the curve is painted.

Uwe

sapym
22nd June 2010, 07:50
Thanks for your answer

Actually yes...I want the 4096 y interpolated values (x is easy indeed ! ;) )
Is that possible ?

Uwe
22nd June 2010, 14:43
Actually yes...I want the 4096 y interpolated values (x is easy indeed ! ;) )
These points are temporary because there position depends on the geometry of the plot canvas and the current scales. You could do the same interpolation in your application code, but probably what you want is to interpolate the untranslated curve points.

So do the interpolation of your points manually ( with a local fitter object ) and pass the interpolated points to a curve without internal fitting.

Uwe

sapym
22nd June 2010, 14:49
I'm sorry... I don't understand...

Ok...points of the curve are temporary and their position depends of axis scale etc...

What do you call interpolate manually ? or local fitter object ....

Sorry if I'm such a noob here...

Uwe
22nd June 2010, 20:45
QPolygonF points;
for ( int i = 0; i < ...; i++ )
points += QPointF(tab_x[i], tabỵ[i]);

points = QwtSplineCurveFitter()::fitCurve(points);

// now you have interpolated untranslated points

curve = new QwtPlotCurve();
curve->setCurveAttribute(QwtPlotCurve::Fitted, false);
curve->setData(points);
...

HTH,
Uwe

sapym
23rd June 2010, 07:21
Ok.... that works great...

Now my only problem is to retrieve the coordonates of the points I moved ...

Uwe
23rd June 2010, 09:28
See QwtPlot::canvasMap().

Uwe

sapym
25th June 2010, 08:45
Sorry for my late answer...but... THAKNS a lot for your tips...
I finally do it this way :




void Plot::getPoints()
{
QwtArray<double> xData(curve->dataSize());
QwtArray<double> yData(curve->dataSize());

QPolygonF points,points2;

for ( int i = 0; i < curve->dataSize(); i++ )
{
points += QPointF(curve->x(i), curve->y(i));
}

QwtSplineCurveFitter curvefitter;
curvefitter.setFitMode(curveFitter->ParametricSpline);
curvefitter.setSplineSize(4096);

points2 = Toto.fitCurve(points);
}


Can I raise another last little question ? :o

I have my plot...with goes from 0 to 4096 on x and 0 to 1024 on y ....how can I have the same scale on x and y axis ? (1 cm on x = for example 100 = 1 cm on y )

Uwe
25th June 2010, 11:17
See QwtPlotRescaler. In SVN trunk you find the navigation example that shows how to use it.

Uwe

sapym
19th July 2010, 10:22
Thanks for all your help !

I have now another problem...perhas should I start another thread ?

I have now my plot which I made using the event_filter example : I'm moving points of my curve and I am abble to save them... But I want to have the coordinates of my cursor on the plot...

So I tried to combine the bode example with QwtPlotZoomer or QwtPlotPicker... but my canvaspicker class (extracted from event_filter example) installs an eventFilter on the canvas ...so no click seems to be linked to the Picker...

sapym
19th July 2010, 17:05
Gloups...
fitCurve(points) don't give the exact points that I can see on the plot ....

I can see on the graph some values always > 0 and in the PolygonF retrieved... I have some negative values...how can I retrieve the exact values of the plot ???

Uwe
20th July 2010, 06:50
Of course you have to assign the fitted points ( = points2 in your code snippet ) to your curve and disable QwtPlotCurve::Fitted.

Uwe

sapym
20th July 2010, 07:47
This is my code :

Plot::Plot(QWidget *parent):
QwtPlot(parent)
{
tab_x[0] = 0; tab_x[1] = 200; tab_x[2] = 400; tab_x[3] = 600; tab_x[4] = 1600; tab_x[5] = 2000;
tab_x[6] = 2400; tab_x[7] = 2800; tab_x[8] = 3200; tab_x[9] = 3600; tab_x[10] =

tab_y[0] = mygamma(tab_x[0],4096,1023,0.5);
tab_y[1] = mygamma(tab_x[1],4096,1023,0.5);
tab_y[2] = mygamma(tab_x[2],4096,1023,0.5);
tab_y[3] = mygamma(tab_x[3],4096,1023,0.5);
tab_y[4] = mygamma(tab_x[4],4096,1023,0.5);
tab_y[5] = mygamma(tab_x[5],4096,1023,0.
tab_y[6] = mygamma(tab_x[6],4096,1023,0.5);
tab_y[7] = mygamma(tab_x[7],4096,1023,0.5);
tab_y[8] = mygamma(tab_x[8],4096,1023,0.5);
tab_y[9] = mygamma(tab_x[9],4096,1023,0.5);
tab_y[10] = mygamma(tab_x[10],4096,1023,0.5);

int nb_points = sizeof(tab_x) / sizeof(tab_x[0]);
QPolygonF points,points2;
for ( int i = 0; i < nb_points ; i++ )
{
points += QPointF(tab_x[i], tab_y[i]);
}

m_Curve = new QwtPlotCurve();
m_CurveFitter = new QwtSplineCurveFitter();

m_Curve->setCurveAttribute(QwtPlotCurve::Fitted, true); // Otherwise I have got Lines and not smooth curve the fitted curve is better for me
m_Curve->setStyle(QwtPlotCurve::Lines);

m_CurveFitter->setFitMode(m_CurveFitter->ParametricSpline);
m_CurveFitter->setSplineSize(4096); // from my orignal 10 points I want 4096 points

m_Curve->setCurveFitter(m_CurveFitter);
m_Curve->setData(tab_x, tab_y, sizeof(tab_x) / sizeof(tab_x[0]));
m_Curve->attach(this);
}



QPolygonF Plot::getPoints(int nCurve)
{
QPolygonF points,InterpolatedPoints;
m_Curve;
m_CurveFitter

for ( int i = 0; i < m_Curve->dataSize(); i++ )
{
points += QPointF(m_Curve->x(i), m_Curve->y(i));
}

InterpolatedPoints = curveFitter->fitCurve(points);

return InterpolatedPoints;
}


double mygamma(double in,int nbpoints_in,int nbpoints_out,double gma)
{
double x = in / nbpoints_in;

return (pow(x,gma) * nbpoints_out );
}




So I have to setCurveAttribute(QwtPlotCurve::Fitted, FALSE ); ?? I that case my curve is totally not smooth...
I don't understand how Qwt can trace a curve, and one cannot access the points of that curve...

I do understand in my code that the Interpolated points that I retrieve are not the one traced on my graph ..the Fitted parameter should change this ...but I need it.

Uwe
20th July 2010, 08:47
You have to interpolate your points first and then assign the interpolated points to to your curve. What's so hard about this ?

Uwe

sapym
20th July 2010, 08:56
Well...sorry to bother you ...how do you assign ? setData ?


points2 = m_CurveFitter->fitCurve(points);
m_Curve->setData(points2);


if I do so : setData...my curve is made of 4096 points... and I cannot move the original points like I used to...

What I want to "capture" : http://www.thilloy.fr/fofo.JPG

Uwe
20th July 2010, 09:38
if I do so : setData...my curve is made of 4096 points... and I cannot move the original points like I used to...
The interpolated points and your 4096 points are different - that's what spline interpolation is about. Of course you have to find a way to re-translate changes of the interpolated points into changes of your original ones.

Maybe it helps to insert 2 curves: one with your 4096 points with symbols only and a second one with the interpolated points showing the lines but no symbols ?


Uwe

sapym
20th July 2010, 09:56
I'm starting from 10 points : x_0 = 0 to x_10 = 4095 and y_0 = 0 to y_10 = 1023 y = f(x) with f = gamma function...

I used the "CanvasPicker" from the event_filter example to be abble to move these points ... the curve is modified at the same time... (setData (tab_x,tab_y,10) with tab_x and tab_y modified )

And from these 10 pôints ...I want the 4096 interpolated points (I don't see what you mean by "The interpolated points and your 4096 points are different")

sapym
21st July 2010, 08:51
I tried everything... from

curve->plot()->invTransform(curve->yAxis(), x);
or curve->plot()->transform(curve->yAxis(), x);
or curveFitter->spline().value(x);

Nothing...snif... :crying:

Uwe
22nd July 2010, 06:17
Well, without understanding ( what is obvious from your code snippets ) what happens to your points you will fail. But what about the idea of using 2 QwtPlotCurves for your points: the first displaying the symbols only and a second one with a spline interpolated line ?

Uwe

sapym
22nd July 2010, 07:35
Yes Uwe... I was a little stubborn and moreover kind of lost... please accept my appologies !
I know that my code is very far from perfect .. I do my best ... but as I said...a newbie...

I read this post form the beginning in order to have a fresh view on your advices and #4 is now clear to me...
Yes I tried yesterday with 2 curves ...


for (int ii = 0 ; ii < 2 ; ii ++)
{
m_UniqueCurve[ii] = new QwtPlotCurve();
m_UniqueCurveFitter[ii] = new QwtSplineCurveFitter();
m_UniqueCurveFitter[ii]->setFitMode(m_UniqueCurveFitter[ii]->ParametricSpline);
m_UniqueCurveFitter[ii]->setSplineSize(4096);
m_UniqueCurve[ii]->setCurveFitter(m_UniqueCurveFitter[ii]);
}

m_UniqueCurve[0]->setCurveAttribute(QwtPlotCurve::Fitted, true);
m_UniqueCurve[1]->setCurveAttribute(QwtPlotCurve::Fitted, false);
m_UniqueCurve[0]->setStyle(QwtPlotCurve::Lines);
m_UniqueCurve[1]->setStyle(QwtPlotCurve::Dots);


m_UniqueCurve[0]->setPen(QColor(Qt::transparent));
m_UniqueCurve[0]->setSymbol(QwtSymbol(QwtSymbol::Ellipse,Qt::gray, QColor(Qt::black), QSize(8,8)));

m_UniqueCurve[1]->setPen(QColor(Qt::black));

QPolygonF OriginalPoints,InterpolatedPoints;
for ( int i = 0; i < TabX.count() ; i++ )
{
OriginalPoints+= QPointF(TabX[i], TabY[i]);
}

InterpolatedPoints= m_RedCurveFitter[1]->fitCurve(points);

m_UniqueCurve[0]->setData(TabX.data(), TabY.data(),TabX.count());
m_UniqueCurve[1]->setData(InterpolatedPoints);


And then I had to patch some lines in tne canvaspicker to be abble to select the good curve and move them together...

So again I'm deeply sorry for hte bad quality of my code and my eyes while reading your posts ;)

Thanks a lot for your help

Best regards

Paul