Results 1 to 10 of 10

Thread: How to plot a simple function with QDateTime X axis and int/double Y axis?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    May 2010
    Posts
    86
    Thanks
    17
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to plot a simple function with QDateTime X axis and int/double Y axis?

    I found this example hidden in the code as commented, but it cannot be compiled. This looks to be a simple application of Qwt, and it is almost what I need to start with and to learn some basics.

    Qt Code:
    1. #include <cmath>
    2. #include <qwt_series_data.h>
    3. #include <qwt_plot_curve.h>
    4. #include <qwt_plot.h>
    5. #include <qapplication.h>
    6.  
    7. class SinusData: public QwtSyntheticPointData
    8. {
    9. public:
    10. SinusData():
    11. QwtSyntheticPointData(100)
    12. {
    13. }
    14. virtual double y(double x) const
    15. {
    16. return qSin(x);
    17. }
    18. };
    19.  
    20. int main(int argc, char **argv)
    21. {
    22. QApplication a(argc, argv);
    23.  
    24. QwtPlot plot;
    25. plot.setAxisScale(QwtPlot::xBottom, 0.0, 10.0);
    26. plot.setAxisScale(QwtPlot::yLeft, -1.0, 1.0);
    27.  
    28. QwtPlotCurve *curve = new QwtPlotCurve("y = sin(x)");
    29. curve->setData(SinusData());
    30. curve->attach(&plot);
    31.  
    32. plot.show();
    33. return a.exec();
    34. }
    To copy to clipboard, switch view to plain text mode 

    This is what I get as error:

    ..\sinus\main.cpp: In function 'int qMain(int, char**)':
    ..\sinus\main.cpp:29: error: no matching function for call to 'QwtPlotCurve::setData(SinusData)'
    ..\sinus\libraries\qwt/qwt_plot_seriesitem.h:146: note: candidates are: void QwtPlotSeriesItem<T>::setData(QwtSeriesData<T>*) [with T = QPointF]
    mingw32-make[1]: *** [release/main.o] Error 1

    If you can fix this code for me, I think I will be able to extend it with more. Thanx in advance!

  2. #2
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,312
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to plot a simple function with QDateTime X axis and int/double Y axis?

    This is basic C++ and the compiler already told you what to do: "curve->setData( new SinusData() );"

    In most applications you want to pass samples from some sort array instead of a data object, that calculates values on the fly. So check all classes derived from QwtSeriesData and the convenience methods QwtPlotCurve::setSamples().

    Uwe

  3. The following user says thank you to Uwe for this useful post:

    falconium (1st May 2011)

  4. #3
    Join Date
    May 2010
    Posts
    86
    Thanks
    17
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to plot a simple function with QDateTime X axis and int/double Y axis?

    Yes, it was the problem. I thought that it could be some mismatch in arguments, but I also noticed finally that not the instance is given. Thx!

  5. #4
    Join Date
    May 2010
    Posts
    86
    Thanks
    17
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to plot a simple function with QDateTime X axis and int/double Y axis?

    Alright, this is where I got:

    Qt Code:
    1. #include <qapplication.h>
    2. #include <qlayout.h>
    3. #include <qlabel.h>
    4. #include <qtime>
    5. #include <qpainter.h>
    6. #include <qwt_plot_layout.h>
    7. #include <qwt_plot_curve.h>
    8. #include <qwt_plot_grid.h>
    9. #include <qwt_scale_draw.h>
    10. #include <qwt_scale_widget.h>
    11. #include <qwt_legend.h>
    12. #include <qwt_legend_item.h>
    13. #include <qwt_curve_fitter.h>
    14. #include "chartplot.h"
    15. #include <QDebug>
    16.  
    17. class Grid: public QwtPlotGrid
    18. {
    19. public:
    20. Grid()
    21. {
    22. enableXMin(true);
    23. setMajPen(QPen(Qt::white, 0, Qt::DotLine));
    24. setMinPen(QPen(Qt::lightGray, 0 , Qt::DotLine));
    25. }
    26.  
    27. virtual void updateScaleDiv(const QwtScaleDiv &xMap,
    28. const QwtScaleDiv &yMap)
    29. {
    30. QList<double> ticks[QwtScaleDiv::NTickTypes];
    31.  
    32. ticks[QwtScaleDiv::MajorTick] = xMap.ticks(QwtScaleDiv::MajorTick);
    33. ticks[QwtScaleDiv::MinorTick] = xMap.ticks(QwtScaleDiv::MinorTick);
    34.  
    35. QwtPlotGrid::updateScaleDiv(
    36. QwtScaleDiv(xMap.lowerBound(), xMap.upperBound(), ticks),
    37. yMap );
    38. }
    39. };
    40.  
    41. class TimeScaleDraw: public QwtScaleDraw
    42. {
    43. public:
    44. TimeScaleDraw(/*const QTime &base*/)/* : baseTime(base)*/
    45. {
    46. setTickLength(QwtScaleDiv::MajorTick, 6);
    47. setTickLength(QwtScaleDiv::MinorTick, 0);
    48. setTickLength(QwtScaleDiv::MediumTick, 0);
    49. setLabelRotation(0);
    50. setLabelAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    51. setSpacing(20);
    52. }
    53.  
    54. virtual QwtText label(double v) const
    55. {
    56. // QTime upTime = baseTime.addSecs((int)v);
    57. QDateTime time;
    58. time = time.fromTime_t(v);
    59. return time.toString("yyyy.MM.dd.\nhh:mm:ss");
    60. }
    61. //private:
    62. // QTime baseTime;
    63. };
    64.  
    65. class Background: public QwtPlotItem
    66. {
    67. public:
    68. Background()
    69. {
    70. setZ(0.0);
    71. }
    72.  
    73. virtual int rtti() const
    74. {
    75. return QwtPlotItem::Rtti_PlotUserItem;
    76. }
    77.  
    78. virtual void draw(QPainter *painter,
    79. const QwtScaleMap &, const QwtScaleMap &/*yMap*/,
    80. const QRectF &rect) const
    81. {
    82. QColor c(Qt::gray);
    83. c=c.darker(150);
    84. // QRectF r = rect;
    85.  
    86. // r.setBottom(yMap.transform(500));
    87. // r.setTop(yMap.transform(0));
    88. painter->fillRect(rect, c);
    89. }
    90. };
    91.  
    92. class ChartCurve: public QwtPlotCurve
    93. {
    94. public:
    95. ChartCurve(const QString &title) : QwtPlotCurve(title)
    96. {
    97. setRenderHint(QwtPlotItem::RenderAntialiased);
    98. }
    99.  
    100. void setColor(const QColor &color)
    101. {
    102. QColor c = color;
    103. c.setAlpha(150);
    104.  
    105. setPen(c);
    106. setBrush(c);
    107. }
    108. };
    109.  
    110. ChartPlot::ChartPlot(QStandardItemModel *model, QWidget *parent) : QwtPlot(parent)
    111. {
    112. setAutoReplot(false);
    113.  
    114. plotLayout()->setAlignCanvasToScales(true);
    115.  
    116. QwtLegend *legend = new QwtLegend;
    117. legend->setItemMode(QwtLegend::CheckableItem);
    118. insertLegend(legend, QwtPlot::RightLegend);
    119.  
    120. setAxisTitle(QwtPlot::xBottom, "Report time");
    121. setAxisAutoScale(QwtPlot::xBottom);
    122. setAxisLabelRotation(QwtPlot::xBottom, -45.0);
    123. setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
    124. setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw());
    125.  
    126. QwtScaleWidget *scaleWidget = axisWidget(QwtPlot::xBottom);
    127. const int fmh = QFontMetrics(scaleWidget->font()).height();
    128. scaleWidget->setMinBorderDist(0, fmh / 2);
    129.  
    130. setAxisTitle(QwtPlot::yLeft, "Quantity");
    131. //setAxisScale(QwtPlot::yLeft, 0, 50);
    132.  
    133. QwtPlotGrid *grid = new Grid;
    134. grid->attach(this);
    135.  
    136. Background *bg = new Background();
    137. bg->attach(this);
    138.  
    139. for (int column = 1; column < model->columnCount(); column++)
    140. {
    141. curve = new ChartCurve(model->horizontalHeaderItem(column)->text());
    142. curve->setStyle(QwtPlotCurve::Lines);
    143. QVariant decoration = model->item(0, column)->data(Qt::DecorationRole);
    144. if (decoration.type() == QVariant::Color)
    145. {
    146. curve->setColor(decoration.value<QColor>());
    147. }
    148. curve->setCurveAttribute(QwtPlotCurve::Fitted, true);
    149. curve->setCurveFitter(curveFitter);
    150. curve->setZ(curve->z() - 1);
    151. curve->attach(this);
    152.  
    153. QVector<double> xData;
    154. QVector<double> yData;
    155. for (int row=0; row<model->rowCount(); row++)
    156. {
    157. QDateTime xDateTime = model->item(row, 0)->data(Qt::EditRole).toDateTime();
    158. xData << xDateTime.toTime_t();
    159. yData << model->item(row, column)->data(Qt::EditRole).toDouble();
    160. }
    161. curve->setSamples(xData, yData);
    162. showCurve(curve, true);
    163. }
    164.  
    165. connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)), SLOT(showCurve(QwtPlotItem *, bool)));
    166. }
    167.  
    168. void ChartPlot::showCurve(QwtPlotItem *item, bool on)
    169. {
    170. item->setVisible(on);
    171. QWidget *w = legend()->find(item);
    172. if (w && w->inherits("QwtLegendItem")) ((QwtLegendItem *)w)->setChecked(on);
    173.  
    174. replot();
    175. }
    To copy to clipboard, switch view to plain text mode 

    How can I change the values of (major) ticks on axis X to match the date of source values or to match some nice value to be easily read by humans?

    I also have problems with spine, as it doesn't always match precisely. The plot can grow higher than the actual value. I'll send you picture tomorrow. Here it is: wrong spline

    Pictures:

    Source data: link
    Chart: link

    Thanks for any idea!
    Last edited by falconium; 2nd May 2011 at 05:35.

  6. #5
    Join Date
    May 2010
    Posts
    86
    Thanks
    17
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to plot a simple function with QDateTime X axis and int/double Y axis?

    OK, I have managed to fill the gaps in the chart by using Floating attribute:

    Qt Code:
    1. scaleEngineX->setAttribute(QwtScaleEngine::Floating, true);
    2. setAxisScaleEngine(QwtPlot::xBottom, scaleEngineX);
    To copy to clipboard, switch view to plain text mode 

    Now, the question is still, how to set major ticks to exact values of the original, source data, not some intermediate, calculated ones. (And of course, if there are too many discrete values on axis, to show only part of them based on an algorithm.)

    I have tried to play around with:

    setAxisMaxMinor(QwtPlot::xBottom, <some value>);
    setAxisMaxMajor(QwtPlot::xBottom, <model->rowCount() or other values>);

    No success. They always put ticks to wrong positions.
    Thank you for the help in advance! This would be the only critical thing to me.

  7. #6
    Join Date
    May 2010
    Posts
    86
    Thanks
    17
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to plot a simple function with QDateTime X axis and int/double Y axis?

    Now I know i would have had to use QwtScaleDiv class for this purpose:

    Qt Code:
    1. QwtScaleDiv ChartPlot::scaleDiv()
    2. {
    3. QList<double> ticks[QwtScaleDiv::NTickTypes];
    4.  
    5. QList<double> &majorTicks = ticks[QwtScaleDiv::MajorTick];
    6.  
    7. foreach (double val, xData)
    8. majorTicks += val;
    9.  
    10. QList<double> &mediumTicks = ticks[QwtScaleDiv::MediumTick];
    11. for (int i = 0; i < xData.count() - 1; ++i)
    12. mediumTicks += QDateTime::fromTime_t(xData[i]).addSecs(900).toTime_t();
    13.  
    14. QList<double> &minorTicks = ticks[QwtScaleDiv::MinorTick];
    15. for (int i = 0; i < xData.count() - 1; ++i)
    16. minorTicks += QDateTime::fromTime_t(xData[i]).addSecs(300).toTime_t();
    17.  
    18. return QwtScaleDiv(xData.first(), xData.last(), ticks);
    19. }
    To copy to clipboard, switch view to plain text mode 

    Simply call this function to set axis scale divisions in your QwtPlot instance as following:

    Qt Code:
    1. setAxisScaleDiv(QwtPlot::xBottom, scaleDiv());
    To copy to clipboard, switch view to plain text mode 

    The only problem now I have is to set one minor tick to 1/10 of major tick and one medium tick to 1/5 of major tick. Thanks for suggestions in advance!

  8. #7
    Join Date
    May 2010
    Posts
    86
    Thanks
    17
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to plot a simple function with QDateTime X axis and int/double Y axis?

    I solved it, please, find it here for future reference:

    Qt Code:
    1. QwtScaleDiv ChartPlot::scaleDiv()
    2. {
    3. QList<double> ticks[QwtScaleDiv::NTickTypes];
    4.  
    5. QList<double> &majorTicks = ticks[QwtScaleDiv::MajorTick];
    6.  
    7. foreach (double val, xData)
    8. majorTicks += val;
    9.  
    10. if (xData.count()>1)
    11. {
    12. QList<double> &mediumTicks = ticks[QwtScaleDiv::MediumTick];
    13. for (int i = 0; i < xData.count() - 1; i++)
    14. for (int j = 1; j < 6; j++)
    15. mediumTicks += xData[i] + j * (xData[i+1] - xData[i]) / 5;
    16.  
    17. QList<double> &minorTicks = ticks[QwtScaleDiv::MinorTick];
    18. for (int i = 0; i < xData.count()*10 - 1; i++)
    19. for (int j = 1; j < 11; j++)
    20. minorTicks += xData[i] + j * (xData[i+1] - xData[i]) / 10;
    21. }
    22.  
    23. return QwtScaleDiv(xData.first(), xData.last(), ticks);
    24. }
    To copy to clipboard, switch view to plain text mode 

  9. The following user says thank you to falconium for this useful post:

    corrado1972 (4th May 2011)

Similar Threads

  1. Replies: 2
    Last Post: 8th February 2011, 14:53
  2. Replies: 0
    Last Post: 9th August 2010, 10:46
  3. Replies: 1
    Last Post: 30th July 2010, 07:23
  4. Virtual axis ?
    By viridis in forum Qwt
    Replies: 2
    Last Post: 1st July 2008, 15:28
  5. Qwt and custom axis
    By jiveaxe in forum Qwt
    Replies: 3
    Last Post: 14th November 2007, 15:50

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.