mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-27 21:24:47 +01:00
Use NMEA speed data if available
Now using median speed filtering
This commit is contained in:
parent
da42f3ab33
commit
405c1d2dde
36
src/gpx.cpp
36
src/gpx.cpp
@ -3,9 +3,12 @@
|
||||
#include "ll.h"
|
||||
#include "gpx.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
#define ALPHA 0.5
|
||||
#define WINDOW 5
|
||||
|
||||
#define ALPHA_E 0.5
|
||||
#define ALPHA_S 0.1
|
||||
|
||||
bool GPX::loadFile(const QString &fileName)
|
||||
{
|
||||
@ -38,14 +41,25 @@ void GPX::elevationGraph(QVector<QPointF> &graph) const
|
||||
for (int i = 1; i < _data.size(); i++) {
|
||||
dist += llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
|
||||
dh = _data.at(i).elevation;
|
||||
acc = (i == 1) ? dh : (ALPHA_E * dh) + (1.0 - ALPHA_E) * acc;
|
||||
acc = (i == 1) ? dh : (ALPHA * dh) + (1.0 - ALPHA) * acc;
|
||||
graph.append(QPointF(dist, acc));
|
||||
}
|
||||
}
|
||||
|
||||
static bool lt(const QPointF &p1, const QPointF &p2)
|
||||
{
|
||||
return p1.y() < p2.y();
|
||||
}
|
||||
|
||||
static qreal median(QVector<QPointF> v)
|
||||
{
|
||||
qSort(v.begin(), v.end(), lt);
|
||||
return v.at(v.size() / 2).y();
|
||||
}
|
||||
|
||||
void GPX::speedGraph(QVector<QPointF> &graph) const
|
||||
{
|
||||
qreal dist = 0, v, ds, dt, acc;
|
||||
qreal dist = 0, v, ds, dt;
|
||||
|
||||
if (!_data.size())
|
||||
return;
|
||||
@ -54,13 +68,21 @@ void GPX::speedGraph(QVector<QPointF> &graph) const
|
||||
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;
|
||||
|
||||
if (_data.at(i).speed < 0) {
|
||||
if (dt == 0)
|
||||
continue;
|
||||
dist += ds;
|
||||
v = ds / dt;
|
||||
acc = (i == 1) ? v : (ALPHA_S * v) + (1.0 - ALPHA_S) * acc;
|
||||
graph.append(QPointF(dist, acc));
|
||||
} else
|
||||
v = _data.at(i).speed;
|
||||
|
||||
graph.append(QPointF(dist, v));
|
||||
}
|
||||
|
||||
if (graph.size() > WINDOW)
|
||||
for (int i = WINDOW/2; i < graph.size() - WINDOW/2; i++)
|
||||
graph[i].setY(median(graph.mid(i - WINDOW/2, WINDOW)));
|
||||
}
|
||||
|
||||
void GPX::track(QVector<QPointF> &track) const
|
||||
|
@ -1,5 +1,14 @@
|
||||
#include "parser.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
void Parser::handleExtensionData(QVector<TrackPoint> &data,
|
||||
QStringRef element, const QString &value)
|
||||
{
|
||||
if (element == "speed")
|
||||
data.last().speed = value.toDouble();
|
||||
}
|
||||
|
||||
void Parser::handleTrekPointData(QVector<TrackPoint> &data,
|
||||
QStringRef element, const QString &value)
|
||||
@ -19,11 +28,23 @@ void Parser::handleTrekPointAttributes(QVector<TrackPoint> &data,
|
||||
}
|
||||
|
||||
|
||||
void Parser::extensions(QVector<TrackPoint> &data)
|
||||
{
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == "speed")
|
||||
handleExtensionData(data, _reader.name(), _reader.readElementText());
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::trekPointData(QVector<TrackPoint> &data)
|
||||
{
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == "ele" || _reader.name() == "time")
|
||||
handleTrekPointData(data, _reader.name(), _reader.readElementText());
|
||||
else if (_reader.name() == "extensions")
|
||||
extensions(data);
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
|
@ -10,6 +10,9 @@ struct TrackPoint
|
||||
QPointF coordinates;
|
||||
QDateTime timestamp;
|
||||
qreal elevation;
|
||||
qreal speed;
|
||||
|
||||
TrackPoint() {speed = -1;}
|
||||
};
|
||||
|
||||
class Parser
|
||||
@ -23,12 +26,15 @@ private:
|
||||
void gpx(QVector<TrackPoint> &data);
|
||||
void trek(QVector<TrackPoint> &data);
|
||||
void trekPoints(QVector<TrackPoint> &data);
|
||||
void extensions(QVector<TrackPoint> &data);
|
||||
void trekPointData(QVector<TrackPoint> &data);
|
||||
|
||||
void handleTrekPointAttributes(QVector<TrackPoint> &data,
|
||||
const QXmlStreamAttributes &attr);
|
||||
void handleTrekPointData(QVector<TrackPoint> &data, QStringRef element,
|
||||
const QString &value);
|
||||
void handleExtensionData(QVector<TrackPoint> &data, QStringRef element,
|
||||
const QString &value);
|
||||
|
||||
QXmlStreamReader _reader;
|
||||
};
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "speedgraph.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
SpeedGraph::SpeedGraph()
|
||||
{
|
||||
_max = 0;
|
||||
@ -14,26 +16,35 @@ SpeedGraph::SpeedGraph()
|
||||
|
||||
void SpeedGraph::loadData(const QVector<QPointF> &data)
|
||||
{
|
||||
qreal max = 0, sum = 0, avg, distance, w;
|
||||
qreal max = 0, sum = 0, w = 0, avg;
|
||||
qreal dist;
|
||||
|
||||
if (data.size() < 2)
|
||||
return;
|
||||
|
||||
dist = data.at(data.size() - 1).x() - data.at(0).x();
|
||||
|
||||
distance = (data.at(data.size() - 1).x() - data.at(0).x());
|
||||
|
||||
for (int i = 1; i < data.size(); i++) {
|
||||
qreal val = data.at(i).y();
|
||||
QPointF cur = data.at(i);
|
||||
QPointF prev = data.at(i-1);
|
||||
qreal ds = cur.x() - prev.x();
|
||||
|
||||
sum += val;
|
||||
if (cur.y() == 0)
|
||||
continue;
|
||||
sum += ds;
|
||||
w += ds / cur.y();
|
||||
|
||||
if (val > max)
|
||||
max = val;
|
||||
max = qMax(max, cur.y());
|
||||
}
|
||||
avg = sum / data.size();
|
||||
avg = sum / w;
|
||||
|
||||
_avg.append(QPointF(avg, distance));
|
||||
_avg.append(QPointF(dist, avg));
|
||||
|
||||
sum = 0; w = 0;
|
||||
for (QList<QPointF>::iterator it = _avg.begin(); it != _avg.end(); it++) {
|
||||
sum += it->x() * it->y();
|
||||
w += it->y();
|
||||
sum += it->y() * it->x();
|
||||
w += it->x();
|
||||
}
|
||||
avg = sum / w;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user