1 #include <cmath>
2 #include <QLocale>
3 #include "data/data.h"
4 #include "tooltip.h"
5 #include "elevationgraphitem.h"
6 #include "elevationgraph.h"
7
8
nMin(qreal a,qreal b)9 static qreal nMin(qreal a, qreal b)
10 {
11 if (std::isnan(a))
12 return std::isnan(b) ? NAN : b;
13 else
14 return std::isnan(b) ? a : qMin(a, b);
15 }
16
nMax(qreal a,qreal b)17 static qreal nMax(qreal a, qreal b)
18 {
19 if (std::isnan(a))
20 return std::isnan(b) ? NAN : b;
21 else
22 return std::isnan(b) ? a : qMax(a, b);
23 }
24
ElevationGraph(QWidget * parent)25 ElevationGraph::ElevationGraph(QWidget *parent) : GraphTab(parent)
26 {
27 _trackAscent = 0;
28 _routeAscent = 0;
29 _trackDescent = 0;
30 _routeDescent = 0;
31 _trackMin = NAN;
32 _trackMax = NAN;
33 _routeMin = NAN;
34 _routeMax = NAN;
35
36 _showRoutes = true;
37 _showTracks = true;
38
39 setYUnits(Metric);
40 setYLabel(tr("Elevation"));
41 setMinYRange(50.0);
42 }
43
~ElevationGraph()44 ElevationGraph::~ElevationGraph()
45 {
46 qDeleteAll(_tracks);
47 qDeleteAll(_routes);
48 }
49
setInfo()50 void ElevationGraph::setInfo()
51 {
52 if (std::isnan(max()) || std::isnan(min()))
53 clearInfo();
54 else {
55 QLocale l(QLocale::system());
56
57 GraphView::addInfo(tr("Ascent"), l.toString(ascent() * yScale(),
58 'f', 0) + UNIT_SPACE + yUnits());
59 GraphView::addInfo(tr("Descent"), l.toString(descent() * yScale(),
60 'f', 0) + UNIT_SPACE + yUnits());
61 GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f',
62 0) + UNIT_SPACE + yUnits());
63 GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale(), 'f',
64 0) + UNIT_SPACE + yUnits());
65 }
66 }
67
loadGraph(const Graph & graph,PathType type,const QColor & color,bool primary)68 GraphItem *ElevationGraph::loadGraph(const Graph &graph, PathType type,
69 const QColor &color, bool primary)
70 {
71 if (!graph.isValid())
72 return 0;
73
74 ElevationGraphItem *gi = new ElevationGraphItem(graph, _graphType, _width,
75 color, primary ? Qt::SolidLine : Qt::DashLine);
76 gi->setUnits(_units);
77
78 if (type == TrackPath) {
79 _tracks.append(gi);
80 if (_showTracks)
81 addGraph(gi);
82
83 if (primary) {
84 _trackAscent += gi->ascent();
85 _trackDescent += gi->descent();
86 _trackMax = nMax(_trackMax, gi->max());
87 _trackMin = nMin(_trackMin, gi->min());
88 }
89 } else {
90 _routes.append(gi);
91 if (_showRoutes)
92 addGraph(gi);
93
94 if (primary) {
95 _routeAscent += gi->ascent();
96 _routeDescent += gi->descent();
97 _routeMax = nMax(_routeMax, gi->max());
98 _routeMin = nMin(_routeMin, gi->min());
99 }
100 }
101
102 return gi;
103 }
104
loadData(const Data & data)105 QList<GraphItem*> ElevationGraph::loadData(const Data &data)
106 {
107 QList<GraphItem*> graphs;
108 GraphItem *primary, *secondary;
109
110 for (int i = 0; i < data.tracks().count(); i++) {
111 QColor color(_palette.nextColor());
112 const GraphPair &gp = data.tracks().at(i).elevation();
113
114 primary = loadGraph(gp.primary(), TrackPath, color, true);
115 secondary = primary
116 ? loadGraph(gp.secondary(), TrackPath, color, false) : 0;
117 if (primary && secondary)
118 primary->setSecondaryGraph(secondary);
119
120 graphs.append(primary);
121 }
122 for (int i = 0; i < data.routes().count(); i++) {
123 QColor color(_palette.nextColor());
124 const GraphPair &gp = data.routes().at(i).elevation();
125
126 primary = loadGraph(gp.primary(), RoutePath, color, true);
127 secondary = primary
128 ? loadGraph(gp.secondary(), RoutePath, color, false) : 0;
129 if (primary && secondary)
130 primary->setSecondaryGraph(secondary);
131
132 graphs.append(primary);
133 }
134 for (int i = 0; i < data.areas().count(); i++)
135 _palette.nextColor();
136
137 setInfo();
138 redraw();
139
140 return graphs;
141 }
142
clear()143 void ElevationGraph::clear()
144 {
145 qDeleteAll(_tracks);
146 _tracks.clear();
147 qDeleteAll(_routes);
148 _routes.clear();
149
150 _trackAscent = 0;
151 _routeAscent = 0;
152 _trackDescent = 0;
153 _routeDescent = 0;
154 _trackMin = NAN;
155 _trackMax = NAN;
156 _routeMin = NAN;
157 _routeMax = NAN;
158
159 GraphTab::clear();
160 }
161
setYUnits(Units units)162 void ElevationGraph::setYUnits(Units units)
163 {
164 if (units == Metric) {
165 GraphView::setYUnits(tr("m"));
166 setYScale(1);
167 } else {
168 GraphView::setYUnits(tr("ft"));
169 setYScale(M2FT);
170 }
171 }
172
setUnits(Units units)173 void ElevationGraph::setUnits(Units units)
174 {
175 setYUnits(units);
176 setInfo();
177
178 GraphView::setUnits(units);
179 }
180
showItems(const QList<ElevationGraphItem * > & list,bool show)181 void ElevationGraph::showItems(const QList<ElevationGraphItem *> &list,
182 bool show)
183 {
184 for (int i = 0; i < list.size(); i++) {
185 if (show)
186 addGraph(list.at(i));
187 else
188 removeGraph(list.at(i));
189 }
190 }
191
showTracks(bool show)192 void ElevationGraph::showTracks(bool show)
193 {
194 _showTracks = show;
195
196 showItems(_tracks, show);
197 setInfo();
198
199 redraw();
200 }
201
showRoutes(bool show)202 void ElevationGraph::showRoutes(bool show)
203 {
204 _showRoutes = show;
205
206 showItems(_routes, show);
207 setInfo();
208
209 redraw();
210 }
211
ascent() const212 qreal ElevationGraph::ascent() const
213 {
214 qreal val = 0;
215
216 if (_showRoutes)
217 val += _routeAscent;
218 if (_showTracks)
219 val += _trackAscent;
220
221 return val;
222 }
223
descent() const224 qreal ElevationGraph::descent() const
225 {
226 qreal val = 0;
227
228 if (_showRoutes)
229 val += _routeDescent;
230 if (_showTracks)
231 val += _trackDescent;
232
233 return val;
234 }
235
max() const236 qreal ElevationGraph::max() const
237 {
238 qreal val;
239
240 if (_showRoutes && _showTracks)
241 val = nMax(_routeMax, _trackMax);
242 else if (_showTracks)
243 val = _trackMax;
244 else if (_showRoutes)
245 val = _routeMax;
246 else
247 val = NAN;
248
249 return val;
250 }
251
min() const252 qreal ElevationGraph::min() const
253 {
254 qreal val;
255
256 if (_showRoutes && _showTracks)
257 val = nMin(_routeMin, _trackMin);
258 else if (_showTracks)
259 val = _trackMin;
260 else if (_showRoutes)
261 val = _routeMin;
262 else
263 val = NAN;
264
265 return val;
266 }
267