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

Added track statistics

This commit is contained in:
Martin Tůma 2015-10-12 01:12:12 +02:00
parent 5131a9d81d
commit 96e8415e00
15 changed files with 535 additions and 143 deletions

View File

@ -18,7 +18,10 @@ HEADERS += src/config.h \
src/colorshop.h \ src/colorshop.h \
src/keys.h \ src/keys.h \
src/slideritem.h \ src/slideritem.h \
src/markeritem.h src/markeritem.h \
src/infoitem.h \
src/elevationgraph.h \
src/speedgraph.h
SOURCES += src/main.cpp \ SOURCES += src/main.cpp \
src/gui.cpp \ src/gui.cpp \
src/gpx.cpp \ src/gpx.cpp \
@ -31,7 +34,10 @@ SOURCES += src/main.cpp \
src/poiitem.cpp \ src/poiitem.cpp \
src/colorshop.cpp \ src/colorshop.cpp \
src/slideritem.cpp \ src/slideritem.cpp \
src/markeritem.cpp src/markeritem.cpp \
src/infoitem.cpp \
src/elevationgraph.cpp \
src/speedgraph.cpp
RESOURCES += gpxsee.qrc RESOURCES += gpxsee.qrc
TRANSLATIONS = lang/gpxsee_cs.ts TRANSLATIONS = lang/gpxsee_cs.ts
macx:ICON = icons/gpxsee.icns macx:ICON = icons/gpxsee.icns

View File

@ -2,131 +2,163 @@
<!DOCTYPE TS> <!DOCTYPE TS>
<TS version="2.1" language="cs_CZ"> <TS version="2.1" language="cs_CZ">
<context> <context>
<name>GUI</name> <name>ElevationGraph</name>
<message> <message>
<location filename="../src/gui.cpp" line="68"/> <location filename="../src/elevationgraph.cpp" line="11"/>
<source>About Qt</source> <source>Distance</source>
<translation>O Qt</translation> <translation>Vzdálenost</translation>
</message> </message>
<message> <message>
<location filename="../src/gui.cpp" line="185"/> <location filename="../src/elevationgraph.cpp" line="12"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>Program GPXSee je distribuován pod podmínkami licence GNU General Public License verze 3. Pro více informací navštivte stránky programu na adrese </translation>
</message>
<message>
<location filename="../src/gui.cpp" line="193"/>
<source>Open file</source>
<translation>Otevřít soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="82"/>
<source>Save as</source>
<translation>Uložit jako</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="233"/>
<source>Open POI file</source>
<translation>Otevřít POI soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="73"/>
<source>Open</source>
<translation>Otevřít</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="61"/>
<source>Quit</source>
<translation>Ukončit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="77"/>
<source>Save</source>
<translation>Uložit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="87"/>
<source>Close</source>
<translation>Zavřít</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="94"/>
<source>Load file</source>
<translation>Nahrát soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="97"/>
<source>Show</source>
<translation>Zobrazit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="104"/>
<location filename="../src/gui.cpp" line="125"/>
<source>File</source>
<translation>Soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="114"/>
<location filename="../src/gui.cpp" line="133"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="118"/>
<source>Help</source>
<translation>Nápověda</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="148"/>
<location filename="../src/gui.cpp" line="153"/>
<source>Distance [km]</source>
<translation>Vzdálenost [km]</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="149"/>
<source>Elevation [m.a.s.l.]</source>
<translation>Výška [m.n.m.]</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="154"/>
<source>Speed [km/h]</source>
<translation>Rychlost [km/h]</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="159"/>
<source>Elevation</source> <source>Elevation</source>
<translation>Výška</translation> <translation>Výška</translation>
</message> </message>
<message> <message>
<location filename="../src/gui.cpp" line="160"/> <location filename="../src/elevationgraph.cpp" line="13"/>
<source>km</source>
<translation>km</translation>
</message>
<message>
<location filename="../src/elevationgraph.cpp" line="14"/>
<source>m</source>
<translation>m</translation>
</message>
<message>
<location filename="../src/elevationgraph.cpp" line="45"/>
<source>Ascent</source>
<translation>Stoupání</translation>
</message>
<message>
<location filename="../src/elevationgraph.cpp" line="46"/>
<source>Descent</source>
<translation>Klesání</translation>
</message>
<message>
<location filename="../src/elevationgraph.cpp" line="47"/>
<source>Minimum</source>
<translation>Minimum</translation>
</message>
<message>
<location filename="../src/elevationgraph.cpp" line="48"/>
<source>Maximum</source>
<translation>Maximum</translation>
</message>
</context>
<context>
<name>GUI</name>
<message>
<location filename="../src/gui.cpp" line="70"/>
<source>About Qt</source>
<translation>O Qt</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="181"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>Program GPXSee je distribuován pod podmínkami licence GNU General Public License verze 3. Pro více informací navštivte stránky programu na adrese </translation>
</message>
<message>
<location filename="../src/gui.cpp" line="189"/>
<source>Open file</source>
<translation>Otevřít soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="84"/>
<source>Save as</source>
<translation>Uložit jako</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="239"/>
<source>Open POI file</source>
<translation>Otevřít POI soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="75"/>
<source>Open</source>
<translation>Otevřít</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="63"/>
<source>Quit</source>
<translation>Ukončit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="79"/>
<source>Save</source>
<translation>Uložit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="89"/>
<source>Close</source>
<translation>Zavřít</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="96"/>
<source>Load file</source>
<translation>Nahrát soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="99"/>
<source>Show</source>
<translation>Zobrazit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="106"/>
<location filename="../src/gui.cpp" line="129"/>
<source>File</source>
<translation>Soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="118"/>
<location filename="../src/gui.cpp" line="137"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="122"/>
<source>Help</source>
<translation>Nápověda</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="155"/>
<source>Elevation</source>
<translation>Výška</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="156"/>
<source>Speed</source> <source>Speed</source>
<translation>Rychlost</translation> <translation>Rychlost</translation>
</message> </message>
<message> <message>
<location filename="../src/gui.cpp" line="66"/> <location filename="../src/gui.cpp" line="68"/>
<location filename="../src/gui.cpp" line="182"/> <location filename="../src/gui.cpp" line="178"/>
<source>About GPXSee</source> <source>About GPXSee</source>
<translation>O aplikaci GPXSee</translation> <translation>O aplikaci GPXSee</translation>
</message> </message>
<message> <message>
<location filename="../src/gui.cpp" line="184"/> <location filename="../src/gui.cpp" line="180"/>
<source>GPX viewer and analyzer</source> <source>GPX viewer and analyzer</source>
<translation>Prohlížeč a analyzátor GPX</translation> <translation>Prohlížeč a analyzátor GPX</translation>
</message> </message>
<message> <message>
<location filename="../src/gui.cpp" line="223"/> <location filename="../src/gui.cpp" line="223"/>
<location filename="../src/gui.cpp" line="237"/> <source>%1 tracks</source>
<translation>Počet tras: %1</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="229"/>
<location filename="../src/gui.cpp" line="243"/>
<source>Error</source> <source>Error</source>
<translation>Chyba</translation> <translation>Chyba</translation>
</message> </message>
<message> <message>
<location filename="../src/gui.cpp" line="224"/> <location filename="../src/gui.cpp" line="230"/>
<source>Error loading GPX file: <source>Error loading GPX file:
%1</source> %1</source>
<translation>Soubor GPX nelze otevřít: <translation>Soubor GPX nelze otevřít:
%1</translation> %1</translation>
</message> </message>
<message> <message>
<location filename="../src/gui.cpp" line="238"/> <location filename="../src/gui.cpp" line="244"/>
<source>Error loading POI file: <source>Error loading POI file:
%1</source> %1</source>
<translation>Soubor POI nelze otevřít: <translation>Soubor POI nelze otevřít:
@ -162,4 +194,37 @@ Line %1</source>
Rádka %1</translation> Rádka %1</translation>
</message> </message>
</context> </context>
<context>
<name>SpeedGraph</name>
<message>
<location filename="../src/speedgraph.cpp" line="7"/>
<source>Distance</source>
<translation>Vzdálenost</translation>
</message>
<message>
<location filename="../src/speedgraph.cpp" line="8"/>
<source>Speed</source>
<translation>Rychlost</translation>
</message>
<message>
<location filename="../src/speedgraph.cpp" line="9"/>
<source>km</source>
<translation></translation>
</message>
<message>
<location filename="../src/speedgraph.cpp" line="10"/>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<location filename="../src/speedgraph.cpp" line="42"/>
<source>Average</source>
<translation>Průměr</translation>
</message>
<message>
<location filename="../src/speedgraph.cpp" line="43"/>
<source>Maximum</source>
<translation>Maximum</translation>
</message>
</context>
</TS> </TS>

61
src/elevationgraph.cpp Normal file
View File

@ -0,0 +1,61 @@
#include <float.h>
#include "elevationgraph.h"
ElevationGraph::ElevationGraph()
{
_ascent = 0;
_descent = 0;
_max = -FLT_MAX;
_min = FLT_MAX;
Graph::setXLabel(tr("Distance"));
Graph::setYLabel(tr("Elevation"));
Graph::setXUnits(tr("km"));
Graph::setYUnits(tr("m"));
Graph::setXScale(0.001);
}
void ElevationGraph::loadData(const QVector<QPointF> &data)
{
qreal ascent = 0, descent = 0;
qreal min = data.at(0).y();
qreal max = data.at(0).y();
for (int i = 1; i < data.size(); i++) {
qreal cur = data.at(i).y();
qreal prev = data.at(i-1).y();
if (cur > prev)
ascent += cur - prev;
if (cur < prev)
descent += prev - cur;
if (cur > max)
max = cur;
if (cur < min)
min = cur;
}
_ascent += ascent;
_descent += descent;
_max = qMax(_max, max);
_min = qMin(_min, min);
addInfo(tr("Ascent"), QString::number((int)_ascent) + " " + _yUnits);
addInfo(tr("Descent"), QString::number((int)_descent) + " " + _yUnits);
addInfo(tr("Minimum"), QString::number((int)_min) + " " + _yUnits);
addInfo(tr("Maximum"), QString::number((int)_max) + " " + _yUnits);
Graph::loadData(data);
}
void ElevationGraph::clear()
{
_ascent = 0;
_descent = 0;
_max = -FLT_MAX;
_min = FLT_MAX;
Graph::clear();
}

19
src/elevationgraph.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef ELEVATIONGRAPH_H
#define ELEVATIONGRAPH_H
#include "graph.h"
class ElevationGraph : public Graph
{
public:
ElevationGraph();
void loadData(const QVector<QPointF> &data);
void clear();
private:
qreal _ascent, _descent;
qreal _max, _min;
};
#endif // ELEVATIONGRAPH_H

View File

@ -4,7 +4,7 @@
#include "gpx.h" #include "gpx.h"
#define ALPHA_E 0.9 #define ALPHA_E 0.5
#define ALPHA_S 0.1 #define ALPHA_S 0.1
bool GPX::loadFile(const QString &fileName) bool GPX::loadFile(const QString &fileName)
@ -27,13 +27,12 @@ bool GPX::loadFile(const QString &fileName)
return ret; return ret;
} }
QVector<QPointF> GPX::elevationGraph() const void GPX::elevationGraph(QVector<QPointF> &graph) const
{ {
QVector<QPointF> graph;
qreal dist = 0, ds, dh, acc; qreal dist = 0, ds, dh, acc;
if (!_data.size()) if (!_data.size())
return graph; return;
graph.append(QPointF(0, _data.at(0).elevation)); graph.append(QPointF(0, _data.at(0).elevation));
for (int i = 1; i < _data.size(); i++) { for (int i = 1; i < _data.size(); i++) {
@ -43,40 +42,34 @@ QVector<QPointF> GPX::elevationGraph() const
acc = (i == 1) ? dh : (ALPHA_E * dh) + (1.0 - ALPHA_E) * acc; acc = (i == 1) ? dh : (ALPHA_E * dh) + (1.0 - ALPHA_E) * acc;
graph.append(QPointF(dist, acc)); graph.append(QPointF(dist, acc));
} }
return graph;
} }
QVector<QPointF> GPX::speedGraph() const void GPX::speedGraph(QVector<QPointF> &graph) const
{ {
QVector<QPointF> graph;
qreal dist = 0, v, ds, dt, acc; qreal dist = 0, v, ds, dt, acc;
if (!_data.size()) if (!_data.size())
return graph; return;
graph.append(QPointF(0, 0)); graph.append(QPointF(0, 0));
for (int i = 1; i < _data.size(); i++) { for (int i = 1; i < _data.size(); i++) {
ds = llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates); ds = llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
dt = _data.at(i-1).timestamp.msecsTo(_data.at(i).timestamp) / 1000.0; dt = _data.at(i-1).timestamp.msecsTo(_data.at(i).timestamp) / 1000.0;
if (dt == 0)
continue;
dist += ds; dist += ds;
v = ds / dt; v = ds / dt;
acc = (i == 1) ? v : (ALPHA_S * v) + (1.0 - ALPHA_S) * acc; acc = (i == 1) ? v : (ALPHA_S * v) + (1.0 - ALPHA_S) * acc;
graph.append(QPointF(dist, acc)); graph.append(QPointF(dist, acc));
} }
return graph;
} }
QVector<QPointF> GPX::track() const void GPX::track(QVector<QPointF> &track) const
{ {
QVector<QPointF> track;
QPointF p; QPointF p;
for (int i = 0; i < _data.size(); i++) { for (int i = 0; i < _data.size(); i++) {
ll2mercator(_data.at(i).coordinates, p); ll2mercator(_data.at(i).coordinates, p);
track.append(p); track.append(p);
} }
return track;
} }

View File

@ -11,9 +11,10 @@ class GPX
public: public:
bool loadFile(const QString &fileName); bool loadFile(const QString &fileName);
const QString &errorString() const {return _error;} const QString &errorString() const {return _error;}
QVector<QPointF> elevationGraph() const;
QVector<QPointF> speedGraph() const; void elevationGraph(QVector<QPointF> &graph) const;
QVector<QPointF> track() const; void speedGraph(QVector<QPointF> &graph) const;
void track(QVector<QPointF> &track) const;
private: private:
Parser _parser; Parser _parser;

View File

@ -2,6 +2,8 @@
#include <QGraphicsView> #include <QGraphicsView>
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QEvent> #include <QEvent>
#include "slideritem.h"
#include "infoitem.h"
#include "graph.h" #include "graph.h"
#include <QDebug> #include <QDebug>
@ -18,9 +20,12 @@ Graph::Graph(QWidget *parent)
_yAxis = new AxisItem(AxisItem::Y); _yAxis = new AxisItem(AxisItem::Y);
_slider = new SliderItem(); _slider = new SliderItem();
_slider->setZValue(2.0);
connect(_slider, SIGNAL(positionChanged(const QPointF&)), this, connect(_slider, SIGNAL(positionChanged(const QPointF&)), this,
SLOT(emitSliderPositionChanged(const QPointF&))); SLOT(emitSliderPositionChanged(const QPointF&)));
_info = new InfoItem();
_xMax = -FLT_MAX; _xMax = -FLT_MAX;
_xMin = FLT_MAX; _xMin = FLT_MAX;
_yMax = -FLT_MAX; _yMax = -FLT_MAX;
@ -40,6 +45,9 @@ Graph::~Graph()
if (_slider->scene() != _scene) if (_slider->scene() != _scene)
delete _slider; delete _slider;
if (_info->scene() != _scene)
delete _info;
delete _scene; delete _scene;
} }
@ -55,6 +63,40 @@ void Graph::updateBounds(const QPointF &point)
_yMax = point.y(); _yMax = point.y();
} }
void Graph::createXLabel()
{
_xAxis->setLabel(QString("%1 [%2]").arg(_xLabel).arg(_xUnits));
}
void Graph::createYLabel()
{
_yAxis->setLabel(QString("%1 [%2]").arg(_yLabel).arg(_yUnits));
}
void Graph::setXLabel(const QString &label)
{
_xLabel = label;
createXLabel();
}
void Graph::setYLabel(const QString &label)
{
_yLabel = label;
createYLabel();
}
void Graph::setXUnits(const QString &units)
{
_xUnits = units;
createXLabel();
}
void Graph::setYUnits(const QString &units)
{
_yUnits = units;
createYLabel();
}
void Graph::loadData(const QVector<QPointF> &data) void Graph::loadData(const QVector<QPointF> &data)
{ {
QPainterPath path; QPainterPath path;
@ -95,20 +137,22 @@ void Graph::resize(const QSizeF &size)
_scene->removeItem(_xAxis); _scene->removeItem(_xAxis);
if (_yAxis->scene() == _scene) if (_yAxis->scene() == _scene)
_scene->removeItem(_yAxis); _scene->removeItem(_yAxis);
_xAxis->setRange(QPointF(_xMin * _xScale, _xMax * _xScale));
_yAxis->setRange(QPointF(_yMin * _yScale, _yMax * _yScale));
if (_slider->scene() == _scene) if (_slider->scene() == _scene)
_scene->removeItem(_slider); _scene->removeItem(_slider);
if (_info->scene() == _scene)
_scene->removeItem(_info);
for (int i = 0; i < _graphs.size(); i++) for (int i = 0; i < _graphs.size(); i++)
_graphs.at(i)->resetTransform(); _graphs.at(i)->resetTransform();
_xAxis->setRange(QPointF(_xMin * _xScale, _xMax * _xScale));
_yAxis->setRange(QPointF(_yMin * _yScale, _yMax * _yScale));
mx = _xAxis->margin(); mx = _xAxis->margin();
my = _yAxis->margin(); my = _yAxis->margin();
r = _scene->itemsBoundingRect(); r = _scene->itemsBoundingRect();
xs = (size.width() - (my.width() + mx.width())) / r.width(); xs = (size.width() - (my.width() + mx.width())) / r.width();
ys = (size.height() - (mx.height() + my.height())) / r.height(); ys = (size.height() - (mx.height() + my.height())
- _info->boundingRect().height()) / r.height();
transform.scale(xs, ys); transform.scale(xs, ys);
for (int i = 0; i < _graphs.size(); i++) for (int i = 0; i < _graphs.size(); i++)
@ -126,6 +170,11 @@ void Graph::resize(const QSizeF &size)
_slider->setPos(r.bottomLeft()); _slider->setPos(r.bottomLeft());
_scene->addItem(_slider); _scene->addItem(_slider);
r = _scene->itemsBoundingRect();
_info->setPos(r.topLeft() + QPointF(r.width()/2
- _info->boundingRect().width()/2, -_info->boundingRect().height()));
_scene->addItem(_info);
_scene->setSceneRect(_scene->itemsBoundingRect()); _scene->setSceneRect(_scene->itemsBoundingRect());
} }
@ -158,6 +207,9 @@ void Graph::clear()
if (_slider->scene() == _scene) if (_slider->scene() == _scene)
_scene->removeItem(_slider); _scene->removeItem(_slider);
if (_info->scene() == _scene)
_scene->removeItem(_info);
_scene->clear(); _scene->clear();
_graphs.clear(); _graphs.clear();
_colorShop.reset(); _colorShop.reset();
@ -185,3 +237,8 @@ void Graph::setSliderPosition(qreal pos)
{ {
_slider->setPos(pos * _slider->area().width(), 0); _slider->setPos(pos * _slider->area().width(), 0);
} }
void Graph::addInfo(const QString &key, const QString &value)
{
_info->insert(key, value);
}

View File

@ -6,10 +6,12 @@
#include <QList> #include <QList>
#include <QPointF> #include <QPointF>
#include "axisitem.h" #include "axisitem.h"
#include "slideritem.h"
#include "colorshop.h" #include "colorshop.h"
class SliderItem;
class InfoItem;
class Graph : public QGraphicsView class Graph : public QGraphicsView
{ {
Q_OBJECT Q_OBJECT
@ -19,8 +21,10 @@ public:
~Graph(); ~Graph();
void loadData(const QVector<QPointF> &data); void loadData(const QVector<QPointF> &data);
void setXLabel(const QString &label) {_xAxis->setLabel(label);} void setXLabel(const QString &label);
void setYLabel(const QString &label) {_yAxis->setLabel(label);} void setYLabel(const QString &label);
void setXUnits(const QString &units);
void setYUnits(const QString &units);
void setXScale(qreal scale) {_xScale = scale;} void setXScale(qreal scale) {_xScale = scale;}
void setYScale(qreal scale) {_yScale = scale;} void setYScale(qreal scale) {_yScale = scale;}
@ -30,16 +34,24 @@ public:
qreal sliderPosition() const; qreal sliderPosition() const;
void setSliderPosition(qreal pos); void setSliderPosition(qreal pos);
void addInfo(const QString &key, const QString &value);
signals: signals:
void sliderPositionChanged(qreal); void sliderPositionChanged(qreal);
protected: protected:
void resizeEvent(QResizeEvent *); void resizeEvent(QResizeEvent *);
qreal _xScale, _yScale;
QString _xUnits, _yUnits;
QString _xLabel, _yLabel;
private slots: private slots:
void emitSliderPositionChanged(const QPointF &pos); void emitSliderPositionChanged(const QPointF &pos);
private: private:
void createXLabel();
void createYLabel();
void updateBounds(const QPointF &point); void updateBounds(const QPointF &point);
void resize(const QSizeF &size); void resize(const QSizeF &size);
@ -47,9 +59,11 @@ private:
QGraphicsScene *_scene; QGraphicsScene *_scene;
AxisItem *_xAxis, *_yAxis; AxisItem *_xAxis, *_yAxis;
SliderItem *_slider; SliderItem *_slider;
qreal _xMin, _xMax, _yMin, _yMax; InfoItem *_info;
QList<QGraphicsPathItem*> _graphs; QList<QGraphicsPathItem*> _graphs;
qreal _xScale, _yScale;
qreal _xMin, _xMax, _yMin, _yMax;
ColorShop _colorShop; ColorShop _colorShop;
}; };

View File

@ -13,7 +13,8 @@
#include "icons.h" #include "icons.h"
#include "keys.h" #include "keys.h"
#include "gpx.h" #include "gpx.h"
#include "graph.h" #include "elevationgraph.h"
#include "speedgraph.h"
#include "track.h" #include "track.h"
#include <QDebug> #include <QDebug>
@ -45,6 +46,7 @@ GUI::GUI()
setUnifiedTitleAndToolBarOnMac(true); setUnifiedTitleAndToolBarOnMac(true);
_dirIndex = -1; _dirIndex = -1;
_files = 0;
resize(600, 800); resize(600, 800);
} }
@ -146,16 +148,8 @@ void GUI::createTrackView()
void GUI::createTrackGraphs() void GUI::createTrackGraphs()
{ {
_elevationGraph = new Graph; _elevationGraph = new ElevationGraph;
_elevationGraph->setXLabel(tr("Distance [km]")); _speedGraph = new SpeedGraph;
_elevationGraph->setYLabel(tr("Elevation [m.a.s.l.]"));
_elevationGraph->setXScale(0.001);
_speedGraph = new Graph;
_speedGraph->setXLabel(tr("Distance [km]"));
_speedGraph->setYLabel(tr("Speed [km/h]"));
_speedGraph->setXScale(0.001);
_speedGraph->setYScale(3.6);
_trackGraphs = new QTabWidget; _trackGraphs = new QTabWidget;
_trackGraphs->addTab(_elevationGraph, tr("Elevation")); _trackGraphs->addTab(_elevationGraph, tr("Elevation"));
@ -207,17 +201,28 @@ void GUI::openFile()
bool GUI::openFile(const QString &fileName) bool GUI::openFile(const QString &fileName)
{ {
GPX gpx; GPX gpx;
QVector<QPointF> elevation;
QVector<QPointF> speed;
QVector<QPointF> track;
if (!fileName.isEmpty()) { if (!fileName.isEmpty()) {
if (gpx.loadFile(fileName)) { if (gpx.loadFile(fileName)) {
_elevationGraph->loadData(gpx.elevationGraph()); gpx.elevationGraph(elevation);
_speedGraph->loadData(gpx.speedGraph()); gpx.speedGraph(speed);
_track->loadData(gpx.track()); gpx.track(track);
_elevationGraph->loadData(elevation);
_speedGraph->loadData(speed);
_track->loadData(track);
if (_showPOIAction->isChecked()) if (_showPOIAction->isChecked())
_track->loadPOI(_poi); _track->loadPOI(_poi);
_fileActionGroup->setEnabled(true); _fileActionGroup->setEnabled(true);
_fileName->setText(fileName);
if (++_files > 1)
_fileName->setText(tr("%1 tracks").arg(_files));
else
_fileName->setText(fileName);
return true; return true;
} else { } else {
@ -283,6 +288,8 @@ void GUI::saveFile(const QString &fileName)
void GUI::closeFile() void GUI::closeFile()
{ {
_files = 0;
_elevationGraph->clear(); _elevationGraph->clear();
_speedGraph->clear(); _speedGraph->clear();
_track->clear(); _track->clear();

View File

@ -12,7 +12,8 @@
#include <QFileInfoList> #include <QFileInfoList>
#include "poi.h" #include "poi.h"
class Graph; class ElevationGraph;
class SpeedGraph;
class Track; class Track;
class GUI : public QMainWindow class GUI : public QMainWindow
@ -70,8 +71,8 @@ private:
QLabel *_fileName; QLabel *_fileName;
QLabel *_zoom; QLabel *_zoom;
Graph *_elevationGraph; ElevationGraph *_elevationGraph;
Graph *_speedGraph; SpeedGraph *_speedGraph;
Track *_track; Track *_track;
POI _poi; POI _poi;
@ -80,6 +81,7 @@ private:
int _dirIndex; int _dirIndex;
QString _saveFileName; QString _saveFileName;
unsigned _files;
}; };
#endif // GUI_H #endif // GUI_H

70
src/infoitem.cpp Normal file
View File

@ -0,0 +1,70 @@
#include <QFont>
#include <QPainter>
#include "infoitem.h"
#define FONT_FAMILY "Arial"
#define FONT_SIZE 12
#define PADDING 10
InfoItem::InfoItem()
{
}
QRectF InfoItem::boundingRect() const
{
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
QFontMetrics fm(font);
QMap<QString, QString>::const_iterator i;
int width = 0;
if (_map.isEmpty())
return QRectF();
for (i = _map.constBegin(); i != _map.constEnd(); i++) {
width += fm.width(i.key() + ": ");
width += fm.width(i.value()) + ((i == _map.end() - 1) ? 0 : PADDING);
}
return QRectF(0, 0, width, fm.height());
}
void InfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
painter->setFont(font);
QFontMetrics fm(font);
QMap<QString, QString>::const_iterator i;
int width = 0;
for (i = _map.constBegin(); i != _map.constEnd(); i++) {
painter->drawText(width, fm.height() - fm.descent(), i.key() + ": ");
width += fm.width(i.key() + ": ");
painter->drawText(width, fm.height() - fm.descent(), i.value());
width += fm.width(i.value()) + ((i == _map.end() - 1) ? 0 : PADDING);
if (i != _map.end() - 1) {
painter->save();
painter->setPen(Qt::gray);
painter->drawLine(width - PADDING/2, fm.descent(),
width - PADDING/2, fm.height() - fm.descent());
painter->restore();
}
}
/*
painter->setPen(Qt::red);
painter->drawRect(boundingRect());
*/
}
void InfoItem::insert(const QString &key, const QString &value)
{
_map.insert(key, value);
}

22
src/infoitem.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef INFOITEM_H
#define INFOITEM_H
#include <QGraphicsItem>
#include <QMap>
class InfoItem : public QGraphicsItem
{
public:
InfoItem();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
void insert(const QString &key, const QString &value);
private:
QMap<QString, QString> _map;
};
#endif // INFOITEM_H

56
src/speedgraph.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "speedgraph.h"
SpeedGraph::SpeedGraph()
{
_max = 0;
Graph::setXLabel(tr("Distance"));
Graph::setYLabel(tr("Speed"));
Graph::setXUnits(tr("km"));
Graph::setYUnits(tr("km/h"));
Graph::setXScale(0.001);
Graph::setYScale(3.6);
}
void SpeedGraph::loadData(const QVector<QPointF> &data)
{
qreal max = 0, sum = 0, avg, distance, w;
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();
sum += val;
if (val > max)
max = val;
}
avg = sum / data.size();
_avg.append(QPointF(avg, distance));
sum = 0; w = 0;
for (QList<QPointF>::iterator it = _avg.begin(); it != _avg.end(); it++) {
sum += it->x() * it->y();
w += it->y();
}
avg = sum / w;
_max = qMax(_max, max);
addInfo(tr("Average"), QString::number(avg * _yScale, 'f', 1)
+ " " + _yUnits);
addInfo(tr("Maximum"), QString::number(_max * _yScale, 'f', 1)
+ " " + _yUnits);
Graph::loadData(data);
}
void SpeedGraph::clear()
{
_max = 0;
_avg.clear();
Graph::clear();
}

20
src/speedgraph.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef SPEEDGRAPH_H
#define SPEEDGRAPH_H
#include <QList>
#include "graph.h"
class SpeedGraph : public Graph
{
public:
SpeedGraph();
void loadData(const QVector<QPointF> &data);
void clear();
private:
qreal _max;
QList<QPointF> _avg;
};
#endif // SPEEDGRAPH_H

View File

@ -62,7 +62,6 @@ void Track::loadData(const QVector<QPointF> &track)
mi->setPos(pi->path().pointAtPercent(0)); mi->setPos(pi->path().pointAtPercent(0));
_markers.append(mi); _markers.append(mi);
for (int i = 0; i < _trackPaths.size(); i++) { for (int i = 0; i < _trackPaths.size(); i++) {
_markers.at(i)->setTransform(t); _markers.at(i)->setTransform(t);
_scene->addItem(_markers.at(i)); _scene->addItem(_markers.at(i));