/*************************************************************************** * 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