1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-24 03:35:53 +01:00

Added support for GPX files with multiple tracks

This commit is contained in:
Martin Tůma 2016-02-08 17:53:09 +01:00
parent 82660caccb
commit 923a00479a
9 changed files with 179 additions and 159 deletions

View File

@ -31,11 +31,11 @@ void ElevationGraph::addInfo()
void ElevationGraph::loadGPX(const GPX &gpx)
{
for (int i = 0; i < gpx.count(); i++) {
QVector<QPointF> data;
qreal min, max, ascent = 0, descent = 0;
gpx.elevationGraph(data);
gpx.elevationGraph(i, data);
if (data.isEmpty())
return;
@ -64,6 +64,7 @@ void ElevationGraph::loadGPX(const GPX &gpx)
addInfo();
loadData(data);
}
}
void ElevationGraph::clear()
{

View File

@ -94,7 +94,7 @@ bool GPX::loadFile(const QString &fileName)
return false;
}
if (!(ret = _parser.loadFile(&file, _data))) {
if (!(ret = _parser.loadFile(&file, &_data))) {
_error = _parser.errorString();
_errorLine = _parser.errorLine();
}
@ -103,44 +103,46 @@ bool GPX::loadFile(const QString &fileName)
return ret;
}
void GPX::elevationGraph(QVector<QPointF> &graph) const
void GPX::elevationGraph(int i, QVector<QPointF> &graph) const
{
const QVector<TrackPoint> &data = _data.at(i);
qreal dist = 0;
QVector<QPointF> raw;
if (!_data.size())
if (!data.size())
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);
raw.append(QPointF(dist, _data.at(i).elevation
- _data.at(i).geoidheight));
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);
raw.append(QPointF(dist, data.at(i).elevation
- data.at(i).geoidheight));
}
graph = filter(raw, WINDOW_EF);
}
void GPX::speedGraph(QVector<QPointF> &graph) const
void GPX::speedGraph(int i, QVector<QPointF> &graph) const
{
const QVector<TrackPoint> &data = _data.at(i);
qreal dist = 0, v, ds, dt;
QVector<QPointF> raw;
if (!_data.size())
if (!data.size())
return;
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;
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 (data.at(i).speed < 0) {
if (dt == 0)
continue;
v = ds / dt;
} else
v = _data.at(i).speed;
v = data.at(i).speed;
raw.append(QPointF(dist, v));
}
@ -148,35 +150,42 @@ void GPX::speedGraph(QVector<QPointF> &graph) const
graph = filter(eliminate(raw, WINDOW_SE), WINDOW_SF);
}
void GPX::track(QVector<QPointF> &track) const
void GPX::track(int i, QVector<QPointF> &track) const
{
for (int i = 0; i < _data.size(); i++)
track.append(ll2mercator(_data.at(i).coordinates));
const QVector<TrackPoint> &data = _data.at(i);
for (int i = 0; i < data.size(); i++)
track.append(ll2mercator(data.at(i).coordinates));
}
qreal GPX::distance() const
qreal GPX::distance(int i) const
{
const QVector<TrackPoint> &data = _data.at(i);
qreal dist = 0;
for (int i = 1; i < _data.size(); i++)
dist += llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
for (int i = 1; i < data.size(); i++)
dist += llDistance(data.at(i).coordinates, data.at(i-1).coordinates);
return dist;
}
qreal GPX::time() const
qreal GPX::time(int i) const
{
if (_data.size() < 2)
const QVector<TrackPoint> &data = _data.at(i);
if (data.size() < 2)
return 0;
return (_data.at(0).timestamp.msecsTo(_data.at(_data.size() - 1).timestamp)
return (data.at(0).timestamp.msecsTo(data.at(data.size() - 1).timestamp)
/ 1000.0);
}
QDateTime GPX::date() const
QDateTime GPX::date(int i) const
{
if (_data.size())
return _data.at(0).timestamp;
const QVector<TrackPoint> &data = _data.at(i);
if (data.size())
return data.at(0).timestamp;
else
return QDateTime();
}

View File

@ -2,6 +2,7 @@
#define GPX_H
#include <QVector>
#include <QList>
#include <QPointF>
#include <QString>
#include "parser.h"
@ -13,16 +14,17 @@ public:
const QString &errorString() const {return _error;}
int errorLine() const {return _errorLine;}
void elevationGraph(QVector<QPointF> &graph) const;
void speedGraph(QVector<QPointF> &graph) const;
void track(QVector<QPointF> &track) const;
qreal distance() const;
qreal time() const;
QDateTime date() const;
int count() const {return _data.count();}
void elevationGraph(int i, QVector<QPointF> &graph) const;
void speedGraph(int i, QVector<QPointF> &graph) const;
void track(int i, QVector<QPointF> &track) const;
qreal distance(int i) const;
qreal time(int i) const;
QDateTime date(int i) const;
private:
Parser _parser;
QVector<TrackPoint> _data;
QList<QVector<TrackPoint> > _data;
QString _error;
int _errorLine;
};

View File

@ -67,6 +67,7 @@ GUI::GUI()
_distance = 0;
_time = 0;
_trackCount = 0;
resize(600, 800);
}
@ -443,8 +444,12 @@ bool GUI::loadFile(const QString &fileName)
if (_showPOIAction->isChecked())
_track->loadPOI(_poi);
_distance += gpx.distance();
_time += gpx.time();
for (int i = 0; i < gpx.count(); i++) {
_distance += gpx.distance(i);
_time += gpx.time(i);
}
_trackCount += gpx.count();
return true;
} else {
@ -571,6 +576,7 @@ void GUI::closeFile()
{
_distance = 0;
_time = 0;
_trackCount = 0;
_elevationGraph->clear();
_speedGraph->clear();
@ -621,17 +627,15 @@ void GUI::showToolbars(bool checked)
void GUI::updateStatusBarInfo()
{
int files = _files.size();
if (files == 0) {
if (_files.count() == 0) {
_fileNameLabel->clear();
_distanceLabel->clear();
_timeLabel->clear();
return;
} else if (files == 1)
} else if (_files.count() == 1)
_fileNameLabel->setText(_files.at(0));
else
_fileNameLabel->setText(tr("%1 tracks").arg(_files.size()));
_fileNameLabel->setText(tr("%1 tracks").arg(_trackCount));
if (_imperialUnitsAction->isChecked())
_distanceLabel->setText(QString::number(_distance * M2MI, 'f', 1)

View File

@ -126,6 +126,7 @@ private:
qreal _distance;
qreal _time;
int _trackCount;
};
#endif // GUI_H

View File

@ -1,96 +1,95 @@
#include "parser.h"
void Parser::handleExtensionData(QVector<TrackPoint> &data,
QStringRef element, const QString &value)
void Parser::handleExtensionData(QStringRef element, const QString &value)
{
if (element == "speed")
data.last().speed = value.toDouble();
_track->last().speed = value.toDouble();
}
void Parser::handleTrekPointData(QVector<TrackPoint> &data,
QStringRef element, const QString &value)
void Parser::handleTrekPointData(QStringRef element, const QString &value)
{
if (element == "ele")
data.last().elevation = value.toLatin1().toDouble();
_track->last().elevation = value.toLatin1().toDouble();
if (element == "time")
data.last().timestamp = QDateTime::fromString(value.toLatin1(),
_track->last().timestamp = QDateTime::fromString(value.toLatin1(),
Qt::ISODate);
if (element == "geoidheight")
data.last().geoidheight = value.toLatin1().toDouble();
_track->last().geoidheight = value.toLatin1().toDouble();
}
void Parser::handleTrekPointAttributes(QVector<TrackPoint> &data,
const QXmlStreamAttributes &attr)
void Parser::handleTrekPointAttributes(const QXmlStreamAttributes &attr)
{
data.last().coordinates.setY(attr.value("lat").toLatin1().toDouble());
data.last().coordinates.setX(attr.value("lon").toLatin1().toDouble());
_track->last().coordinates.setY(attr.value("lat").toLatin1().toDouble());
_track->last().coordinates.setX(attr.value("lon").toLatin1().toDouble());
}
void Parser::extensions(QVector<TrackPoint> &data)
void Parser::extensions()
{
while (_reader.readNextStartElement()) {
if (_reader.name() == "speed")
handleExtensionData(data, _reader.name(), _reader.readElementText());
handleExtensionData(_reader.name(), _reader.readElementText());
else
_reader.skipCurrentElement();
}
}
void Parser::trekPointData(QVector<TrackPoint> &data)
void Parser::trackPointData()
{
while (_reader.readNextStartElement()) {
if (_reader.name() == "ele" || _reader.name() == "time"
|| _reader.name() == "geoidheight")
handleTrekPointData(data, _reader.name(), _reader.readElementText());
handleTrekPointData(_reader.name(), _reader.readElementText());
else if (_reader.name() == "extensions")
extensions(data);
extensions();
else
_reader.skipCurrentElement();
}
}
void Parser::trekPoints(QVector<TrackPoint> &data)
void Parser::trackPoints()
{
QXmlStreamAttributes attr;
while (_reader.readNextStartElement()) {
if (_reader.name() == "trkpt") {
attr = _reader.attributes();
data.append(TrackPoint());
handleTrekPointAttributes(data, attr);
trekPointData(data);
_track->append(TrackPoint());
handleTrekPointAttributes(attr);
trackPointData();
} else
_reader.skipCurrentElement();
}
}
void Parser::trek(QVector<TrackPoint> &data)
void Parser::track()
{
while (_reader.readNextStartElement()) {
if (_reader.name() == "trkseg") {
trekPoints(data);
trackPoints();
} else
_reader.skipCurrentElement();
}
}
void Parser::gpx(QVector<TrackPoint> &data)
void Parser::gpx()
{
while (_reader.readNextStartElement()) {
if (_reader.name() == "trk")
trek(data);
else
if (_reader.name() == "trk") {
_data->append(QVector<TrackPoint>());
_track = &_data->back();
track();
} else
_reader.skipCurrentElement();
}
}
bool Parser::parse(QVector<TrackPoint> &data)
bool Parser::parse()
{
if (_reader.readNextStartElement()) {
if (_reader.name() == "gpx")
gpx(data);
gpx();
else
_reader.raiseError("Not a GPX file.");
}
@ -98,10 +97,11 @@ bool Parser::parse(QVector<TrackPoint> &data)
return !_reader.error();
}
bool Parser::loadFile(QIODevice *device, QVector<TrackPoint> &data)
bool Parser::loadFile(QIODevice *device, QList<QVector<TrackPoint> > *data)
{
_reader.clear();
_reader.setDevice(device);
_data = data;
return parse(data);
return parse();
}

View File

@ -19,26 +19,26 @@ struct TrackPoint
class Parser
{
public:
bool loadFile(QIODevice *device, QVector<TrackPoint> &data);
Parser() {_data = 0; _track = 0;}
bool loadFile(QIODevice *device, QList<QVector<TrackPoint> > *data);
QString errorString() const {return _reader.errorString();}
int errorLine() const {return _reader.lineNumber();}
private:
bool parse(QVector<TrackPoint> &data);
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);
bool parse();
void gpx();
void track();
void trackPoints();
void extensions();
void trackPointData();
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);
void handleTrekPointAttributes(const QXmlStreamAttributes &attr);
void handleTrekPointData(QStringRef element, const QString &value);
void handleExtensionData(QStringRef element, const QString &value);
QXmlStreamReader _reader;
QList<QVector<TrackPoint> > *_data;
QVector<TrackPoint> *_track;
};
#endif // PARSER_H

View File

@ -25,15 +25,15 @@ void SpeedGraph::addInfo()
void SpeedGraph::loadGPX(const GPX &gpx)
{
for (int i = 0; i < gpx.count(); i++) {
QVector<QPointF> data;
qreal max = 0;
gpx.speedGraph(data);
gpx.speedGraph(i, data);
if (data.isEmpty())
return;
_avg.append(QPointF(gpx.distance(), gpx.distance() / gpx.time()));
_avg.append(QPointF(gpx.distance(i), gpx.distance(i) / gpx.time(i)));
for (int i = 0; i < data.size(); i++)
max = qMax(max, data.at(i).y());
@ -42,6 +42,7 @@ void SpeedGraph::loadGPX(const GPX &gpx)
addInfo();
loadData(data);
}
}
qreal SpeedGraph::avg() const
{

View File

@ -41,6 +41,7 @@ Track::~Track()
void Track::loadGPX(const GPX &gpx)
{
for (int i = 0; i < gpx.count(); i++) {
QVector<QPointF> track;
QPainterPath path;
QGraphicsPathItem *pi;
@ -49,10 +50,10 @@ void Track::loadGPX(const GPX &gpx)
qreal prevScale = _scale;
gpx.track(track);
gpx.track(i, track);
if (track.size() < 2)
return;
continue;
_tracks.append(track);
@ -92,6 +93,7 @@ void Track::loadGPX(const GPX &gpx)
_mapScale->setLatitude(track.at(track.size() / 2).y());
_mapScale->setZoom(_zoom);
}
}
QRectF Track::trackBoundingRect() const
{