mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-06-27 11:39:16 +02:00
Added moving time info.
Added special track data processing for "pause states".
This commit is contained in:
38
src/gui.cpp
38
src/gui.cpp
@ -78,6 +78,7 @@ GUI::GUI(QWidget *parent) : QMainWindow(parent)
|
||||
_trackDistance = 0;
|
||||
_routeDistance = 0;
|
||||
_time = 0;
|
||||
_movingTime = 0;
|
||||
|
||||
_sliderPos = 0;
|
||||
|
||||
@ -661,6 +662,7 @@ bool GUI::loadFile(const QString &fileName)
|
||||
for (int i = 0; i < data.tracks().count(); i++) {
|
||||
_trackDistance += data.tracks().at(i)->distance();
|
||||
_time += data.tracks().at(i)->time();
|
||||
_movingTime += data.tracks().at(i)->movingTime();
|
||||
const QDate &date = data.tracks().at(i)->date().date();
|
||||
if (_dateRange.first.isNull() || _dateRange.first > date)
|
||||
_dateRange.first = date;
|
||||
@ -822,9 +824,9 @@ void GUI::plot(QPrinter *printer)
|
||||
QPainter p(printer);
|
||||
TrackInfo info;
|
||||
qreal ih, gh, mh, ratio;
|
||||
Units units = _imperialUnitsAction->isChecked() ? Imperial : Metric;
|
||||
qreal d = distance();
|
||||
qreal t = time();
|
||||
qreal tm = movingTime();
|
||||
|
||||
if (!_pathName.isNull() && _options.printName)
|
||||
info.insert(tr("Name"), _pathName);
|
||||
@ -851,9 +853,11 @@ void GUI::plot(QPrinter *printer)
|
||||
}
|
||||
|
||||
if (d > 0 && _options.printDistance)
|
||||
info.insert(tr("Distance"), Format::distance(d, units));
|
||||
info.insert(tr("Distance"), Format::distance(d, units()));
|
||||
if (t > 0 && _options.printTime)
|
||||
info.insert(tr("Time"), Format::timeSpan(t));
|
||||
if (tm > 0 && _options.printMovingTime)
|
||||
info.insert(tr("Moving Time"), Format::timeSpan(tm));
|
||||
|
||||
|
||||
ratio = p.paintEngine()->paintDevice()->logicalDpiX() / SCREEN_DPI;
|
||||
@ -908,6 +912,7 @@ void GUI::reloadFile()
|
||||
_trackDistance = 0;
|
||||
_routeDistance = 0;
|
||||
_time = 0;
|
||||
_movingTime = 0;
|
||||
_dateRange = DateRange(QDate(), QDate());
|
||||
_pathName = QString();
|
||||
|
||||
@ -942,6 +947,7 @@ void GUI::closeFiles()
|
||||
_trackDistance = 0;
|
||||
_routeDistance = 0;
|
||||
_time = 0;
|
||||
_movingTime = 0;
|
||||
_dateRange = DateRange(QDate(), QDate());
|
||||
_pathName = QString();
|
||||
|
||||
@ -1063,18 +1069,20 @@ void GUI::updateStatusBarInfo()
|
||||
else
|
||||
_fileNameLabel->setText(tr("%n files", "", _files.count()));
|
||||
|
||||
qreal d = distance();
|
||||
Units units = _imperialUnitsAction->isChecked() ? Imperial : Metric;
|
||||
if (d > 0)
|
||||
_distanceLabel->setText(Format::distance(distance(), units));
|
||||
if (distance() > 0)
|
||||
_distanceLabel->setText(Format::distance(distance(), units()));
|
||||
else
|
||||
_distanceLabel->clear();
|
||||
|
||||
qreal t = time();
|
||||
if (t > 0)
|
||||
if (time() > 0)
|
||||
_timeLabel->setText(Format::timeSpan(time()));
|
||||
else
|
||||
_timeLabel->clear();
|
||||
|
||||
if (movingTime() > 0)
|
||||
_timeLabel->setToolTip(Format::timeSpan(movingTime()));
|
||||
else
|
||||
_timeLabel->setToolTip(QString());
|
||||
}
|
||||
|
||||
void GUI::updateWindowTitle()
|
||||
@ -1429,6 +1437,8 @@ void GUI::writeSettings()
|
||||
settings.setValue(PRINT_DISTANCE_SETTING, _options.printDistance);
|
||||
if (_options.printTime != PRINT_TIME_DEFAULT)
|
||||
settings.setValue(PRINT_TIME_SETTING, _options.printTime);
|
||||
if (_options.printMovingTime != PRINT_MOVING_TIME_DEFAULT)
|
||||
settings.setValue(PRINT_MOVING_TIME_SETTING, _options.printMovingTime);
|
||||
if (_options.printItemCount != PRINT_ITEM_COUNT_DEFAULT)
|
||||
settings.setValue(PRINT_ITEM_COUNT_SETTING, _options.printItemCount);
|
||||
if (_options.separateGraphPage != SEPARATE_GRAPH_PAGE_DEFAULT)
|
||||
@ -1598,6 +1608,8 @@ void GUI::readSettings()
|
||||
PRINT_DISTANCE_DEFAULT).toBool();
|
||||
_options.printTime = settings.value(PRINT_TIME_SETTING, PRINT_TIME_DEFAULT)
|
||||
.toBool();
|
||||
_options.printMovingTime = settings.value(PRINT_MOVING_TIME_SETTING,
|
||||
PRINT_MOVING_TIME_DEFAULT).toBool();
|
||||
_options.printItemCount = settings.value(PRINT_ITEM_COUNT_SETTING,
|
||||
PRINT_ITEM_COUNT_DEFAULT).toBool();
|
||||
_options.separateGraphPage = settings.value(SEPARATE_GRAPH_PAGE_SETTING,
|
||||
@ -1635,6 +1647,11 @@ int GUI::mapIndex(const QString &name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Units GUI::units() const
|
||||
{
|
||||
return _imperialUnitsAction->isChecked() ? Imperial : Metric;
|
||||
}
|
||||
|
||||
qreal GUI::distance() const
|
||||
{
|
||||
qreal dist = 0;
|
||||
@ -1651,3 +1668,8 @@ qreal GUI::time() const
|
||||
{
|
||||
return (_showTracksAction->isChecked()) ? _time : 0;
|
||||
}
|
||||
|
||||
qreal GUI::movingTime() const
|
||||
{
|
||||
return (_showTracksAction->isChecked()) ? _movingTime : 0;
|
||||
}
|
||||
|
@ -102,11 +102,13 @@ private:
|
||||
void updateGraphTabs();
|
||||
void updatePathView();
|
||||
|
||||
Units units() const;
|
||||
void setUnits(Units units);
|
||||
void setGraphType(GraphType type);
|
||||
|
||||
qreal distance() const;
|
||||
qreal time() const;
|
||||
qreal movingTime() const;
|
||||
int mapIndex(const QString &name);
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
@ -188,6 +190,7 @@ private:
|
||||
qreal _trackDistance;
|
||||
qreal _routeDistance;
|
||||
qreal _time;
|
||||
qreal _movingTime;
|
||||
DateRange _dateRange;
|
||||
QString _pathName;
|
||||
|
||||
|
@ -152,6 +152,8 @@ QWidget *OptionsDialog::createExportPage()
|
||||
_distance->setChecked(_options->printDistance);
|
||||
_time = new QCheckBox(tr("Time"));
|
||||
_time->setChecked(_options->printTime);
|
||||
_movingTime = new QCheckBox(tr("Moving Time"));
|
||||
_movingTime->setChecked(_options->printMovingTime);
|
||||
_itemCount = new QCheckBox(tr("Item count (>1)"));
|
||||
_itemCount->setChecked(_options->printItemCount);
|
||||
|
||||
@ -160,6 +162,7 @@ QWidget *OptionsDialog::createExportPage()
|
||||
headerTabLayout->addWidget(_date);
|
||||
headerTabLayout->addWidget(_distance);
|
||||
headerTabLayout->addWidget(_time);
|
||||
headerTabLayout->addWidget(_movingTime);
|
||||
headerTabLayout->addItem(new QSpacerItem(10, 10));
|
||||
headerTabLayout->addWidget(_itemCount);
|
||||
QWidget *headerTab = new QWidget();
|
||||
@ -277,6 +280,7 @@ void OptionsDialog::accept()
|
||||
_options->printDate = _date->isChecked();
|
||||
_options->printDistance = _distance->isChecked();
|
||||
_options->printTime = _time->isChecked();
|
||||
_options->printMovingTime = _movingTime->isChecked();
|
||||
_options->printItemCount = _itemCount->isChecked();
|
||||
_options->separateGraphPage = _separateGraphPage->isChecked();
|
||||
|
||||
|
@ -31,6 +31,7 @@ struct Options {
|
||||
bool printDate;
|
||||
bool printDistance;
|
||||
bool printTime;
|
||||
bool printMovingTime;
|
||||
bool printItemCount;
|
||||
bool separateGraphPage;
|
||||
|
||||
@ -70,6 +71,7 @@ private:
|
||||
QCheckBox *_date;
|
||||
QCheckBox *_distance;
|
||||
QCheckBox *_time;
|
||||
QCheckBox *_movingTime;
|
||||
QCheckBox *_itemCount;
|
||||
QCheckBox *_separateGraphPage;
|
||||
};
|
||||
|
@ -100,6 +100,8 @@
|
||||
#define PRINT_DISTANCE_DEFAULT true
|
||||
#define PRINT_TIME_SETTING "printTime"
|
||||
#define PRINT_TIME_DEFAULT true
|
||||
#define PRINT_MOVING_TIME_SETTING "printMovingTime"
|
||||
#define PRINT_MOVING_TIME_DEFAULT false
|
||||
#define PRINT_ITEM_COUNT_SETTING "printItemCount"
|
||||
#define PRINT_ITEM_COUNT_DEFAULT true
|
||||
#define SEPARATE_GRAPH_PAGE_SETTING "separateGraphPage"
|
||||
|
132
src/track.cpp
132
src/track.cpp
@ -9,6 +9,9 @@
|
||||
#define WINDOW_CF 3
|
||||
#define WINDOW_PF 3
|
||||
|
||||
#define PAUSE_SPEED 0.5
|
||||
#define PAUSE_TIME_DIFF 10
|
||||
|
||||
|
||||
static qreal median(QVector<qreal> v)
|
||||
{
|
||||
@ -43,30 +46,31 @@ static QSet<int> eliminate(const QVector<qreal> &v, int window)
|
||||
return rm;
|
||||
}
|
||||
|
||||
static Graph filter(const Graph &v, int window)
|
||||
static Graph filter(const Graph &g, int window)
|
||||
{
|
||||
qreal acc = 0;
|
||||
Graph ret;
|
||||
|
||||
if (v.size() < window)
|
||||
if (g.size() < window)
|
||||
return ret;
|
||||
|
||||
for (int i = 0; i < window; i++)
|
||||
acc += v.at(i).y();
|
||||
acc += g.at(i).y();
|
||||
for (int i = 0; i <= window/2; i++)
|
||||
ret.append(GraphPoint(v.at(i).s(), v.at(i).t(), acc/window));
|
||||
ret.append(GraphPoint(g.at(i).s(), g.at(i).t(), acc/window));
|
||||
|
||||
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(GraphPoint(v.at(i).s(), v.at(i).t(), acc/window));
|
||||
for (int i = window/2 + 1; i < g.size() - window/2; i++) {
|
||||
acc += g.at(i + window/2).y() - g.at(i - (window/2 + 1)).y();
|
||||
ret.append(GraphPoint(g.at(i).s(), g.at(i).t(), acc/window));
|
||||
}
|
||||
|
||||
for (int i = v.size() - window/2; i < v.size(); i++)
|
||||
ret.append(GraphPoint(v.at(i).s(), v.at(i).t(), acc/window));
|
||||
for (int i = g.size() - window/2; i < g.size(); i++)
|
||||
ret.append(GraphPoint(g.at(i).s(), g.at(i).t(), acc/window));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Track::Track(const TrackData &data) : _data(data)
|
||||
{
|
||||
qreal dt, ds, total;
|
||||
@ -98,13 +102,28 @@ Track::Track(const TrackData &data) : _data(data)
|
||||
}
|
||||
}
|
||||
|
||||
_pause = 0;
|
||||
for (int i = 1; i < data.count(); i++) {
|
||||
if (_time.at(i) > _time.at(i-1) + PAUSE_TIME_DIFF
|
||||
&& _speed.at(i) < PAUSE_SPEED) {
|
||||
_pause += _time.at(i) - _time.at(i-1);
|
||||
_stop.insert(i-1);
|
||||
_stop.insert(i);
|
||||
}
|
||||
}
|
||||
|
||||
_outliers = eliminate(_speed, WINDOW_OE);
|
||||
|
||||
QSet<int>::const_iterator it;
|
||||
for (it = _stop.constBegin(); it != _stop.constEnd(); ++it)
|
||||
_outliers.remove(*it);
|
||||
|
||||
total = 0;
|
||||
for (int i = 0; i < _data.size(); i++) {
|
||||
if (_outliers.contains(i))
|
||||
continue;
|
||||
total += _distance.at(i);
|
||||
if (!discardStopPoint(i))
|
||||
total += _distance.at(i);
|
||||
_distance[i] = total;
|
||||
}
|
||||
}
|
||||
@ -113,9 +132,6 @@ Graph Track::elevation() const
|
||||
{
|
||||
Graph raw;
|
||||
|
||||
if (!_data.size())
|
||||
return raw;
|
||||
|
||||
for (int i = 0; i < _data.size(); i++)
|
||||
if (_data.at(i).hasElevation() && !_outliers.contains(i))
|
||||
raw.append(GraphPoint(_distance.at(i), _time.at(i),
|
||||
@ -126,14 +142,16 @@ Graph Track::elevation() const
|
||||
|
||||
Graph Track::speed() const
|
||||
{
|
||||
Graph raw;
|
||||
Graph raw, filtered;
|
||||
qreal v;
|
||||
|
||||
if (!_data.size())
|
||||
return raw;
|
||||
QSet<int> stop;
|
||||
|
||||
for (int i = 0; i < _data.size(); i++) {
|
||||
if (_data.at(i).hasSpeed() && !_outliers.contains(i))
|
||||
if (_stop.contains(i) && (!std::isnan(_speed.at(i))
|
||||
|| _data.at(i).hasSpeed())) {
|
||||
v = 0;
|
||||
stop.insert(raw.size());
|
||||
} else if (_data.at(i).hasSpeed() && !_outliers.contains(i))
|
||||
v = _data.at(i).speed();
|
||||
else if (!std::isnan(_speed.at(i)) && !_outliers.contains(i))
|
||||
v = _speed.at(i);
|
||||
@ -143,16 +161,19 @@ Graph Track::speed() const
|
||||
raw.append(GraphPoint(_distance.at(i), _time.at(i), v));
|
||||
}
|
||||
|
||||
return filter(raw, WINDOW_SF);
|
||||
filtered = filter(raw, WINDOW_SF);
|
||||
|
||||
QSet<int>::const_iterator it;
|
||||
for (it = stop.constBegin(); it != stop.constEnd(); ++it)
|
||||
filtered[*it].setY(0);
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
Graph Track::heartRate() const
|
||||
{
|
||||
Graph raw;
|
||||
|
||||
if (!_data.size())
|
||||
return raw;
|
||||
|
||||
for (int i = 0; i < _data.count(); i++)
|
||||
if (_data.at(i).hasHeartRate() && !_outliers.contains(i))
|
||||
raw.append(GraphPoint(_distance.at(i), _time.at(i),
|
||||
@ -175,26 +196,56 @@ Graph Track::temperature() const
|
||||
|
||||
Graph Track::cadence() const
|
||||
{
|
||||
Graph raw;
|
||||
Graph raw, filtered;
|
||||
QSet<int> stop;
|
||||
qreal c;
|
||||
|
||||
for (int i = 0; i < _data.size(); i++)
|
||||
if (_data.at(i).hasCadence() && !_outliers.contains(i))
|
||||
raw.append(GraphPoint(_distance.at(i), _time.at(i),
|
||||
_data.at(i).cadence()));
|
||||
for (int i = 0; i < _data.size(); i++) {
|
||||
if (_data.at(i).hasCadence() && _stop.contains(i)) {
|
||||
c = 0;
|
||||
stop.insert(raw.size());
|
||||
} else if (_data.at(i).hasCadence() && !_outliers.contains(i))
|
||||
c = _data.at(i).cadence();
|
||||
else
|
||||
continue;
|
||||
|
||||
return filter(raw, WINDOW_CF);
|
||||
raw.append(GraphPoint(_distance.at(i), _time.at(i), c));
|
||||
}
|
||||
|
||||
filtered = filter(raw, WINDOW_CF);
|
||||
|
||||
QSet<int>::const_iterator it;
|
||||
for (it = stop.constBegin(); it != stop.constEnd(); ++it)
|
||||
filtered[*it].setY(0);
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
Graph Track::power() const
|
||||
{
|
||||
Graph raw;
|
||||
Graph raw, filtered;
|
||||
QSet<int> stop;
|
||||
qreal p;
|
||||
|
||||
for (int i = 0; i < _data.size(); i++)
|
||||
if (_data.at(i).hasPower() && !_outliers.contains(i))
|
||||
raw.append(GraphPoint(_distance.at(i), _time.at(i),
|
||||
_data.at(i).power()));
|
||||
for (int i = 0; i < _data.size(); i++) {
|
||||
if (_data.at(i).hasPower() && _stop.contains(i)) {
|
||||
p = 0;
|
||||
stop.insert(raw.size());
|
||||
} else if (_data.at(i).hasPower() && !_outliers.contains(i))
|
||||
p = _data.at(i).power();
|
||||
else
|
||||
continue;
|
||||
|
||||
return filter(raw, WINDOW_PF);
|
||||
raw.append(GraphPoint(_distance.at(i), _time.at(i), p));
|
||||
}
|
||||
|
||||
filtered = filter(raw, WINDOW_PF);
|
||||
|
||||
QSet<int>::const_iterator it;
|
||||
for (it = stop.constBegin(); it != stop.constEnd(); ++it)
|
||||
filtered[*it].setY(0);
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
qreal Track::distance() const
|
||||
@ -208,6 +259,11 @@ qreal Track::time() const
|
||||
(_data.first().timestamp().msecsTo(_data.last().timestamp()) / 1000.0);
|
||||
}
|
||||
|
||||
qreal Track::movingTime() const
|
||||
{
|
||||
return (time() - _pause);
|
||||
}
|
||||
|
||||
QDateTime Track::date() const
|
||||
{
|
||||
return (_data.size()) ? _data.first().timestamp() : QDateTime();
|
||||
@ -218,8 +274,14 @@ Path Track::path() const
|
||||
Path ret;
|
||||
|
||||
for (int i = 0; i < _data.size(); i++)
|
||||
if (!_outliers.contains(i))
|
||||
if (!_outliers.contains(i) && !discardStopPoint(i))
|
||||
ret.append(PathPoint(_data.at(i).coordinates(), _distance.at(i)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Track::discardStopPoint(int i) const
|
||||
{
|
||||
return (_stop.contains(i) && i > 0 && _stop.contains(i-1)
|
||||
&& i < _data.size() - 1 && _stop.contains(i+1));
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ public:
|
||||
|
||||
qreal distance() const;
|
||||
qreal time() const;
|
||||
qreal movingTime() const;
|
||||
QDateTime date() const;
|
||||
|
||||
const QString &name() const {return _data.name();}
|
||||
@ -32,6 +33,8 @@ public:
|
||||
bool isNull() const {return (_data.size() < 2);}
|
||||
|
||||
private:
|
||||
bool discardStopPoint(int i) const;
|
||||
|
||||
const TrackData &_data;
|
||||
|
||||
QVector<qreal> _distance;
|
||||
@ -39,6 +42,9 @@ private:
|
||||
QVector<qreal> _speed;
|
||||
|
||||
QSet<int> _outliers;
|
||||
QSet<int> _stop;
|
||||
|
||||
qreal _pause;
|
||||
};
|
||||
|
||||
#endif // TRACK_H
|
||||
|
@ -15,6 +15,8 @@ QString TrackItem::toolTip()
|
||||
tt.insert(tr("Distance"), Format::distance(_distance.last(), _units));
|
||||
if (_time > 0)
|
||||
tt.insert(tr("Time"), Format::timeSpan(_time));
|
||||
if (_movingTime > 0)
|
||||
tt.insert(tr("Moving Time"), Format::timeSpan(_movingTime));
|
||||
if (!_date.isNull())
|
||||
tt.insert(tr("Date"), _date.toString(Qt::SystemLocaleShortDate));
|
||||
|
||||
@ -45,6 +47,7 @@ TrackItem::TrackItem(const Track &track, QGraphicsItem *parent)
|
||||
_desc = track.description();
|
||||
_date = track.date();
|
||||
_time = track.time();
|
||||
_movingTime = track.movingTime();
|
||||
|
||||
_marker->setPos(_path.elementAt(0));
|
||||
|
||||
|
@ -23,6 +23,7 @@ private:
|
||||
QString _desc;
|
||||
QDateTime _date;
|
||||
qreal _time;
|
||||
qreal _movingTime;
|
||||
};
|
||||
|
||||
#endif // TRACKITEM_H
|
||||
|
Reference in New Issue
Block a user