Add Polar SpinScan Plot

The Power Stroke chart will now show a
bar or polar chart.
This commit is contained in:
Mark Liversedge
2011-12-03 15:08:23 +00:00
parent feaef59169
commit 04ff0a2249
8 changed files with 274 additions and 6 deletions

View File

@@ -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;

View File

@@ -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");

View File

@@ -64,7 +64,7 @@ class SpinScanPlot : public QwtPlot
SpinScanData *leftSpinScanData;
SpinScanData *rightSpinScanData;
SpinScanPlot(uint8_t *);
SpinScanPlot(QWidget *parent, uint8_t *);
uint8_t *spinData;

View File

@@ -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
}

View File

@@ -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
View 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
View 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

View File

@@ -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 \