PDA

View Full Version : QwtPlotCurve with timestamps on ARM



MrGentleman
21st July 2017, 05:57
Hello folks!

I am having some troubles when plotting a QwtPlotCurve with time stamps on the x axis when drawing plots on an embedded system.
The QwtPlotCurve uses internally a representation with a series of QPointF, the QPointF again uses qreal's for the coordinates. While the qreal is a typedef for 'double' on Desktop systems, qreal is defined to be 'float' on ARM based systems. The problem is now that I can not store UNIX timestamps in a float without data loss because there are 'only' 23 bits available (double has 52 bits).

My question is now if there is any other curve implementation which will support a series of e.g. QPair<unsigned long, double> instead of QPointF? Or do I have to implement a custom curve?

Best regards,
michael

Uwe
23rd July 2017, 11:48
qreal is defined to be 'float' on ARM based systems. The problem is now that I can not store UNIX timestamps in a float without data loss because there are 'only' 23 bits available (double has 52 bits).
First of all you could check if this is really the correct setting for your hardware. I remember, that this once was the default - often false - configuration chosen, when building Qt for ARM.
Also the fact that qreal is a float does not prevent you from using double - simply don't use qreal, where you explicitly want to have doubles.


My question is now if there is any other curve implementation which will support a series of e.g. QPair<unsigned long, double> instead of QPointF?
In general QwtPlotCurve is totally independend from how you store your values and using your pairs is totally fine. All you need to do is to implement a class derived from QwtSeriesData<QPointF>, that returns the samples from your pairs and assign it with curve->setSamples().

And yes QPointF is based on qreal and here is where the story ends for QwtDateScaleEngine/QwtDateScaleDraw, that are converting a QDateTime from it. But as long as you don't need these classes there should be no problem.

Uwe

MrGentleman
24th July 2017, 06:24
Hello Uwe,

thanks a lot for the reply.

Maybe I am wrong, but when deriving from QwtSeriesData<QPointF>, I have QPointF as underlying data type, how can I switch to e.g. QPair<unsigned long, double>?
Do you have any example code which shows how to use a custom type for a series data?

Thanks and best regards!

Uwe
24th July 2017, 06:39
class YourData: public QwtSeriesData<QPointF>
{
public:
....
virtual size_t size() const override
{
return m_pairs.size();
}

virtual QPointF sample( size_t i ) const override
{
auto& pair = m_pairs[i];
return QPointF( pair.first, pair.second );
}

private:
QVector< QPair<unsigned long, qreal> >;
};
Uwe

MrGentleman
24th July 2017, 07:20
Thank you very much for the code snippet.

This meands, that the method 'sample()' returns a QPointF. But this will not solve the fact, that the QPointF is based on a float and therefore there will be a loss of precicision for large 'unsigned long' values, does it?

Best regards!

Uwe
24th July 2017, 09:04
But this will not solve the fact, that the QPointF is based on a float and therefore there will be a loss of precision for large 'unsigned long' values, does it?
Yes sure, but it depends on your use case if it matters. F.e in case of using QwtDateScaleEngine it definitely hurts as a float is not enough to store ms since epoch ( see QwtDate::toDateTime ).

Note, that finally those qreals end up being translated into screen coordinates using a class derived from QwtTransform. Not sure if it helps in your case, but you might be able to shift your values so that they fit into the significance of a float and revert that shift later there.

Uwe

MrGentleman
24th July 2017, 11:50
Hello Uwe,

thank you very much. Then I think the only solution would be not to store absolute timestamps, but relative timestamps. By implementing a custom axis drawer which adds the deltas to a base timestamp value I can calculate the original absolute timestamp.

Thanks, michael!