1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-07 07:13:21 +02:00
GPXSee/src/track.cpp

162 lines
3.3 KiB
C++
Raw Normal View History

2016-03-19 17:24:53 +01:00
#include <cmath>
2015-11-23 02:37:08 +01:00
#include "ll.h"
2015-10-05 01:43:48 +02:00
#include "track.h"
#define WINDOW_EF 3
#define WINDOW_SE 11
#define WINDOW_SF 11
2016-01-14 00:37:51 +01:00
static bool lt(const QPointF &p1, const QPointF &p2)
2015-10-05 01:43:48 +02:00
{
return p1.y() < p2.y();
2015-10-05 01:43:48 +02:00
}
static qreal median(QVector<QPointF> v)
2015-10-05 01:43:48 +02:00
{
qSort(v.begin(), v.end(), lt);
return v.at(v.size() / 2).y();
2015-10-05 01:43:48 +02:00
}
static qreal MAD(QVector<QPointF> v, qreal m)
2015-10-05 01:43:48 +02:00
{
for (int i = 0; i < v.size(); i++)
v[i].setY(qAbs(v.at(i).y() - m));
qSort(v.begin(), v.end(), lt);
return v.at(v.size() / 2).y();
2015-12-06 00:51:02 +01:00
}
static QVector<QPointF> eliminate(const QVector<QPointF> &v, int window)
2015-12-06 00:51:02 +01:00
{
QList<int> rm;
QVector<QPointF> ret;
qreal m, M;
2015-12-06 00:51:02 +01:00
2015-11-23 02:37:08 +01:00
if (v.size() < window)
return QVector<QPointF>(v);
2015-10-05 01:43:48 +02:00
for (int i = window/2; i < v.size() - window/2; i++) {
m = median(v.mid(i - window/2, window));
M = MAD(v.mid(i - window/2, window), m);
if (qAbs((0.6745 * (v.at(i).y() - m)) / M) > 3.5)
rm.append(i);
2015-11-25 23:17:39 +01:00
}
QList<int>::const_iterator it = rm.begin();
for (int i = 0; i < v.size(); i++) {
if (it == rm.end() || *it != i)
ret.append(v.at(i));
else
it++;
2015-11-25 23:17:39 +01:00
}
2015-11-23 02:37:08 +01:00
return ret;
2015-10-05 01:43:48 +02:00
}
static QVector<QPointF> filter(const QVector<QPointF> &v, int window)
2015-10-05 01:43:48 +02:00
{
qreal acc = 0;
QVector<QPointF> ret;
2015-12-06 00:51:02 +01:00
if (v.size() < window)
return QVector<QPointF>(v);
2015-10-05 01:43:48 +02:00
for (int i = 0; i < window; i++)
acc += v.at(i).y();
for (int i = 0; i <= window/2; i++)
ret.append(QPointF(v.at(i).x(), acc/window));
2015-10-05 01:43:48 +02:00
for (int i = window/2 + 1; i < v.size() - window/2; i++) {
acc += v.at(i + window/2).y() - v.at(i - (window/2 + 1)).y();
ret.append(QPointF(v.at(i).x(), acc/window));
2015-10-05 01:43:48 +02:00
}
for (int i = v.size() - window/2; i < v.size(); i++)
ret.append(QPointF(v.at(i).x(), acc/window));
2015-11-23 02:37:08 +01:00
return ret;
2016-01-14 00:37:51 +01:00
}
void Track::elevationGraph(QVector<QPointF> &graph) const
2015-11-23 02:37:08 +01:00
{
qreal dist = 0;
QVector<QPointF> raw;
2015-10-05 01:43:48 +02:00
if (!_data.size())
return;
if (isnan(_data.at(0).elevation))
return;
raw.append(QPointF(0, _data.at(0).elevation));
for (int i = 1; i < _data.size(); i++) {
dist += llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
if (isnan(_data.at(i).elevation))
return;
raw.append(QPointF(dist, _data.at(i).elevation
- _data.at(i).geoidheight));
2015-10-05 01:43:48 +02:00
}
graph = filter(raw, WINDOW_EF);
2015-10-05 01:43:48 +02:00
}
void Track::speedGraph(QVector<QPointF> &graph) const
2015-10-05 01:43:48 +02:00
{
qreal dist = 0, v, ds, dt;
QVector<QPointF> raw;
2015-10-05 01:43:48 +02:00
if (!_data.size())
return;
2015-10-05 01:43:48 +02:00
raw.append(QPointF(0, 0));
for (int i = 1; i < _data.size(); i++) {
ds = llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
dt = _data.at(i-1).timestamp.msecsTo(_data.at(i).timestamp) / 1000.0;
dist += ds;
2016-01-14 00:37:51 +01:00
if (isnan(_data.at(i).speed)) {
if (dt == 0)
continue;
v = ds / dt;
} else
v = _data.at(i).speed;
2015-10-05 01:43:48 +02:00
raw.append(QPointF(dist, v));
}
2015-10-05 01:43:48 +02:00
graph = filter(eliminate(raw, WINDOW_SE), WINDOW_SF);
2015-10-05 01:43:48 +02:00
}
void Track::track(QVector<QPointF> &track) const
2015-10-05 01:43:48 +02:00
{
for (int i = 0; i < _data.size(); i++)
track.append(_data.at(i).coordinates);
2015-10-05 01:43:48 +02:00
}
2015-11-23 02:37:08 +01:00
qreal Track::distance() const
2015-11-23 02:37:08 +01:00
{
qreal dist = 0;
2015-11-23 02:37:08 +01:00
for (int i = 1; i < _data.size(); i++)
dist += llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
2015-11-23 02:37:08 +01:00
return dist;
2015-11-23 02:37:08 +01:00
}
2015-12-20 09:33:40 +01:00
qreal Track::time() const
2015-12-20 09:33:40 +01:00
{
if (_data.size() < 2)
return 0;
2015-12-20 09:33:40 +01:00
return (_data.at(0).timestamp.msecsTo(_data.at(_data.size() - 1).timestamp)
/ 1000.0);
2015-12-20 09:33:40 +01:00
}
2016-01-14 00:37:51 +01:00
QDateTime Track::date() const
2016-01-14 00:37:51 +01:00
{
if (_data.size())
return _data.at(0).timestamp;
else
return QDateTime();
2016-01-14 00:37:51 +01:00
}