mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Add Polar SpinScan Plot
The Power Stroke chart will now show a bar or polar chart.
This commit is contained in:
@@ -373,7 +373,8 @@ void Computrainer::unpackTelemetry(int &ss1, int &ss2, int &ss3, int &buttons, i
|
||||
value12 = value8 | (b1&7)<<9 | (b3&2)<<7;
|
||||
|
||||
if (buttons&64) {
|
||||
memcpy((void*)spinScan, (void*)ss, 24);
|
||||
memcpy((void*)spinScan, (void*)ss+3, 21);
|
||||
memcpy((void*)spinScan+21, (void*)ss, 3);
|
||||
//for (pos=0; pos<24; pos++) fprintf(stderr, "%d, ", ss[pos]);
|
||||
//fprintf(stderr, "\n");
|
||||
pos=0;
|
||||
|
||||
@@ -45,7 +45,7 @@ size_t SpinScanData::size() const { return 48; }
|
||||
QwtData *SpinScanData::copy() const { return new SpinScanData(spinData, isleft); }
|
||||
void SpinScanData::init() { }
|
||||
|
||||
SpinScanPlot::SpinScanPlot(uint8_t *spinData) : leftCurve(NULL), rightCurve(NULL), spinData(spinData)
|
||||
SpinScanPlot::SpinScanPlot(QWidget *parent, uint8_t *spinData) : QwtPlot(parent), leftCurve(NULL), rightCurve(NULL), spinData(spinData)
|
||||
{
|
||||
setInstanceName("SpinScan Plot");
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class SpinScanPlot : public QwtPlot
|
||||
SpinScanData *leftSpinScanData;
|
||||
SpinScanData *rightSpinScanData;
|
||||
|
||||
SpinScanPlot(uint8_t *);
|
||||
SpinScanPlot(QWidget *parent, uint8_t *);
|
||||
|
||||
uint8_t *spinData;
|
||||
|
||||
|
||||
@@ -24,9 +24,26 @@ SpinScanPlotWindow::SpinScanPlotWindow(MainWindow *mainWindow) :
|
||||
{
|
||||
setContentsMargins(0,0,0,0);
|
||||
setInstanceName("SpinScan Plot");
|
||||
setControls(NULL);
|
||||
setProperty("color", GColor(CRIDEPLOTBACKGROUND));
|
||||
|
||||
// setup controls
|
||||
QWidget *c = new QWidget;
|
||||
QVBoxLayout *cl = new QVBoxLayout(c);
|
||||
QHBoxLayout *style = new QHBoxLayout();
|
||||
cl->addLayout(style);
|
||||
cl->addStretch();
|
||||
|
||||
QLabel *label = new QLabel("Style", this);
|
||||
mode = new QComboBox(this);
|
||||
mode->addItem("Bar");
|
||||
mode->addItem("Polar");
|
||||
|
||||
style->addWidget(label);
|
||||
style->addWidget(mode);
|
||||
style->addStretch();
|
||||
|
||||
setControls(c);
|
||||
|
||||
// init to zero
|
||||
history[0] = set1;
|
||||
history[1] = set2;
|
||||
@@ -46,8 +63,18 @@ SpinScanPlotWindow::SpinScanPlotWindow(MainWindow *mainWindow) :
|
||||
history[15] = set16;
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
rtPlot = new SpinScanPlot(spinData);
|
||||
layout->addWidget(rtPlot);
|
||||
stack = new QStackedWidget(this);
|
||||
|
||||
rtPlot = new SpinScanPlot(this, spinData);
|
||||
plPlot = new SpinScanPolarPlot(this, spinData);
|
||||
|
||||
stack->addWidget(rtPlot);
|
||||
stack->addWidget(plPlot);
|
||||
|
||||
layout->addWidget(stack);
|
||||
|
||||
// when we change styles..
|
||||
connect(mode, SIGNAL(currentIndexChanged(int)), this, SLOT(styleChanged()));
|
||||
|
||||
// get updates..
|
||||
connect(mainWindow, SIGNAL(telemetryUpdate(RealtimeData)), this, SLOT(telemetryUpdate(RealtimeData)));
|
||||
@@ -58,6 +85,20 @@ SpinScanPlotWindow::SpinScanPlotWindow(MainWindow *mainWindow) :
|
||||
stop(); // resets the array
|
||||
}
|
||||
|
||||
void
|
||||
SpinScanPlotWindow::setStyle(int x)
|
||||
{
|
||||
stack->setCurrentIndex(x);
|
||||
}
|
||||
|
||||
void
|
||||
SpinScanPlotWindow::styleChanged()
|
||||
{
|
||||
int index = mode->currentIndex();
|
||||
if (index < 0 || index > 1) return;
|
||||
stack->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void
|
||||
SpinScanPlotWindow::start()
|
||||
{
|
||||
@@ -96,5 +137,6 @@ SpinScanPlotWindow::telemetryUpdate(RealtimeData rtData)
|
||||
memcpy(history[current++], rtData.spinScan, 24);
|
||||
if (current==16) current=0;
|
||||
|
||||
plPlot->replot(); // redraw
|
||||
rtPlot->replot(); // redraw
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "RideFile.h" // for data series types
|
||||
#include "SpinScanPolarPlot.h"
|
||||
#include "SpinScanPlot.h"
|
||||
#include "RealtimeData.h" // for realtimedata structure
|
||||
|
||||
@@ -37,6 +38,8 @@ class SpinScanPlotWindow : public GcWindow
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
Q_PROPERTY(int style READ getStyle WRITE setStyle USER true)
|
||||
|
||||
public:
|
||||
|
||||
SpinScanPlotWindow(MainWindow *mainWindow);
|
||||
@@ -49,6 +52,10 @@ class SpinScanPlotWindow : public GcWindow
|
||||
void stop();
|
||||
void pause();
|
||||
|
||||
int getStyle() const { return mode->currentIndex(); }
|
||||
void setStyle(int x);
|
||||
void styleChanged();
|
||||
|
||||
private:
|
||||
|
||||
// we keep 8 sets of spinscan data (last 2 seconds)
|
||||
@@ -80,9 +87,14 @@ class SpinScanPlotWindow : public GcWindow
|
||||
int current;
|
||||
|
||||
MainWindow *mainWindow;
|
||||
|
||||
QStackedWidget *stack;
|
||||
SpinScanPlot *rtPlot;
|
||||
SpinScanPolarPlot *plPlot;
|
||||
|
||||
uint8_t spinData[24]; // what we give to the plot
|
||||
|
||||
QComboBox *mode;
|
||||
};
|
||||
|
||||
#endif // _GC_SpinScanPlotWindow_h
|
||||
|
||||
133
src/SpinScanPolarPlot.cpp
Normal file
133
src/SpinScanPolarPlot.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Mark Liversedge (liversedge@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <QDebug>
|
||||
#include <qwt_data.h>
|
||||
#include <qwt_legend.h>
|
||||
#include <qwt_plot_curve.h>
|
||||
#include <qwt_plot_canvas.h>
|
||||
#include <qwt_plot_grid.h>
|
||||
#include "SpinScanPolarPlot.h"
|
||||
#include <stdint.h>
|
||||
#include "Colors.h"
|
||||
|
||||
// to avoid excessive floating point operations when updating the display
|
||||
// this is a precomputed value for cos(i*15) * (PI / 180)
|
||||
static const double cosx[24] = {
|
||||
1.000000, 0.965926, 0.866026, 0.707107, 0.500001, 0.258820,
|
||||
0.000000, -0.258818, -0.499999, -0.707106, -0.866024, -0.965925,
|
||||
-1.000000, -0.965926, -0.866027, -0.707109, -0.500003, -0.258822,
|
||||
-0.000004, 0.258815, 0.499997, 0.707104, 0.866023, 0.965925
|
||||
};
|
||||
|
||||
// this is a precomputed value for sin(i*15) * (PI / 180)
|
||||
static const double siny[24] = {
|
||||
0.000000, 0.258819, 0.500000, 0.707106, 0.866025, 0.965926,
|
||||
1.000000, 0.965926, 0.866026, 0.707108, 0.500002, 0.258821,
|
||||
0.000000, -0.258817, -0.499998, -0.707105, -0.866024, -0.965925,
|
||||
-1.000000, -0.965927, -0.866027, -0.707110, -0.500004, -0.258823
|
||||
};
|
||||
|
||||
// SpinScan force/direction to cartesian for plotting
|
||||
size_t SpinScanPolarData::size() const { return 13; }
|
||||
QwtData *SpinScanPolarData::copy() const { return new SpinScanPolarData(spinData, isleft); }
|
||||
void SpinScanPolarData::init() { }
|
||||
double SpinScanPolarData::x(size_t i) const { i += isleft?0:12; if (i>=24) i=0; return cosx[i] * (double)spinData[i]; }
|
||||
double SpinScanPolarData::y(size_t i) const { i += isleft?0:12; if (i>=24) i=0; return siny[i] * (double)spinData[i]; }
|
||||
|
||||
// Original code before moving to precomputed constants
|
||||
//double SpinScanPolarData::x(size_t i) const { if (i==24) i=0; return cos((i*15)*3.14159f/180.00f) * (double)spinData[i]; }
|
||||
//double SpinScanPolarData::y(size_t i) const { if (i==24) i=0; return sin((i*15)*3.14159f/180.00f) * (double)spinData[i]; }
|
||||
|
||||
SpinScanPolarPlot::SpinScanPolarPlot(QWidget *parent, uint8_t *spinData) : QwtPlot(parent), leftCurve(NULL), rightCurve(NULL), spinData(spinData)
|
||||
{
|
||||
setInstanceName("SpinScan Plot");
|
||||
|
||||
// Setup the axis
|
||||
setAxisTitle(yLeft, "SpinScan");
|
||||
setAxisMaxMinor(xBottom, 0);
|
||||
setAxisMaxMinor(yLeft, 0);
|
||||
|
||||
QPalette pal;
|
||||
setAxisScale(yLeft, -90, 90); // max 8 bit plus a little
|
||||
setAxisScale(xBottom, -90, 90); // max 8 bit plus a little
|
||||
pal.setColor(QPalette::WindowText, GColor(CSPINSCANLEFT));
|
||||
pal.setColor(QPalette::Text, GColor(CSPINSCANLEFT));
|
||||
axisWidget(QwtPlot::yLeft)->setPalette(pal);
|
||||
axisWidget(QwtPlot::yLeft)->scaleDraw()->setTickLength(QwtScaleDiv::MajorTick, 3);
|
||||
|
||||
enableAxis(xBottom, false); // very little value and some cpu overhead
|
||||
enableAxis(yLeft, false);
|
||||
|
||||
rightCurve = new QwtPlotCurve("SpinScan Right");
|
||||
rightCurve->setRenderHint(QwtPlotItem::RenderAntialiased); // too cpu intensive
|
||||
rightCurve->attach(this);
|
||||
rightCurve->setYAxis(QwtPlot::yLeft);
|
||||
rightSpinScanPolarData = new SpinScanPolarData(spinData, false);
|
||||
|
||||
leftCurve = new QwtPlotCurve("SpinScan Left");
|
||||
leftCurve->setRenderHint(QwtPlotItem::RenderAntialiased); // too cpu intensive
|
||||
leftCurve->attach(this);
|
||||
leftCurve->setYAxis(QwtPlot::yLeft);
|
||||
leftSpinScanPolarData = new SpinScanPolarData(spinData, true);
|
||||
|
||||
canvas()->setFrameStyle(QFrame::NoFrame);
|
||||
configChanged(); // set colors
|
||||
}
|
||||
|
||||
void
|
||||
SpinScanPolarPlot::setAxisTitle(int axis, QString label)
|
||||
{
|
||||
// setup the default fonts
|
||||
QFont stGiles; // hoho - Chart Font St. Giles ... ok you have to be British to get this joke
|
||||
stGiles.fromString(appsettings->value(this, GC_FONT_CHARTLABELS, QFont().toString()).toString());
|
||||
stGiles.setPointSize(appsettings->value(NULL, GC_FONT_CHARTLABELS_SIZE, 8).toInt());
|
||||
|
||||
QwtText title(label);
|
||||
title.setFont(stGiles);
|
||||
QwtPlot::setAxisFont(axis, stGiles);
|
||||
QwtPlot::setAxisTitle(axis, title);
|
||||
}
|
||||
|
||||
void
|
||||
SpinScanPolarPlot::configChanged()
|
||||
{
|
||||
setCanvasBackground(GColor(CRIDEPLOTBACKGROUND));
|
||||
|
||||
QColor col = GColor(CSPINSCANRIGHT);
|
||||
col.setAlpha(120);
|
||||
QBrush brush = QBrush(col);
|
||||
QPen pen(col);
|
||||
pen.setWidth(4); // thicker pen
|
||||
rightCurve->setBrush(Qt::NoBrush);
|
||||
rightCurve->setPen(pen);
|
||||
rightCurve->setStyle(QwtPlotCurve::Lines);
|
||||
rightCurve->setData(*rightSpinScanPolarData);
|
||||
|
||||
QColor col2 = GColor(CSPINSCANLEFT);
|
||||
col2.setAlpha(120);
|
||||
QBrush brush2 = QBrush(col2);
|
||||
QPen pen2(col2);
|
||||
pen2.setWidth(4); // thicker pen
|
||||
leftCurve->setBrush(Qt::NoBrush);
|
||||
leftCurve->setPen(pen2);
|
||||
leftCurve->setStyle(QwtPlotCurve::Lines);
|
||||
leftCurve->setData(*leftSpinScanPolarData);
|
||||
}
|
||||
78
src/SpinScanPolarPlot.h
Normal file
78
src/SpinScanPolarPlot.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Mark Liversedge (liversedge@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _GC_SpinScanPolarPlot_h
|
||||
#define _GC_SpinScanPolarPlot_h 1
|
||||
#include "GoldenCheetah.h"
|
||||
|
||||
#include <QtGui>
|
||||
#include <qwt_plot.h>
|
||||
#include <qwt_plot_marker.h>
|
||||
#include <qwt_plot_curve.h>
|
||||
#include <qwt_plot_grid.h>
|
||||
#include <qwt_scale_draw.h>
|
||||
#include <qwt_scale_div.h>
|
||||
#include <qwt_scale_widget.h>
|
||||
#include <qwt_data.h>
|
||||
#include "Settings.h"
|
||||
|
||||
#include <stdint.h> //uint8_t
|
||||
|
||||
class SpinScanPolarData : public QwtData
|
||||
{
|
||||
bool isleft;
|
||||
uint8_t *spinData;
|
||||
|
||||
public:
|
||||
SpinScanPolarData(uint8_t *spinData, bool isleft) : isleft(isleft), spinData(spinData) { init(); }
|
||||
|
||||
double x(size_t i) const ;
|
||||
double y(size_t i) const ;
|
||||
size_t size() const ;
|
||||
virtual QwtData *copy() const ;
|
||||
void init() ;
|
||||
};
|
||||
|
||||
class SpinScanPolarPlot : public QwtPlot
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
QwtPlotCurve *leftCurve;
|
||||
QwtPlotCurve *rightCurve;
|
||||
|
||||
public:
|
||||
void setAxisTitle(int axis, QString label);
|
||||
|
||||
SpinScanPolarData *leftSpinScanPolarData;
|
||||
SpinScanPolarData *rightSpinScanPolarData;
|
||||
|
||||
SpinScanPolarPlot(QWidget *parent, uint8_t *);
|
||||
|
||||
uint8_t *spinData;
|
||||
|
||||
public slots:
|
||||
void configChanged();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // _GC_SpinScanPolarPlot_h
|
||||
|
||||
@@ -305,6 +305,7 @@ HEADERS += \
|
||||
SimpleNetworkClient.h \
|
||||
SpecialFields.h \
|
||||
SpinScanPlot.h \
|
||||
SpinScanPolarPlot.h \
|
||||
SpinScanPlotWindow.h \
|
||||
SplitRideDialog.h \
|
||||
SplitActivityWizard.h \
|
||||
@@ -480,6 +481,7 @@ SOURCES += \
|
||||
SmallPlot.cpp \
|
||||
SpecialFields.cpp \
|
||||
SpinScanPlot.cpp \
|
||||
SpinScanPolarPlot.cpp \
|
||||
SpinScanPlotWindow.cpp \
|
||||
SplitRideDialog.cpp \
|
||||
SplitActivityWizard.cpp \
|
||||
|
||||
Reference in New Issue
Block a user