--- /dev/null
+#include "graphdrawer.h"
+#include <QtGui/QPainter>
+
+#include <QDebug>
+
+GraphDrawer::GraphDrawer(QObject *parent) :
+ QObject(parent)
+{
+}
+
+QPixmap* GraphDrawer::drawGraph(const double* const data, const size_t len, size_t w, size_t h, double min, double max)
+{
+ QPixmap* pixmap;
+ QPainter p;
+ int fromX = 0;
+ int fromY;
+ double xStep;
+ double yStep;
+
+ if (w < 1 || h < 1 || data == nullptr || len < 1)
+ return nullptr;
+
+ pixmap = new QPixmap(w, h);
+ p.begin(pixmap);
+ p.fillRect(0, 0, w, h, Qt::white);
+ p.setPen(QColor(Qt::blue));
+
+ xStep = static_cast<double>(w) / len;
+ yStep = static_cast<double>(h) / fabs(max - min);
+ fromY = h - yStep * data[0] - min;
+ for (uint i = 1; i < len; i++) {
+ int toX = xStep * i;
+ int toY = h - yStep * (data[i] - min);
+ p.drawLine(fromX, fromY, toX, toY);
+
+ qDebug() << "fromX" << fromX << "fromY" << fromY << "toX" << toX << "toY" << toY;
+ fromX = toX;
+ fromY = toY;
+ }
+
+ p.end();
+ return pixmap;
+}
+
+bool GraphDrawer::overlayIntegratedPeak(QPixmap* canvas, int startX, int startY, int stopX, int stopY, int peakStartX, int peakStartY, const QString& time,
+ const QString& area)
+{
+ QPainter p;
+ QFont font("arial", 10);
+ QFontMetrics fm(font);
+ int textWidth;
+ if (canvas == nullptr)
+ return false;
+
+ p.begin(canvas);
+ p.setPen(Qt::red);
+ p.drawLine(startX, startY, stopX, stopY);
+
+ /* Draw AREA and TIME caption */
+ p.setFont(font);
+ p.setPen(Qt::black);
+ textWidth = fm.width(time);
+ if (peakStartY - textWidth < 2)
+ peakStartY += textWidth - peakStartY + 2;
+ p.save();
+ p.translate(peakStartX, peakStartY);
+ p.rotate(-90);
+ p.drawText(0, 0, time);
+ p.rotate(+90);
+ p.restore();
+ p.drawText(peakStartX + 5, peakStartY, area);
+ p.end();
+
+ //TODO: Report back what region of the canvas has been updated to allow drawing optimizations
+ return true;
+}
m_graphCrosshairX(-1),
m_graphCrosshairY(-1)
{
+ m_graphDrawer = std::unique_ptr<GraphDrawer>(new GraphDrawer);
setMouseTracking(true);
setCursor(Qt::BlankCursor);
}
update(reg);
}
-void GraphView::drawIntegratedPeak(const int fromX, const double fromY, const int toX, const double toY, const int peakX, const double peakY,
- const QString& time, const QString& area, const bool valley)
-{
- QPainter p;
- QPainter pBB;
- QRegion reg;
- int w, h;
- int startX, startY, stopX, stopY, peakStartX, peakStartY;
- double yStep, xStep;
- double dStartY, dStopY;
- QFont font("arial", 10);
- QFontMetrics fm(font);
- int textWidth;
- if (m_backbuffer == nullptr)
- return;
-
- w = this->width();
- h = this->height();
- xStep = static_cast<double>(w) / m_drawDataLen;
- yStep = static_cast<double>(h) / (m_drawDataMax - m_drawDataMin);
- startX = floor(fromX * xStep + 0.5);
- stopX = floor(toX * xStep + 0.5);
- startY = floor((h - yStep * (fromY - m_drawDataMin)) + 0.5);
- stopY = floor((h - yStep * (toY - m_drawDataMin)) + 0.5);
- peakStartX = floor(peakX * xStep + 0.5);
- peakStartY = floor(h - yStep * (peakY - m_drawDataMin) + 0.5);
-
- dStartY = h - yStep * (fromY - m_drawDataMin);
- dStopY = h - yStep * (toY - m_drawDataMin);
-
- /*qDebug("Drawing peak");
- qDebug() << "RSX" << fromX << "RSY" << fromY << "REX" << toX << "REY" << toY;
- qDebug() << "X step" << xStep << "Y step" << yStep;
- qDebug() << "SX" << startX << "SY" << startY << "EX" << stopX << "EY" << stopY << "w/h" << w << h;
- qDebug() << "DSY" << dStartY << "DEY" << dStopY << "Slope I" << (toY-fromY)/(toX-fromX) << "Slope D" << (dStopY-dStartY)/(toX-fromX);
- qDebug("---");*/
-
- p.begin(m_plainGraph);
- p.setPen(Qt::red);
- p.drawLine(startX, startY, stopX, stopY);
-
- /* Draw AREA and TIME caption */
- p.setFont(font);
- p.setPen(Qt::black);
- textWidth = fm.width(time);
- if (peakStartY - textWidth < 2)
- peakStartY += textWidth - peakStartY + 2;
- p.save();
- p.translate(peakStartX, peakStartY);
- p.rotate(-90);
- p.drawText(0, 0, time);
- p.rotate(+90);
- p.restore();
- p.drawText(peakStartX + 5, peakStartY, area);
- p.end();
-
- /* Copy updated plainGraph to backbuffer */
- pBB.begin(m_backbuffer);
- pBB.drawPixmap(QRect(0, 0, w, h), *m_plainGraph); // Can be optimized!
- //pBB.drawPixmap(startX, 0, *m_plainGraph, startX, 0, w - startX, h);
- pBB.end();
-
- //reg = QRect(startX, 0, w - startX, h);
- update(); //Again - can be optimized!
-}
-
void GraphView::drawIntegrationBaseline(const int x, const int y)
{
QPainter p;
{
int w = this->width();
int h = this->height();
- uint lastColumn = 0;
- double yAvg = 0;
- double yStep;
- QPainter p;
- QPixmap* fresh;
-
- if (m_drawData == nullptr)
- return;
- if (w < 1 || h < 1)
+ QPixmap* fresh = m_graphDrawer->drawGraph(m_drawData, m_drawDataLen, w, h, m_drawDataMin, m_drawDataMax);
+ if (fresh == nullptr)
return;
- fresh = new QPixmap(w, h);
- qDebug() << "DGR" << w << h;
-
- p.begin(fresh);
- p.fillRect(0, 0, w, h, Qt::white);
- p.setPen(QColor(Qt::blue));
-
- /* Scaling */
- yStep = static_cast<double>(h) / fabs(m_drawDataMax - m_drawDataMin);
-
- /* Downscale to grid */
- if (w < m_drawDataLen) {
- double columnsPerPixel = static_cast<double>(m_drawDataLen) / w;
- uint columnsPerLastPixel = 0;
- int* block = new int[w];
- //qDebug() << "CPP" << columnsPerPixel << "yStep" << yStep << "Dims" << h << w << "Data" << w*columnsPerPixel << m_graphLen;
- for (uint i = 0; i < m_drawDataLen; i++) {
- uint column = i / columnsPerPixel;
- if (column != lastColumn) {
- yAvg /= columnsPerLastPixel;
- block[lastColumn] = h - yStep * (yAvg -m_drawDataMin);
- //qDebug() << "YAVG" << block[lastColumn] << "CPLP" << columnsPerLastPixel;
- yAvg = 0;
- columnsPerLastPixel= 0;
- lastColumn = column;
- }
- yAvg += m_drawData[i];
- columnsPerLastPixel++;
- }
- /* Add the last column */
- yAvg /= columnsPerLastPixel;
- block[w-1] = h - yStep * (yAvg - m_drawDataMin);
- /* Draw the pixmap */
- for (int i = 1; i < w; i++)
- p.drawLine(i-1, floor(block[i-1]+0.5), i, floor(block[i]+0.5));
- //qDebug() << "LAST YAVG" << block[m_graphLen-1] << "CPLP" << columnsPerLastPixel;
- delete[] block;
- } else { /* Upscale to grid */
- double pixelsPerValue = static_cast<double>(w) / m_drawDataLen;
- uint cPixX;
- uint pPixX = 0;
- uint cPixY;
- uint pPixY = floor((h - yStep * (m_drawData[0] - m_drawDataMin)) + 0.5);
- for (int i = 1; i < m_drawDataLen; i++) {
- cPixX= floor(i * pixelsPerValue + 0.5);
- cPixY = h - yStep * (m_drawData[i] - m_drawDataMin);
- //qDebug() << "Upscale" << pPixX << pPixY << cPixX << cPixY;
- p.drawLine(pPixX, pPixY, cPixX, cPixY);
- pPixX = cPixX;
- pPixY = cPixY;
- }
- }
-
if (m_backbuffer != nullptr)
delete m_backbuffer;
m_backbuffer = fresh;
void GraphView::onDrawIntegration(const int fromX, const double fromY, const int toX, const double toY, const int peakX, const double peakY,
const QString& time, const QString& area, const bool valley)
{
- this->drawIntegratedPeak(fromX, fromY, toX, toY, peakX, peakY, time, area, valley);
+ int w = this->width();
+ int h = this->height();
+ double xStep = static_cast<double>(w) / m_drawDataLen;
+ double yStep = static_cast<double>(h) / (m_drawDataMax - m_drawDataMin);
+ int startX = floor(fromX * xStep + 0.5);
+ int stopX = floor(toX * xStep + 0.5);
+ int startY = floor((h - yStep * (fromY - m_drawDataMin)) + 0.5);
+ int stopY = floor((h - yStep * (toY - m_drawDataMin)) + 0.5);
+ int peakStartX = floor(peakX * xStep + 0.5);
+ int peakStartY = floor(h - yStep * (peakY - m_drawDataMin) + 0.5);
+
+ if (m_graphDrawer->overlayIntegratedPeak(m_plainGraph, startX, startY, stopX, stopY, peakStartX, peakStartY, time, area)) {
+ //TODO: Optimize so that the whole graph is not redrawn on each integration
+ QPainter pBB(m_backbuffer);
+ pBB.drawPixmap(QRect(0, 0, w, h), *m_plainGraph);
+ update();
+ }
}
void GraphView::onUpdateGraph(double* data, size_t len, double min, double max)