1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-06-27 03:29:16 +02:00

Enable simultaneous display of GPS and DEM data

This commit is contained in:
2020-03-25 23:08:26 +01:00
parent 441c738d0f
commit 19a847c7d4
33 changed files with 402 additions and 191 deletions

View File

@ -20,7 +20,6 @@
#include "cupparser.h"
#include "gpiparser.h"
#include "smlparser.h"
#include "dem.h"
#include "data.h"
@ -73,49 +72,17 @@ static QMap<QString, Parser*> parsers()
return map;
}
QMap<QString, Parser*> Data::_parsers = parsers();
bool Data::_useDEM = false;
void Data::processData(QList<TrackData> &trackData, QList<RouteData> &routeData)
{
for (int i = 0; i < trackData.count(); i++) {
TrackData &track = trackData[i];
for (int j = 0; j < track.size(); j++) {
SegmentData &segment = track[j];
for (int k = 0; k < segment.size(); k++) {
Trackpoint &t = segment[k];
if (!t.hasElevation() || _useDEM) {
qreal elevation = DEM::elevation(t.coordinates());
if (!std::isnan(elevation))
t.setElevation(elevation);
}
}
}
for (int i = 0; i < trackData.count(); i++)
_tracks.append(Track(trackData.at(i)));
}
for (int i = 0; i < routeData.count(); i++) {
RouteData &route = routeData[i];
for (int j = 0; j < route.size(); j++) {
Waypoint &w = route[j];
if (!w.hasElevation() || _useDEM) {
qreal elevation = DEM::elevation(w.coordinates());
if (!std::isnan(elevation))
w.setElevation(elevation);
}
}
for (int i = 0; i < routeData.count(); i++)
_routes.append(Route(routeData.at(i)));
}
for (int i = 0; i < _waypoints.size(); i++) {
if (!_waypoints.at(i).hasElevation() || _useDEM) {
qreal elevation = DEM::elevation(_waypoints.at(i).coordinates());
if (!std::isnan(elevation))
_waypoints[i].setElevation(elevation);
}
}
}
Data::Data(const QString &fileName, bool poi)
Data::Data(const QString &fileName)
{
QFile file(fileName);
QFileInfo fi(fileName);
@ -134,8 +101,7 @@ Data::Data(const QString &fileName, bool poi)
if ((it = _parsers.find(fi.suffix().toLower())) != _parsers.end()) {
if (it.value()->parse(&file, trackData, routeData, _polygons,
_waypoints)) {
if (!poi)
processData(trackData, routeData);
processData(trackData, routeData);
_valid = true;
return;
} else {
@ -146,8 +112,7 @@ Data::Data(const QString &fileName, bool poi)
for (it = _parsers.begin(); it != _parsers.end(); it++) {
if (it.value()->parse(&file, trackData, routeData, _polygons,
_waypoints)) {
if (!poi)
processData(trackData, routeData);
processData(trackData, routeData);
_valid = true;
return;
}
@ -198,8 +163,3 @@ QStringList Data::filter()
return filter;
}
void Data::useDEM(bool use)
{
_useDEM = use;
}

View File

@ -14,7 +14,7 @@
class Data
{
public:
Data(const QString &fileName, bool poi = false);
Data(const QString &fileName);
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
@ -28,8 +28,6 @@ public:
static QString formats();
static QStringList filter();
static void useDEM(bool use);
private:
void processData(QList<TrackData> &trackData, QList<RouteData> &routeData);
@ -43,7 +41,6 @@ private:
QVector<Waypoint> _waypoints;
static QMap<QString, Parser*> _parsers;
static bool _useDEM;
};
#endif // DATA_H

View File

@ -67,4 +67,17 @@ public:
}
};
class GraphPair
{
public:
GraphPair(const Graph &primary, const Graph &secondary)
: _primary(primary), _secondary(secondary) {}
const Graph &primary() const {return _primary;}
const Graph &secondary() const {return _secondary;}
private:
Graph _primary, _secondary;
};
#endif // GRAPH_H

View File

@ -14,12 +14,11 @@ POI::POI(QObject *parent) : QObject(parent)
{
_errorLine = 0;
_radius = 1000;
_useDEM = false;
}
bool POI::loadFile(const QString &path)
{
Data data(path, true);
Data data(path);
FileIndex index;
index.enabled = true;
@ -89,17 +88,6 @@ void POI::search(const RectC &rect, QSet<int> &set) const
_tree.Search(min, max, cb, &set);
}
void POI::appendElevation(QList<Waypoint> &points) const
{
for (int i = 0; i < points.size(); i++) {
if (!points.at(i).hasElevation() || _useDEM) {
qreal elevation = DEM::elevation(points.at(i).coordinates());
if (!std::isnan(elevation))
points[i].setElevation(elevation);
}
}
}
QList<Waypoint> POI::points(const Path &path) const
{
QList<Waypoint> ret;
@ -135,8 +123,6 @@ QList<Waypoint> POI::points(const Path &path) const
for (it = set.constBegin(); it != set.constEnd(); ++it)
ret.append(_data.at(*it));
appendElevation(ret);
return ret;
}
@ -158,8 +144,6 @@ QList<Waypoint> POI::points(const Waypoint &point) const
for (it = set.constBegin(); it != set.constEnd(); ++it)
ret.append(_data.at(*it));
appendElevation(ret);
return ret;
}
@ -183,8 +167,6 @@ QList<Waypoint> POI::points(const Area &area) const
for (it = set.constBegin(); it != set.constEnd(); ++it)
ret.append(_data.at(*it));
appendElevation(ret);
return ret;
}
@ -230,10 +212,3 @@ void POI::setRadius(unsigned radius)
emit pointsChanged();
}
void POI::useDEM(bool use)
{
_useDEM = use;
emit pointsChanged();
}

View File

@ -26,7 +26,6 @@ public:
unsigned radius() const {return _radius;}
void setRadius(unsigned radius);
void useDEM(bool use);
QList<Waypoint> points(const Path &path) const;
QList<Waypoint> points(const Waypoint &point) const;
@ -49,7 +48,6 @@ private:
bool loadFile(const QString &path, bool dir);
void search(const RectC &rect, QSet<int> &set) const;
void appendElevation(QList<Waypoint> &points) const;
POITree _tree;
QVector<Waypoint> _data;
@ -57,7 +55,6 @@ private:
QList<FileIndex> _indexes;
unsigned _radius;
bool _useDEM;
QString _errorString;
int _errorLine;

View File

@ -1,5 +1,8 @@
#include "dem.h"
#include "route.h"
bool Route::_useDEM = false;
bool Route::_show2ndElevation = false;
Route::Route(const RouteData &data) : _data(data)
{
@ -25,7 +28,7 @@ Path Route::path() const
return ret;
}
Graph Route::elevation() const
Graph Route::gpsElevation() const
{
Graph graph;
graph.append(GraphSegment());
@ -38,6 +41,38 @@ Graph Route::elevation() const
return graph;
}
Graph Route::demElevation() const
{
Graph graph;
graph.append(GraphSegment());
GraphSegment &gs = graph.last();
for (int i = 0; i < _data.size(); i++) {
qreal dem = DEM::elevation(_data.at(i).coordinates());
if (!std::isnan(dem))
gs.append(GraphPoint(_distance.at(i), NAN, dem));
}
return graph;
}
GraphPair Route::elevation() const
{
if (_useDEM) {
Graph dem(demElevation());
if (dem.isValid())
return GraphPair(dem, _show2ndElevation ? gpsElevation() : Graph());
else
return GraphPair(gpsElevation(), Graph());
} else {
Graph gps(gpsElevation());
if (gps.isValid())
return GraphPair(gps, _show2ndElevation ? demElevation() : Graph());
else
return GraphPair(demElevation(), Graph());
}
}
qreal Route::distance() const
{
return (_distance.isEmpty()) ? 0 : _distance.last();

View File

@ -11,12 +11,9 @@ class Route
public:
Route(const RouteData &data);
Path path() const;
const RouteData &data() const {return _data;}
Graph elevation() const;
Path path() const;
GraphPair elevation() const;
qreal distance() const;
const QString &name() const {return _data.name();}
@ -26,9 +23,19 @@ public:
bool isValid() const {return _data.size() >= 2;}
static void useDEM(bool use) {_useDEM = use;}
static void showSecondaryElevation(bool show)
{_show2ndElevation = show;}
private:
Graph gpsElevation() const;
Graph demElevation() const;
RouteData _data;
QVector<qreal> _distance;
static bool _useDEM;
static bool _show2ndElevation;
};
#endif // ROUTE_H

View File

@ -1,3 +1,4 @@
#include "dem.h"
#include "track.h"
@ -13,6 +14,9 @@ int Track::_pauseInterval = 10;
bool Track::_outlierEliminate = true;
bool Track::_useReportedSpeed = false;
bool Track::_useDEM = false;
bool Track::_show2ndElevation = false;
bool Track::_show2ndSpeed = false;
static qreal avg(const QVector<qreal> &v)
@ -213,7 +217,7 @@ Track::Track(const TrackData &data) : _data(data), _pause(0)
}
}
Graph Track::elevation() const
Graph Track::gpsElevation() const
{
Graph ret;
@ -237,7 +241,48 @@ Graph Track::elevation() const
return ret;
}
Graph Track::speed() const
Graph Track::demElevation() const
{
Graph ret;
for (int i = 0; i < _data.size(); i++) {
const SegmentData &sd = _data.at(i);
if (sd.size() < 2)
continue;
const Segment &seg = _segments.at(i);
GraphSegment gs;
for (int j = 0; j < sd.size(); j++) {
qreal dem = DEM::elevation(sd.at(j).coordinates());
if (std::isnan(dem) || seg.outliers.contains(j))
continue;
gs.append(GraphPoint(seg.distance.at(j), seg.time.at(j), dem));
}
ret.append(filter(gs, _elevationWindow));
}
return ret;
}
GraphPair Track::elevation() const
{
if (_useDEM) {
Graph dem(demElevation());
if (dem.isValid())
return GraphPair(dem, _show2ndElevation ? gpsElevation() : Graph());
else
return GraphPair(gpsElevation(), Graph());
} else {
Graph gps(gpsElevation());
if (gps.isValid())
return GraphPair(gps, _show2ndElevation ? demElevation() : Graph());
else
return GraphPair(demElevation(), Graph());
}
}
Graph Track::computedSpeed() const
{
Graph ret;
@ -251,14 +296,10 @@ Graph Track::speed() const
qreal v;
for (int j = 0; j < sd.size(); j++) {
if (seg.stop.contains(j) && (!std::isnan(seg.speed.at(j))
|| sd.at(j).hasSpeed())) {
if (seg.stop.contains(j) && !std::isnan(seg.speed.at(j))) {
v = 0;
stop.append(gs.size());
} else if (_useReportedSpeed && sd.at(j).hasSpeed()
&& !seg.outliers.contains(j))
v = sd.at(j).speed();
else if (!std::isnan(seg.speed.at(j)) && !seg.outliers.contains(j))
} else if (!std::isnan(seg.speed.at(j)) && !seg.outliers.contains(j))
v = seg.speed.at(j);
else
continue;
@ -276,6 +317,60 @@ Graph Track::speed() const
return ret;
}
Graph Track::reportedSpeed() const
{
Graph ret;
for (int i = 0; i < _data.size(); i++) {
const SegmentData &sd = _data.at(i);
if (sd.size() < 2)
continue;
const Segment &seg = _segments.at(i);
GraphSegment gs;
QList<int> stop;
qreal v;
for (int j = 0; j < sd.size(); j++) {
if (seg.stop.contains(j) && sd.at(j).hasSpeed()) {
v = 0;
stop.append(gs.size());
} else if (sd.at(j).hasSpeed() && !seg.outliers.contains(j))
v = sd.at(j).speed();
else
continue;
gs.append(GraphPoint(seg.distance.at(j), seg.time.at(j), v));
}
ret.append(filter(gs, _speedWindow));
GraphSegment &filtered = ret.last();
for (int j = 0; j < stop.size(); j++)
filtered[stop.at(j)].setY(0);
}
return ret;
}
GraphPair Track::speed() const
{
if (_useReportedSpeed) {
Graph reported(reportedSpeed());
if (reported.isValid())
return GraphPair(reported, _show2ndSpeed ? computedSpeed()
: Graph());
else
return GraphPair(computedSpeed(), Graph());
} else {
Graph computed(computedSpeed());
if (computed.isValid())
return GraphPair(computed, _show2ndSpeed ? reportedSpeed()
: Graph());
else
return GraphPair(reportedSpeed(), Graph());
}
}
Graph Track::heartRate() const
{
Graph ret;

View File

@ -17,8 +17,8 @@ public:
Path path() const;
Graph elevation() const;
Graph speed() const;
GraphPair elevation() const;
GraphPair speed() const;
Graph heartRate() const;
Graph temperature() const;
Graph cadence() const;
@ -48,6 +48,11 @@ public:
static void setOutlierElimination(bool eliminate)
{_outlierEliminate = eliminate;}
static void useReportedSpeed(bool use) {_useReportedSpeed = use;}
static void useDEM(bool use) {_useDEM = use;}
static void showSecondaryElevation(bool show)
{_show2ndElevation = show;}
static void showSecondarySpeed(bool show)
{_show2ndSpeed = show;}
private:
struct Segment {
@ -60,6 +65,11 @@ private:
bool discardStopPoint(const Segment &seg, int i) const;
Graph demElevation() const;
Graph gpsElevation() const;
Graph reportedSpeed() const;
Graph computedSpeed() const;
TrackData _data;
QList<Segment> _segments;
qreal _pause;
@ -74,6 +84,9 @@ private:
static qreal _pauseSpeed;
static int _pauseInterval;
static bool _useReportedSpeed;
static bool _useDEM;
static bool _show2ndElevation;
static bool _show2ndSpeed;
};
#endif // TRACK_H

23
src/data/waypoint.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "dem.h"
#include "waypoint.h"
bool Waypoint::_useDEM = false;
bool Waypoint::_show2ndElevation = false;
QPair<qreal, qreal> Waypoint::elevations() const
{
if (_useDEM) {
qreal dem = DEM::elevation(coordinates());
if (!std::isnan(dem))
return QPair<qreal, qreal>(dem, _show2ndElevation ? elevation()
: NAN);
else
return QPair<qreal, qreal>(elevation(), NAN);
} else {
if (hasElevation())
return QPair<qreal, qreal>(elevation(), _show2ndElevation
? DEM::elevation(coordinates()) : NAN);
else
return QPair<qreal, qreal>(DEM::elevation(coordinates()), NAN);
}
}

View File

@ -14,9 +14,9 @@
class Waypoint
{
public:
Waypoint() {_elevation = NAN;}
Waypoint(const Coordinates &coordinates) : _coordinates(coordinates)
{_elevation = NAN;}
Waypoint() : _elevation(NAN) {}
Waypoint(const Coordinates &coordinates)
: _coordinates(coordinates), _elevation(NAN) {}
const Coordinates &coordinates() const {return _coordinates;}
const QString &name() const {return _name;}
@ -28,6 +28,8 @@ public:
const QDateTime &timestamp() const {return _timestamp;}
qreal elevation() const {return _elevation;}
QPair<qreal, qreal> elevations() const;
void setCoordinates(const Coordinates &coordinates)
{_coordinates = coordinates;}
void setName(const QString &name) {_name = name;}
@ -46,6 +48,10 @@ public:
{return this->_name == other._name
&& this->_coordinates == other._coordinates;}
static void useDEM(bool use) {_useDEM = use;}
static void showSecondaryElevation(bool show)
{_show2ndElevation = show;}
private:
Coordinates _coordinates;
QString _name;
@ -56,6 +62,9 @@ private:
QVector<Link> _links;
QDateTime _timestamp;
qreal _elevation;
static bool _useDEM;
static bool _show2ndElevation;
};
inline uint qHash(const Waypoint &key)
@ -67,11 +76,9 @@ inline uint qHash(const Waypoint &key)
inline QDebug operator<<(QDebug dbg, const Waypoint &waypoint)
{
dbg.nospace() << "Waypoint(" << waypoint.coordinates() << ", "
<< waypoint.name() << ", " << waypoint.description() << ")";
<< waypoint.name() << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG
Q_DECLARE_TYPEINFO(Waypoint, Q_MOVABLE_TYPE);
#endif // WAYPOINT_H