mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
Dan Connelly's MEGA patch.
It includes both powerzones and weekly summary plots. Thanks Dan.
This commit is contained in:
@@ -17,18 +17,31 @@
|
||||
*/
|
||||
|
||||
#include "PowerHist.h"
|
||||
#include "RideItem.h"
|
||||
#include "RideFile.h"
|
||||
#include "Settings.h"
|
||||
#include "Zones.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <qpainter.h>
|
||||
#include <qwt_plot_curve.h>
|
||||
#include <qwt_plot_grid.h>
|
||||
#include <qwt_plot_zoomer.h>
|
||||
#include <qwt_scale_engine.h>
|
||||
#include <qwt_text.h>
|
||||
#include <qwt_legend.h>
|
||||
#include <qwt_data.h>
|
||||
|
||||
class penTooltip: public QwtPlotZoomer
|
||||
static inline int
|
||||
max(int a, int b) { if (a > b) return a; else return b; }
|
||||
|
||||
static inline int
|
||||
min(int a, int b) { if (a < b) return a; else return b; }
|
||||
|
||||
// define a background class to handle shading of power zones
|
||||
// draws power zone bands IF zones are defined and the option
|
||||
// to draw bonds has been selected
|
||||
class PowerHistBackground: public QwtPlotItem
|
||||
{
|
||||
public:
|
||||
penTooltip(QwtPlotCanvas *canvas):
|
||||
@@ -53,15 +66,176 @@ public:
|
||||
PowerHist::PowerHist() :
|
||||
array(NULL), binw(20), withz(true), lny(false)
|
||||
{
|
||||
private:
|
||||
PowerHist *parent;
|
||||
|
||||
public:
|
||||
PowerHistBackground(PowerHist *_parent)
|
||||
{
|
||||
setZ(0.0);
|
||||
parent = _parent;
|
||||
}
|
||||
|
||||
virtual int rtti() const
|
||||
{
|
||||
return QwtPlotItem::Rtti_PlotUserItem;
|
||||
}
|
||||
|
||||
virtual void draw(QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &,
|
||||
const QRect &rect) const
|
||||
{
|
||||
RideItem *rideItem = parent->rideItem;
|
||||
|
||||
if (! rideItem)
|
||||
return;
|
||||
|
||||
Zones **zones = rideItem->zones;
|
||||
int zone_range = rideItem->zoneRange();
|
||||
|
||||
if (parent->shadeZones() && zones && *zones && (zone_range >= 0)) {
|
||||
QList <int> zone_lows = (*zones)->getZoneLows(zone_range);
|
||||
int num_zones = zone_lows.size();
|
||||
if (num_zones > 0) {
|
||||
for (int z = 0; z < num_zones; z ++) {
|
||||
QRect r = rect;
|
||||
|
||||
QColor shading_color =
|
||||
zoneColor(z, num_zones);
|
||||
shading_color.setHsv(
|
||||
shading_color.hue(),
|
||||
shading_color.saturation() / 4,
|
||||
shading_color.value()
|
||||
);
|
||||
r.setLeft(xMap.transform(zone_lows[z]));
|
||||
if (z + 1 < num_zones)
|
||||
r.setRight(xMap.transform(zone_lows[z + 1]));
|
||||
if (r.right() >= r.left())
|
||||
painter->fillRect(r, shading_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Zone labels are drawn if power zone bands are enabled, automatically
|
||||
// at the center of the plot
|
||||
class PowerHistZoneLabel: public QwtPlotItem
|
||||
{
|
||||
private:
|
||||
PowerHist *parent;
|
||||
int zone_number;
|
||||
double watts;
|
||||
QwtText text;
|
||||
|
||||
public:
|
||||
PowerHistZoneLabel(PowerHist *_parent, int _zone_number)
|
||||
{
|
||||
parent = _parent;
|
||||
zone_number = _zone_number;
|
||||
|
||||
RideItem *rideItem = parent->rideItem;
|
||||
|
||||
if (! rideItem)
|
||||
return;
|
||||
|
||||
Zones **zones = rideItem->zones;
|
||||
int zone_range = rideItem->zoneRange();
|
||||
|
||||
setZ(1.0 + zone_number / 100.0);
|
||||
|
||||
// create new zone labels if we're shading
|
||||
if (parent->shadeZones() && zones && *zones && (zone_range >= 0)) {
|
||||
QList <int> zone_lows = (*zones)->getZoneLows(zone_range);
|
||||
QList <QString> zone_names = (*zones)->getZoneNames(zone_range);
|
||||
int num_zones = zone_lows.size();
|
||||
assert(zone_names.size() == num_zones);
|
||||
if (zone_number < num_zones) {
|
||||
watts =
|
||||
(
|
||||
(zone_number + 1 < num_zones) ?
|
||||
0.5 * (zone_lows[zone_number] + zone_lows[zone_number + 1]) :
|
||||
(
|
||||
(zone_number > 0) ?
|
||||
(1.5 * zone_lows[zone_number] - 0.5 * zone_lows[zone_number - 1]) :
|
||||
2.0 * zone_lows[zone_number]
|
||||
)
|
||||
);
|
||||
|
||||
text = QwtText(zone_names[zone_number]);
|
||||
text.setFont(QFont("Helvetica",24, QFont::Bold));
|
||||
QColor text_color = zoneColor(zone_number, num_zones);
|
||||
text_color.setAlpha(64);
|
||||
text.setColor(text_color);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual int rtti() const
|
||||
{
|
||||
return QwtPlotItem::Rtti_PlotUserItem;
|
||||
}
|
||||
|
||||
void draw(QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &,
|
||||
const QRect &rect) const
|
||||
{
|
||||
if (parent->shadeZones()) {
|
||||
int x = xMap.transform(watts);
|
||||
int y = (rect.bottom() + rect.top()) / 2;
|
||||
|
||||
// the following code based on source for QwtPlotMarker::draw()
|
||||
QRect tr(QPoint(0, 0), text.textSize(painter->font()));
|
||||
tr.moveCenter(QPoint(y, -x));
|
||||
painter->rotate(90); // rotate text to avoid overlap: this needs to be fixed
|
||||
text.draw(painter, tr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PowerHist::PowerHist():
|
||||
selected(wattsShaded),
|
||||
rideItem(NULL),
|
||||
wattsArrayLength(0),
|
||||
nmArrayLength(0),
|
||||
hrArrayLength(0),
|
||||
kphArrayLength(0),
|
||||
cadArrayLength(0),
|
||||
binw(20),
|
||||
withz(true),
|
||||
settings(GC_SETTINGS_CO, GC_SETTINGS_APP),
|
||||
unit(settings.value(GC_UNIT)),
|
||||
lny(false)
|
||||
{
|
||||
useMetricUnits = (unit.toString() == "Metric");
|
||||
|
||||
wattsArray = new QVector<unsigned int>(1024);
|
||||
nmArray = new QVector<unsigned int>(512);
|
||||
hrArray = new QVector<unsigned int>(256);
|
||||
kphArray = new QVector<unsigned int>(1024);
|
||||
cadArray = new QVector<unsigned int>(256);
|
||||
|
||||
// create a background object for shading
|
||||
bg = new PowerHistBackground(this);
|
||||
bg->attach(this);
|
||||
|
||||
setCanvasBackground(Qt::white);
|
||||
|
||||
setAxisTitle(xBottom, "Power (watts)");
|
||||
setParameterAxisTitle();
|
||||
setAxisTitle(yLeft, "Cumulative Time (minutes)");
|
||||
|
||||
curve = new QwtPlotCurve("Power");
|
||||
curve = new QwtPlotCurve("");
|
||||
curve->setStyle(QwtPlotCurve::Steps);
|
||||
curve->setRenderHint(QwtPlotItem::RenderAntialiased);
|
||||
curve->setPen(QPen(Qt::red));
|
||||
QPen *pen = new QPen(Qt::black);
|
||||
pen->setWidth(2.0);
|
||||
curve->setPen(*pen);
|
||||
QColor brush_color = Qt::black;
|
||||
brush_color.setAlpha(64);
|
||||
curve->setBrush(brush_color); // fill below the line
|
||||
delete pen;
|
||||
curve->attach(this);
|
||||
|
||||
grid = new QwtPlotGrid();
|
||||
@@ -71,37 +245,141 @@ PowerHist::PowerHist() :
|
||||
grid->setPen(gridPen);
|
||||
grid->attach(this);
|
||||
|
||||
zoneLabels = QList <PowerHistZoneLabel *>::QList();
|
||||
QwtPlotZoomer* zoomer = new penTooltip(this->canvas());
|
||||
}
|
||||
|
||||
PowerHist::~PowerHist() {
|
||||
delete bg;
|
||||
delete curve;
|
||||
delete grid;
|
||||
if (wattsArrayLength)
|
||||
delete [] wattsArray;
|
||||
if (nmArrayLength)
|
||||
delete [] nmArray;
|
||||
if (hrArrayLength)
|
||||
delete [] hrArray;
|
||||
if (kphArrayLength)
|
||||
delete [] kphArray;
|
||||
if (cadArrayLength)
|
||||
delete [] cadArray;
|
||||
}
|
||||
|
||||
// static const variables from PoweHist.h:
|
||||
// discritized unit for smoothing
|
||||
const double PowerHist::wattsDelta;
|
||||
const double PowerHist::nmDelta;
|
||||
const double PowerHist::hrDelta;
|
||||
const double PowerHist::kphDelta;
|
||||
const double PowerHist::cadDelta;
|
||||
|
||||
// digits for text entry validator
|
||||
const int PowerHist::wattsDigits;
|
||||
const int PowerHist::nmDigits;
|
||||
const int PowerHist::hrDigits;
|
||||
const int PowerHist::kphDigits;
|
||||
const int PowerHist::cadDigits;
|
||||
|
||||
void
|
||||
PowerHist::refreshZoneLabels()
|
||||
{
|
||||
// delete any existing power zone labels
|
||||
if (zoneLabels.size()) {
|
||||
QListIterator<PowerHistZoneLabel *> i(zoneLabels);
|
||||
while (i.hasNext()) {
|
||||
PowerHistZoneLabel *label = i.next();
|
||||
label->detach();
|
||||
delete label;
|
||||
}
|
||||
}
|
||||
zoneLabels.clear();
|
||||
|
||||
if (! rideItem)
|
||||
return;
|
||||
|
||||
if ((selected == wattsShaded) || (selected == wattsUnshaded)) {
|
||||
Zones **zones = rideItem->zones;
|
||||
int zone_range = rideItem->zoneRange();
|
||||
|
||||
// generate labels for existing zones
|
||||
if (zones && *zones && (zone_range >= 0)) {
|
||||
int num_zones = (*zones)->numZones(zone_range);
|
||||
for (int z = 0; z < num_zones; z ++) {
|
||||
PowerHistZoneLabel *label = new PowerHistZoneLabel(this, z);
|
||||
label->attach(this);
|
||||
zoneLabels.append(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PowerHist::recalc()
|
||||
{
|
||||
QVector<unsigned int> *array;
|
||||
int arrayLength = 0;
|
||||
double delta;
|
||||
|
||||
// make sure the interval length is set
|
||||
if (dt <= 0)
|
||||
return;
|
||||
|
||||
if ((selected == wattsShaded) ||
|
||||
(selected == wattsUnshaded)
|
||||
) {
|
||||
array = wattsArray;
|
||||
delta = wattsDelta;
|
||||
arrayLength = wattsArrayLength;
|
||||
}
|
||||
else if (selected == nm) {
|
||||
array = nmArray;
|
||||
delta = nmDelta;
|
||||
arrayLength = nmArrayLength;
|
||||
}
|
||||
else if (selected == hr) {
|
||||
array = hrArray;
|
||||
delta = hrDelta;
|
||||
arrayLength = hrArrayLength;
|
||||
}
|
||||
else if (selected == kph) {
|
||||
array = kphArray;
|
||||
delta = kphDelta;
|
||||
arrayLength = kphArrayLength;
|
||||
}
|
||||
else if (selected == cad) {
|
||||
array = cadArray;
|
||||
delta = cadDelta;
|
||||
arrayLength = cadArrayLength;
|
||||
}
|
||||
|
||||
if (!array)
|
||||
return;
|
||||
int count = (int) ceil((arrayLength - 1) / binw);
|
||||
QVector<double> smoothWatts(count+1);
|
||||
QVector<double> smoothTime(count+1);
|
||||
|
||||
int count = int(ceil((arrayLength - 1) / binw));
|
||||
|
||||
// allocate space for data, plus beginning and ending point
|
||||
QVector<double> parameterValue(count+2);
|
||||
QVector<double> totalTime(count+2);
|
||||
int i;
|
||||
for (i = 0; i < count; ++i) {
|
||||
int low = i * binw;
|
||||
int high = low + binw;
|
||||
for (i = 1; i <= count; ++i) {
|
||||
int high = i * binw;
|
||||
int low = high - binw;
|
||||
if (low==0 && !withz)
|
||||
low++;
|
||||
smoothWatts[i] = low;
|
||||
smoothTime[i] = 1e-9; // non-zero for log axis
|
||||
parameterValue[i] = high * delta;
|
||||
totalTime[i] = 1e-9; // nonzero to accomodate log plot
|
||||
while (low < high)
|
||||
smoothTime[i] += array[low++] / 60.0;
|
||||
totalTime[i] += dt * (*array)[low++];
|
||||
}
|
||||
smoothTime[i] = 1e-9;
|
||||
smoothWatts[i] = i * binw;
|
||||
curve->setData(smoothWatts.data(), smoothTime.data(), count+1);
|
||||
setAxisScale(xBottom, 0.0, smoothWatts[count]);
|
||||
totalTime[i] = 1e-9; // nonzero to accomodate log plot
|
||||
parameterValue[i] = i * delta * binw;
|
||||
totalTime[0] = 1e-9;
|
||||
parameterValue[0] = 0;
|
||||
curve->setData(parameterValue.data(), totalTime.data(), count + 2);
|
||||
setAxisScale(xBottom, 0.0, parameterValue[count + 1]);
|
||||
|
||||
refreshZoneLabels();
|
||||
|
||||
setYMax();
|
||||
replot();
|
||||
}
|
||||
@@ -109,35 +387,136 @@ PowerHist::recalc()
|
||||
void
|
||||
PowerHist::setYMax()
|
||||
{
|
||||
setAxisScale(yLeft, (lny ? 0.1 : 0.0), curve->maxYValue() * 1.1);
|
||||
static const double tmin = 1.0/60;
|
||||
setAxisScale(yLeft, (lny ? tmin : 0.0), curve->maxYValue() * 1.1);
|
||||
}
|
||||
|
||||
void
|
||||
PowerHist::setData(RideFile *ride)
|
||||
PowerHist::setData(RideItem *_rideItem)
|
||||
{
|
||||
setTitle(ride->startTime().toString(GC_DATETIME_FORMAT));
|
||||
QMap<double,double> powerHist;
|
||||
QListIterator<RideFilePoint*> j(ride->dataPoints());
|
||||
while (j.hasNext()) {
|
||||
const RideFilePoint *p1 = j.next();
|
||||
if (powerHist.contains(p1->watts))
|
||||
powerHist[p1->watts] += ride->recIntSecs();
|
||||
else
|
||||
powerHist[p1->watts] = ride->recIntSecs();
|
||||
rideItem = _rideItem;
|
||||
|
||||
RideFile *ride = rideItem->ride;
|
||||
|
||||
if (ride) {
|
||||
setTitle(ride->startTime().toString(GC_DATETIME_FORMAT));
|
||||
|
||||
static const int maxSize = 4096;
|
||||
|
||||
// recording interval in minutes
|
||||
dt = ride->recIntSecs() / 60.0;
|
||||
|
||||
for (int i = 0; i < wattsArray->size(); i++)
|
||||
(*wattsArray)[i] = 0;
|
||||
for (int i = 0; i < nmArray->size(); i++)
|
||||
(*nmArray)[i] = 0;
|
||||
for (int i = 0; i < hrArray->size(); i++)
|
||||
(*hrArray)[i] = 0;
|
||||
for (int i = 0; i < kphArray->size(); i++)
|
||||
(*kphArray)[i] = 0;
|
||||
for (int i = 0; i < cadArray->size(); i++)
|
||||
(*cadArray)[i] = 0;
|
||||
|
||||
QListIterator<RideFilePoint*> j(ride->dataPoints());
|
||||
|
||||
int maxWattsIndex = 0;
|
||||
int maxNmIndex = 0;
|
||||
int maxHrIndex = 0;
|
||||
int maxKphIndex = 0;
|
||||
int maxCadIndex = 0;
|
||||
|
||||
// unit conversion factor for imperial units for selected parameters
|
||||
double torque_factor = (useMetricUnits ? 1.0 : 0.73756215);
|
||||
double speed_factor = (useMetricUnits ? 1.0 : 0.62137119);
|
||||
|
||||
while (j.hasNext()) {
|
||||
const RideFilePoint *p1 = j.next();
|
||||
|
||||
int wattsIndex = int(floor(p1->watts / wattsDelta));
|
||||
if (wattsIndex < maxSize) {
|
||||
if (wattsIndex >= wattsArray->size()) {
|
||||
int size = wattsArray->size();
|
||||
int newsize = min(1.5 * wattsIndex, maxSize);
|
||||
wattsArray->resize(newsize);
|
||||
for (int i = size + 1; i < newsize; i ++)
|
||||
(*wattsArray)[i] = 0;
|
||||
}
|
||||
(*wattsArray)[wattsIndex] ++;
|
||||
if (wattsIndex >= maxWattsIndex)
|
||||
maxWattsIndex = wattsIndex;
|
||||
}
|
||||
|
||||
int nmIndex = int(floor(p1->nm * torque_factor / nmDelta));
|
||||
if (nmIndex < maxSize) {
|
||||
if (nmIndex >= nmArray->size()) {
|
||||
int size = nmArray->size();
|
||||
int newsize = min(1.5 * nmIndex, maxSize);
|
||||
nmArray->resize(newsize);
|
||||
for (int i = size + 1; i < newsize; i ++)
|
||||
(*nmArray)[i] = 0;
|
||||
}
|
||||
(*nmArray)[nmIndex] ++;
|
||||
if (nmIndex >= maxNmIndex)
|
||||
maxNmIndex = nmIndex;
|
||||
}
|
||||
|
||||
int hrIndex = int(floor(p1->hr / hrDelta));
|
||||
if (hrIndex < maxSize) {
|
||||
if (hrIndex >= hrArray->size()) {
|
||||
int size = hrArray->size();
|
||||
int newsize = min(3 * size / 2, maxSize);
|
||||
hrArray->resize(newsize);
|
||||
for (int i = size + 1; i < newsize; i ++)
|
||||
(*hrArray)[i] = 0;
|
||||
}
|
||||
(*hrArray)[hrIndex] ++;
|
||||
if (hrIndex >= maxHrIndex)
|
||||
maxHrIndex = hrIndex;
|
||||
|
||||
}
|
||||
|
||||
int kphIndex = int(floor(p1->kph * speed_factor / kphDelta));
|
||||
if (kphIndex < maxSize) {
|
||||
if (kphIndex >= kphArray->size()) {
|
||||
int size = kphArray->size();
|
||||
int newsize = min(1.5 * kphIndex, maxSize);
|
||||
kphArray->resize(newsize);
|
||||
for (int i = size + 1; i < newsize; i ++)
|
||||
(*kphArray)[i] = 0;
|
||||
}
|
||||
(*kphArray)[kphIndex] ++;
|
||||
if (kphIndex >= maxKphIndex)
|
||||
maxKphIndex = kphIndex;
|
||||
}
|
||||
|
||||
int cadIndex = int(floor(p1->cad / cadDelta));
|
||||
if (cadIndex < maxSize) {
|
||||
if (cadIndex >= cadArray->size()) {
|
||||
int size = cadArray->size();
|
||||
int newsize = min(1.5 * cadIndex, maxSize);
|
||||
cadArray->resize(newsize);
|
||||
for (int i = size + 1; i < newsize; i ++)
|
||||
(*cadArray)[i] = 0;
|
||||
}
|
||||
(*cadArray)[cadIndex] ++;
|
||||
if (cadIndex >= maxCadIndex)
|
||||
maxCadIndex = cadIndex;
|
||||
}
|
||||
}
|
||||
|
||||
wattsArrayLength = maxWattsIndex + 1;
|
||||
nmArrayLength = maxNmIndex + 1;
|
||||
hrArrayLength = maxHrIndex + 1;
|
||||
kphArrayLength = maxKphIndex + 1;
|
||||
cadArrayLength = maxCadIndex + 1;
|
||||
|
||||
recalc();
|
||||
}
|
||||
assert(powerHist.keys().first() >= 0);
|
||||
int maxPower = (int) round(powerHist.keys().last());
|
||||
delete [] array;
|
||||
arrayLength = maxPower + 1;
|
||||
array = new double[arrayLength];
|
||||
for (int i = 0; i < arrayLength; ++i)
|
||||
array[i] = 0.0;
|
||||
QMapIterator<double,double> i(powerHist);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
array[(int) round(i.key())] += i.value();
|
||||
else {
|
||||
setTitle("no data");
|
||||
replot();
|
||||
}
|
||||
recalc();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -147,6 +526,57 @@ PowerHist::setBinWidth(int value)
|
||||
recalc();
|
||||
}
|
||||
|
||||
double
|
||||
PowerHist::getDelta()
|
||||
{
|
||||
switch (selected) {
|
||||
case wattsShaded:
|
||||
case wattsUnshaded:
|
||||
return wattsDelta;
|
||||
case nm:
|
||||
return nmDelta;
|
||||
case hr:
|
||||
return hrDelta;
|
||||
case kph:
|
||||
return kphDelta;
|
||||
case cad:
|
||||
return cadDelta;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
PowerHist::getDigits()
|
||||
{
|
||||
switch (selected) {
|
||||
case wattsShaded:
|
||||
case wattsUnshaded:
|
||||
return wattsDigits;
|
||||
case nm:
|
||||
return nmDigits;
|
||||
case hr:
|
||||
return hrDigits;
|
||||
case kph:
|
||||
return kphDigits;
|
||||
case cad:
|
||||
return cadDigits;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
PowerHist::setBinWidthRealUnits(double value)
|
||||
{
|
||||
setBinWidth(round(value / getDelta()));
|
||||
return binw;
|
||||
}
|
||||
|
||||
double
|
||||
PowerHist::getBinWidthRealUnits()
|
||||
{
|
||||
return binw * getDelta();
|
||||
}
|
||||
|
||||
void
|
||||
PowerHist::setWithZeros(bool value)
|
||||
{
|
||||
@@ -178,3 +608,96 @@ PowerHist::setlnY(bool value)
|
||||
replot();
|
||||
}
|
||||
|
||||
void
|
||||
PowerHist::setParameterAxisTitle()
|
||||
{
|
||||
setAxisTitle(
|
||||
xBottom,
|
||||
((selected == wattsShaded) ||
|
||||
(selected == wattsUnshaded)
|
||||
) ?
|
||||
"watts" :
|
||||
((selected == hr) ?
|
||||
"beats/minute" :
|
||||
((selected == cad) ?
|
||||
"revolutions/min" :
|
||||
useMetricUnits ?
|
||||
((selected == nm) ?
|
||||
"newton-meters" :
|
||||
((selected == kph) ?
|
||||
"km/hr" :
|
||||
"undefined"
|
||||
)
|
||||
) :
|
||||
((selected == nm) ?
|
||||
"ft-lb" :
|
||||
((selected == kph) ?
|
||||
"miles/hr" :
|
||||
"undefined"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
PowerHist::setSelection(Selection selection) {
|
||||
if (selected == selection)
|
||||
return;
|
||||
|
||||
selected = selection;
|
||||
setParameterAxisTitle();
|
||||
recalc();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PowerHist::fixSelection() {
|
||||
|
||||
Selection s = selected;
|
||||
RideFile *ride = rideItem->ride;
|
||||
|
||||
if (ride)
|
||||
do {
|
||||
if ((s == wattsShaded) || (s == wattsUnshaded))
|
||||
if (ride->areDataPresent()->watts)
|
||||
setSelection(s);
|
||||
else
|
||||
s = nm;
|
||||
|
||||
else if (s == nm)
|
||||
if (ride->areDataPresent()->nm)
|
||||
setSelection(s);
|
||||
else
|
||||
s = hr;
|
||||
|
||||
else if (s == hr)
|
||||
if (ride->areDataPresent()->hr)
|
||||
setSelection(s);
|
||||
else
|
||||
s = kph;
|
||||
|
||||
else if (s == kph)
|
||||
if (ride->areDataPresent()->kph)
|
||||
setSelection(s);
|
||||
else
|
||||
s = cad;
|
||||
|
||||
else if (s == cad)
|
||||
if (ride->areDataPresent()->cad)
|
||||
setSelection(s);
|
||||
else
|
||||
s = wattsShaded;
|
||||
} while (s != selected);
|
||||
}
|
||||
|
||||
|
||||
bool PowerHist::shadeZones() const
|
||||
{
|
||||
return (
|
||||
rideItem &&
|
||||
rideItem->ride &&
|
||||
selected == wattsShaded
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user