From b389555befb021f07d985dab6b56a504568da35f Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Sat, 16 Feb 2013 13:41:55 +0000 Subject: [PATCH] Shade Selector on CP chart - none - no shading on the all curve - derived CP - as before using the CP value derived from all curve data - CP - the value of CP for the time of the ride NOTE: When in rangemode (i.e. on home) the CP is set to the mean CP for the date range selected. --- src/CpintPlot.cpp | 58 +++++++++++++++++++++++++++---------- src/CpintPlot.h | 6 ++++ src/CriticalPowerWindow.cpp | 57 ++++++++++++++++++++++++++++-------- src/CriticalPowerWindow.h | 6 ++++ 4 files changed, 99 insertions(+), 28 deletions(-) diff --git a/src/CpintPlot.cpp b/src/CpintPlot.cpp index ff846599f..6578b6589 100644 --- a/src/CpintPlot.cpp +++ b/src/CpintPlot.cpp @@ -52,7 +52,8 @@ CpintPlot::CpintPlot(MainWindow *main, QString p, const Zones *zones) : mainWindow(main), current(NULL), bests(NULL), - isFiltered(false) + isFiltered(false), + shadeMode(2) { setInstanceName("CP Plot"); assert(!USE_T0_IN_CP_MODEL); // doesn't work with energyMode=true @@ -366,7 +367,7 @@ CpintPlot::plot_CP_curve(CpintPlot *thisPlot, // the plot we're currently di if (appsettings->value(this, GC_ANTIALIAS, false).toBool() == true) CPCurve->setRenderHint(QwtPlotItem::RenderAntialiased); QPen pen(GColor(CCP)); - pen.setWidth(appsettings->value(this, GC_LINEWIDTH, 2.0).toDouble()); + pen.setWidth(2.0); pen.setStyle(Qt::DashLine); CPCurve->setPen(pen); CPCurve->setData(cp_curve_time.data(), cp_curve_power.data(), curve_points); @@ -391,6 +392,7 @@ CpintPlot::clear_CP_Curves() } } +// plot the all curve, with shading according to the shade mode void CpintPlot::plot_allCurve(CpintPlot *thisPlot, int n_values, @@ -406,10 +408,26 @@ CpintPlot::plot_allCurve(CpintPlot *thisPlot, energyBests[t] = power_values[t] * time_values[t] * 60.0 / 1000.0; } - // generate zones from derived CP value - if (cp > 0) { + // lets work out how we are shading it + switch(shadeMode) { + case 0 : // not shading!! + break; + + case 1 : // value for current date + // or average for date range if a range + shadingCP = dateCP; + break; + + default: + case 2 : // derived value + shadingCP = cp; + break; + } + + // generate zones from shading CP value + if (shadingCP > 0) { QList power_zone; - int n_zones = zones->lowsFromCP(&power_zone, (int) int(cp)); + int n_zones = zones->lowsFromCP(&power_zone, (int) int(shadingCP)); int high = n_values - 1; int zone = 0; while (zone < n_zones && high > 0) { @@ -428,19 +446,21 @@ CpintPlot::plot_allCurve(CpintPlot *thisPlot, if (appsettings->value(this, GC_ANTIALIAS, false).toBool() == true) curve->setRenderHint(QwtPlotItem::RenderAntialiased); QPen pen(color.darker(200)); - pen.setWidth(appsettings->value(this, GC_LINEWIDTH, 2.0).toDouble()); + pen.setWidth(2.0); curve->setPen(pen); curve->attach(thisPlot); // use a linear gradient - color.setAlpha(180); - QColor color1 = color; - color1.setAlpha(64); - QLinearGradient linearGradient(0, 0, 0, height()); - linearGradient.setColorAt(0.0, color); - linearGradient.setColorAt(1.0, color1); - linearGradient.setSpread(QGradient::PadSpread); - curve->setBrush(linearGradient); // fill below the line + if (shadeMode && shadingCP) { // 0 value means no shading please - and only if proper value for shadingCP + color.setAlpha(180); + QColor color1 = color; + color1.setAlpha(64); + QLinearGradient linearGradient(0, 0, 0, height()); + linearGradient.setColorAt(0.0, color); + linearGradient.setColorAt(1.0, color1); + linearGradient.setSpread(QGradient::PadSpread); + curve->setBrush(linearGradient); // fill below the line + } if (series == RideFile::none) { // this is Energy mode curve->setData(time_values.data() + low, @@ -451,7 +471,7 @@ CpintPlot::plot_allCurve(CpintPlot *thisPlot, } allCurves.append(curve); - if (series != RideFile::none || energyBests[high] > 100.0) { + if (shadeMode && (series != RideFile::none || energyBests[high] > 100.0)) { QwtText text(name); text.setFont(QFont("Helvetica", 20, QFont::Bold)); color.setAlpha(255); @@ -554,7 +574,7 @@ CpintPlot::calculate(RideItem *rideItem) else { // make sure color reflects latest config QPen pen(GColor(CCP)); - pen.setWidth(2.0); + pen.setWidth(4.0); pen.setStyle(Qt::DashLine); CPCurve->setPen(pen); } @@ -792,3 +812,9 @@ CpintPlot::setFilter(QStringList list) delete bests; bests = NULL; } + +void +CpintPlot::setShadeMode(int x) +{ + shadeMode = x; +} diff --git a/src/CpintPlot.h b/src/CpintPlot.h index cb968f3e9..2ed088f35 100644 --- a/src/CpintPlot.h +++ b/src/CpintPlot.h @@ -87,11 +87,13 @@ class CpintPlot : public QwtPlot const QwtPlotCurve *getCPCurve() const { return CPCurve; } double cp, tau, t0; // CP model parameters + double shadingCP; // the CP value we use to draw the shade void deriveCPParameters(); void changeSeason(const QDate &start, const QDate &end); void setAxisTitle(int axis, QString label); void setSeries(RideFile::SeriesType); + QVector getBests() { return bests->meanMaxArray(series); } QVector getBestDates() { return bests->meanMaxDates(series); } @@ -103,6 +105,8 @@ class CpintPlot : public QwtPlot void plot_allCurve(CpintPlot *plot, int n_values, const double *power_values); void configChanged(); void pointHover(QwtPlotCurve *curve, int index); + void setShadeMode(int x); + void setDateCP(int x) { dateCP = x; } void clearFilter(); void setFilter(QStringList); @@ -121,6 +125,7 @@ class CpintPlot : public QwtPlot QDate startDate; QDate endDate; const Zones *zones; + int dateCP; RideFile::SeriesType series; MainWindow *mainWindow; @@ -130,6 +135,7 @@ class CpintPlot : public QwtPlot QStringList files; bool isFiltered; + int shadeMode; }; #endif // _GC_CpintPlot_h diff --git a/src/CriticalPowerWindow.cpp b/src/CriticalPowerWindow.cpp index 801cbf003..88b0db223 100644 --- a/src/CriticalPowerWindow.cpp +++ b/src/CriticalPowerWindow.cpp @@ -30,6 +30,7 @@ #include "Season.h" #include "SeasonParser.h" #include "Colors.h" +#include "Zones.h" #include #include @@ -147,23 +148,26 @@ CriticalPowerWindow::CriticalPowerWindow(const QDir &home, MainWindow *parent, b label2->hide(); } - cpintSetCPButton = new QPushButton(tr("&Save CP value"), this); - cpintSetCPButton->setEnabled(false); - cpintSetCPButton->hide(); - cl->addRow(label2, cComboSeason); + cl->addWidget(new QLabel("")); //spacing + cl->addRow(new QLabel(tr("Data series")), seriesCombo); + pcl->addRow(new QLabel(""), cpintSetCPButton); + + // shading + shadeCombo = new QComboBox(this); + shadeCombo->addItem(tr("None")); + shadeCombo->addItem(tr("Using CP")); + shadeCombo->addItem(tr("Using derived CP")); + QLabel *shading = new QLabel(tr("Power Shading")); + shadeCombo->setCurrentIndex(2); + cl->addRow(shading, shadeCombo); dateSetting = new DateSettingsEdit(this); cl->addRow(label, dateSetting); - if (rangemode == false) { dateSetting->hide(); label->hide(); } - cl->addWidget(new QLabel("")); //spacing - cl->addRow(new QLabel(tr("Data series")), seriesCombo); - pcl->addRow(new QLabel(""), cpintSetCPButton); - picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::VLineRubberBand, QwtPicker::AlwaysOff, cpintPlot->canvas()); @@ -196,7 +200,7 @@ CriticalPowerWindow::CriticalPowerWindow(const QDir &home, MainWindow *parent, b connect(mainWindow, SIGNAL(rideAdded(RideItem*)), this, SLOT(newRideAdded(RideItem*))); connect(mainWindow, SIGNAL(rideDeleted(RideItem*)), this, SLOT(newRideAdded(RideItem*))); connect(seasons, SIGNAL(seasonsChanged()), this, SLOT(resetSeasons())); - + connect(shadeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(shadingSelected(int))); connect(dateSetting, SIGNAL(useCustomRange(DateRange)), this, SLOT(useCustomRange(DateRange))); connect(dateSetting, SIGNAL(useThruToday()), this, SLOT(useThruToday())); connect(dateSetting, SIGNAL(useStandardRange()), this, SLOT(useStandardRange())); @@ -238,6 +242,13 @@ CriticalPowerWindow::rideSelected() currentRide = myRideItem; if (currentRide) { + if (mainWindow->zones()) { + int zoneRange = mainWindow->zones()->whichRange(currentRide->dateTime.date()); + int CP = zoneRange >= 0 ? mainWindow->zones()->getCP(zoneRange) : 0; + cpintPlot->setDateCP(CP); + } else { + cpintPlot->setDateCP(0); + } cpintPlot->calculate(currentRide); // apply latest colors @@ -501,11 +512,25 @@ CriticalPowerWindow::dateRangeChanged(DateRange dateRange) if (dateRange.from == cfrom && dateRange.to == cto && !stale) return; + cfrom = dateRange.from; + cto = dateRange.to; + + // lets work out the average CP configure value + if (mainWindow->zones()) { + int fromZoneRange = mainWindow->zones()->whichRange(cfrom); + int toZoneRange = mainWindow->zones()->whichRange(cto); + + int CPfrom = fromZoneRange >= 0 ? mainWindow->zones()->getCP(fromZoneRange) : 0; + int CPto = toZoneRange >= 0 ? mainWindow->zones()->getCP(toZoneRange) : CPfrom; + if (CPfrom == 0) CPfrom = CPto; + int dateCP = (CPfrom + CPto) / 2; + + cpintPlot->setDateCP(dateCP); + } + cpintPlot->changeSeason(dateRange.from, dateRange.to); cpintPlot->calculate(currentRide); - cfrom = dateRange.from; - cto = dateRange.to; stale = false; } @@ -522,3 +547,11 @@ void CriticalPowerWindow::filterChanged() { cpintPlot->calculate(currentRide); } + +void +CriticalPowerWindow::shadingSelected(int shading) +{ + cpintPlot->setShadeMode(shading); + if (rangemode) dateRangeChanged(DateRange()); + else cpintPlot->calculate(currentRide); +} diff --git a/src/CriticalPowerWindow.h b/src/CriticalPowerWindow.h index 0db81f669..ad9501eeb 100644 --- a/src/CriticalPowerWindow.h +++ b/src/CriticalPowerWindow.h @@ -52,6 +52,7 @@ class CriticalPowerWindow : public GcChartWindow Q_PROPERTY(int lastN READ lastN WRITE setLastN USER true) Q_PROPERTY(int lastNX READ lastNX WRITE setLastNX USER true) Q_PROPERTY(int prevN READ prevN WRITE setPrevN USER true) + Q_PROPERTY(int shading READ shading WRITE setShading USER true) Q_PROPERTY(int useSelected READ useSelected WRITE setUseSelected USER true) // !! must be last property !! public: @@ -107,6 +108,9 @@ class CriticalPowerWindow : public GcChartWindow int prevN() { return dateSetting->prevN(); } void setPrevN(int x) { dateSetting->setPrevN(x); } + int shading() { return shadeCombo->currentIndex(); } + void setShading(int x) { return shadeCombo->setCurrentIndex(x); } + protected slots: void newRideAdded(RideItem*); void cpintTimeValueEntered(); @@ -114,6 +118,7 @@ class CriticalPowerWindow : public GcChartWindow void pickerMoved(const QPoint &pos); void rideSelected(); void seasonSelected(int season); + void shadingSelected(int shading); void setSeries(int index); void resetSeasons(); void filterChanged(); @@ -142,6 +147,7 @@ class CriticalPowerWindow : public GcChartWindow QLabel *cpintCPValue; QComboBox *seriesCombo; QComboBox *cComboSeason; + QComboBox *shadeCombo; QPushButton *cpintSetCPButton; QwtPlotPicker *picker; void addSeries();