/***************************************************************************
* BGraph.cpp Graph plotter
* T.Barnaby, BEAM Ltd, 2007-05-31
***************************************************************************
*/
#include <BGraph.h>
#include <BString.h>
#include <qpainter.h>
#include <math.h>
#define BDEBUG 0
#if BDEBUG
#define dprintf(fmt, a...) printf(fmt, ##a);
#else
#define dprintf(fmt, a...)
#endif
class AxisLabel : public QWidget {
public:
AxisLabel(QWidget* parent, BGraph* cp);
protected:
void resizeEvent(QResizeEvent* event);
void paintEvent(QPaintEvent* event);
private:
BGraph* ocp;
};
AxisLabel::AxisLabel(QWidget* parent, BGraph* cp) : QWidget(parent), ocp(cp){
}
void AxisLabel::resizeEvent(QResizeEvent* event){
dprintf("AxisLabel::ResizeEvent: %d,%d\n", width(), height());
ocp->drawLabels();
}
void AxisLabel::paintEvent(QPaintEvent* event){
dprintf("AxisLabel::paintEvent:\n");
ocp->drawLabels();
}
BGraphPlot::BGraphPlot(QWidget* parent, BGraph* cp) : QWidget(parent), ocp(cp){
}
void BGraphPlot::resizeEvent(QResizeEvent* event){
dprintf("BGraphPlot::ResizeEvent: %d,%d\n", width(), height());
ocp->redraw();
}
void BGraphPlot::paintEvent(QPaintEvent* event){
dprintf("BGraphPlot::paintEvent:\n");
ocp->redraw();
}
BGraph::BGraph(QWidget* parent) : QGrid(2, parent){
oxRangeMin = 0.0;
oxRangeMax = 0.0;
oyRangeMin = 0.0;
oyRangeMax = 0.0;
oyMinValue = 0;
oyMaxValue = 0;
oxMinValue = 0;
oxMaxValue = 0;
ocolor = blue;
oxGridStep = 0;
oyGridStep = 0;
setFrameShape(QFrame::StyledPanel);
setFrameShadow(QFrame::Raised);
// Display labels etc
oyLabelBox = new AxisLabel(this, this);
oyLabelBox->setFixedWidth(100);
oplotFrame = new QHBox(this);
oplotFrame->setFrameShape(QFrame::StyledPanel);
oplotFrame->setFrameShadow(QFrame::Raised);
ocorner = new QWidget(this, "corner");
ocorner->setFixedHeight(0);
oxLabelBox = new AxisLabel(this, this);
oxLabelBox->setFixedHeight(0);
// Create main plot widget
oplot = new BGraphPlot(oplotFrame, this);
oplot->setBackgroundColor(white);
oplot->show();
drawLabels();
}
BGraph::~BGraph(){
}
void BGraph::setGrid(int xStep, int yStep){
oxGridStep = xStep;
oyGridStep = yStep;
drawGrid();
}
void BGraph::setXLabel(BString label){
oxLabel = label;
drawLabels();
}
void BGraph::setYLabel(BString label){
oyLabel = label;
drawLabels();
}
void BGraph::setXRange(double min, double max){
oxRangeMin = min;
oxRangeMax = max;
drawPlot();
drawGrid();
drawLabels();
}
void BGraph::setYRange(double min, double max){
oyMinValue = oyRangeMin = min;
oyMaxValue = oyRangeMax = max;
drawPlot();
drawGrid();
drawLabels();
}
void BGraph::getXRange(double& min, double& max){
min = oxMinValue;
max = oxMaxValue;
}
void BGraph::setYLabelWidth(int width){
oyLabelBox->setFixedWidth(width);
}
void BGraph::setData(BArray<float> data){
odata = data;
drawPlot();
drawGrid();
drawLabels();
}
void BGraph::getData(BArray<float>& data){
data = odata;
}
void BGraph::redraw(){
dprintf("BGraph::redraw:\n");
drawPlot();
drawGrid();
drawLabels();
}
void BGraph::drawPlot(){
unsigned int x;
unsigned int i;
QPainter p;
double xScale = 1.0;
double xOffset = 1.0;
double yScale = 1.0;
double yOffset = 0;
unsigned int xMin;
unsigned int xMax;
dprintf("DrawPlot\n");
p.begin(oplot);
p.setPen(ocolor);
oplot->erase();
if(odata.size() == 0)
return;
if((oyRangeMin == 0.0) && (oyRangeMax == 0.0)){
oyMinValue = oyMaxValue = odata[0];
for(x = 0; x < odata.size(); x++){
if(odata[x] > oyMaxValue)
oyMaxValue = odata[x];
if(odata[x] < oyMinValue)
oyMinValue = odata[x];
}
yScale = (oplot->height() - 4) / (oyMaxValue - oyMinValue);
yOffset = (oplot->height() - 2) + oyMinValue * yScale;
dprintf("YMin: %f YMax: %f\n", oyMinValue, oyMaxValue);
dprintf("Height: %d Offset: %f Scale: %f\n", oplot->height(), yOffset, yScale);
}
else {
yScale = (oplot->height() - 4) / (oyRangeMax - oyRangeMin);
yOffset = (oplot->height() - 2) + oyRangeMin * yScale;
dprintf("YMin: %f YMax: %f\n", oyRangeMin, oyRangeMax);
dprintf("Height: %d Offset: %f Scale: %f\n", oplot->height(), yOffset, yScale);
}
if((oxRangeMin == 0.0) && (oxRangeMax == 0.0)){
xOffset = 0;
xMin = 0;
xMax = odata.size() - 1;
xScale = double(oplot->width()) / (xMax - xMin);
}
else {
xOffset = int(oxRangeMin);
xMin = int(oxRangeMin);
xMax = int(oxRangeMax);
xScale = double(oplot->width()) / (xMax - xMin);
}
oxMinValue = xMin;
oxMaxValue = xMax;
dprintf("XMin: %d XMax: %d\n", xMin, xMax);
dprintf("Width: %d Offset: %f Scale: %f\n", oplot->width(), xOffset, xScale);
opoints.resize(xMax - xMin);
for(i = 0; i < (xMax - xMin); i++){
x = int(i * xScale);
if(((xOffset + i) >= 0) && ((xOffset + i) < odata.size()))
opoints[i] = QPoint(x, int(yOffset + yScale * -odata[int(xOffset) + i]));
else
opoints[i] = QPoint(0, 0);
}
#ifdef ZAP
for(i = 0; i < opoints.size(); i++){
printf("%d,%d\n", opoints[i].x(), opoints[i].y());
}
#endif
p.drawPolyline(opoints, 0, opoints.size());
p.flush();
}
void BGraph::drawGrid(){
QPainter p;
double x;
double y;
double xs;
double ys;
dprintf("DrawGrid: XStep: %d\n", oxGridStep);
p.begin(oplot);
p.setPen("black");
p.setPen(Qt::DotLine);
if(oxGridStep){
xs = double(oplot->width()) / oxGridStep;
for(x = xs; x < double(oplot->width()); x += xs){
p.drawLine(int(x), 0, int(x), oplot->height());
}
}
if(oyGridStep){
ys = double(oplot->height()) / oyGridStep;
for(y = ys; y < double(oplot->height()); y += ys){
p.drawLine(0, int(y), oplot->width(), int(y));
}
}
}
void BGraph::drawLabels(){
QPainter p;
int w, h;
BString str;
dprintf("DrawLabels\n");
if(oxLabel.len()){
// X Label
oxLabelBox->setFixedHeight(16);
oxLabelBox->erase();
w = oxLabelBox->width();
h = oxLabelBox->height();
p.begin(oxLabelBox);
p.setPen(blue);
str.printf("%-12.6g", oxMinValue);
p.drawLine(2, 0, 2, 6);
p.drawText(QRect(8, 0, w - 16, h), AlignLeft, str.retStr());
str.printf("%12.6g", oxMaxValue);
p.drawLine(w - 3, 0, w - 3, 6);
p.drawText(QRect(8, 0, w - 16, h), AlignRight, str.retStr());
p.drawText(QRect(0, 0, w, h), AlignCenter, oxLabel.retStr());
p.flush();
p.end();
}
else {
ocorner->setFixedHeight(0);
oxLabelBox->setFixedHeight(0);
}
if(oyLabel.len()){
oyLabelBox->erase();
h = oyLabelBox->height();
w = oyLabelBox->width();
p.begin(oyLabelBox);
p.setPen(blue);
str.printf("%12.6g", oyMaxValue);
p.drawLine(w - 5, 2, w, 2);
p.drawText(QRect(0, 3, w, 16), AlignLeft, str.retStr());
str.printf("%12.6g", oyMinValue);
p.drawLine(w - 5, h - 3, w, h - 3);
p.drawText(QRect(0, h - 16, w, h), AlignLeft, str.retStr());
#ifdef ZAP
p.rotate(90);
p.translate(0, -w);
p.drawText(QRect(0, int(w * 0.25), h, int(w * 0.75)), AlignCenter, oyLabel.retStr());
#else
p.drawText(QRect(0, int(h * 0.5 - 8), w, int(h * 0.5 + 8)), AlignLeft, oyLabel.retStr());
#endif
p.flush();
p.end();
}
else {
}
}
void BGraph::clear(){
dprintf("Clear\n");
oplot->erase();
odata.clear();
}
#if DEBUG_MAIN
#include <stdio.h>
#include <syslog.h>
#include <unistd.h>
#include <qapp.h>
#include <qvbox.h>
#include <qtextedit.h>
#include <qpushbutton.h>
#include <qmainwindow.h>
#include <qframe.h>
#include <qdatetimeedit.h>
#include <math.h>
void usage(){
fprintf(stderr, "Usage: testChart\n");
}
int main(int argc, char** argv){
int a;
QApplication* app;
QMainWindow* mw;
QVBox* v;
BGraph* p1;
BGraph* p2;
BGraph* p3;
BGraph* p4;
BArray<float> data;
unsigned int x;
for(a = 1; a < argc; a++){
if(argv[a][0] == '-'){
switch(argv[a][1]){
case 'd':
if(argc <= (a + 1)){
usage();
return 1;
}
// setDebug(strtol(argv[++a], 0, 0));
break;
// QT Options
case 'g':
break;
default: usage(); return 1;
}
}
}
// Create Gui control class
app = new QApplication(argc, argv);
mw = new QMainWindow();
app->setMainWidget(mw);
mw->show();
v = new QVBox(mw);
mw->setCentralWidget(v);
v->show();
data.resize(100);
for(x = 0; x < data.size(); x++){
data[x] = sin((4.0 * 2.0 * 3.14 * x) / data.size());
}
#ifdef ZAP
p1 = new BGraph(v);
p1->show();
p1->setYLabel("FRef");
// p1->setXLabel("Samples");
p1->setData(data);
p2 = new BGraph(v);
p2->show();
p2->setYRange(-0.555555, 2);
// p2->setYRange(-1.0, 1.0);
p2->setYLabel("FRef");
p2->setXLabel("Samples");
p2->setData(data);
#endif
p3 = new BGraph(v);
p3->show();
p3->setYLabelWidth(100);
p3->setGrid(8, 4);
p3->setXRange(25, 75);
p3->setYLabel("FRef");
p3->setXLabel("Samples");
p3->setData(data);
#ifdef ZAP
p4 = new BGraph(v);
p4->show();
for(x = 0; x < data.size(); x++){
data[x] = 30040000.0 + 10000.0 * sin((4.0 * 2.0 * 3.14 * x) / data.size());
}
p4->setYLabelWidth(100);
p4->setGrid(4, 4);
p4->setYLabel("FRef");
p4->setXLabel("Samples");
p4->setData(data);
#endif
app->exec();
return 0;
}
#endif