From ce03d5bff5ca0c06ac884628c8ef65b902de669f Mon Sep 17 00:00:00 2001 From: Nikita Kostovsky Date: Sat, 9 Nov 2024 17:28:58 +0100 Subject: Initial commit --- QmlCustomPlot.cpp | 335 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 QmlCustomPlot.cpp (limited to 'QmlCustomPlot.cpp') diff --git a/QmlCustomPlot.cpp b/QmlCustomPlot.cpp new file mode 100644 index 0000000..48ec917 --- /dev/null +++ b/QmlCustomPlot.cpp @@ -0,0 +1,335 @@ +#include "QmlCustomPlot.h" + +#include + +#include + +QmlCustomPlot::QmlCustomPlot(QQuickItem* parent) + : QQuickPaintedItem(parent) + , m_timerId(0) +{ + setFlag(QQuickItem::ItemHasContents, true); + setAcceptedMouseButtons(Qt::AllButtons); + + connect(this, &QQuickPaintedItem::widthChanged, + this, &QmlCustomPlot::updateCustomPlotSize); + connect(this, &QQuickPaintedItem::heightChanged, + this, &QmlCustomPlot::updateCustomPlotSize); + + auto t = new QTimer(this); + t->setInterval(1000); + t->setTimerType(Qt::VeryCoarseTimer); + t->setSingleShot(false); + + connect(t, &QTimer::timeout, this, [&](){ + setFps(m_fpsCounter); + m_fpsCounter = 0; + }); + + t->start(); +} + +QmlCustomPlot::~QmlCustomPlot() +{ + delete m_plot; + m_plot = nullptr; + + if(m_timerId != 0) + { + killTimer(m_timerId); + } +} + +void QmlCustomPlot::initCustomPlot() +{ + setPlot(new QCustomPlot()); +} + +void QmlCustomPlot::setPlot(QCustomPlot *plot) +{ + // m_plot = new QCustomPlot(); + m_plot = plot; + + m_plot->setBackgroundScaled(true); + m_plot->setBackgroundScaledMode(Qt::KeepAspectRatio); + + updateCustomPlotSize(); + m_plot->xAxis->setLabel("x"); + m_plot->yAxis->setLabel("y"); + m_plot->xAxis->setRange(-50, 50); + m_plot->yAxis->setRange(0, 100); + m_plot ->setInteractions(QCP::iRangeDrag | + QCP::iRangeZoom | + QCP::iSelectPlottables | + QCP::iSelectItems | + QCP::iSelectOther); + + if(m_profileGraph == nullptr) + { + m_profileGraph = m_plot->addGraph(); + + m_profileGraph->setLineStyle(QCPGraph::lsNone); + m_profileGraph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 2)); + m_profileGraph->setPen(QPen(QColor(Qt::red))); + } + + startTimer(1000 / 24); + + connect(m_plot, &QCustomPlot::afterReplot, this, &QmlCustomPlot::onCustomReplot); + + m_plot->replot(); +} + +void QmlCustomPlot::setPoints(const QVector points) +{ + QVector x; //(qsizetype(points.count())); + QVector y; //(qsizetype(points.count())); + + for(const auto & p : points) + { + // break; + if(qFuzzyIsNull(p.x()) && qFuzzyIsNull(p.y())) + { + qt_noop(); + } + + x << p.x(); + y << p.y(); + + } + + m_profileGraph->setData(x, y); + + // setLines({ + // QLineF(rand() % 100 - 50, rand() % 100, rand() % 100 - 50, rand() % 100), + // QLineF(rand() % 100 - 50, rand() % 100, rand() % 100 - 50, rand() % 100) + // }); +} + +void QmlCustomPlot::setLines(const QVector lines) +{ + while(m_lineItems.count() > lines.count()) + { + m_plot->removeItem(m_lineItems.takeLast()); + } + + m_lineItems.reserve(lines.count()); + + const QCPLineEnding lineEnding(QCPLineEnding::esNone); + + for(int i = 0; i < lines.count(); i++) + { + // const QPen linePen(QColor(Qt::green), 4); + // const QColor color(Qt::green); + // QRgb green = QRandomGenerator::generate(); + // QRgb blue = QRandomGenerator::generate(); + const QColor color { QRgb { QRandomGenerator::global()->generate() } }; + const QPen linePen(color, 4); + QCPItemLine * l; + + if(i >= m_lineItems.count()) + { + l = new QCPItemLine(m_plot); + l->setPen(linePen); + l->setHead(lineEnding); + l->setTail(lineEnding); + + m_lineItems << l; + } + else + { + l = m_lineItems[i]; + } + + const QPointF offset(0, 2); + + const auto & lineToSet = lines.at(i); + l->start->setCoords(lineToSet.p1() + offset); + l->end->setCoords(lineToSet.p2() + offset); + } +} + +void QmlCustomPlot::setContours(const QVector contours) +{ + qDebug() << "contours count" << contours.count(); + + while(m_contourGraphs.count() > contours.count()) + { + m_plot->removeGraph(m_contourGraphs.takeLast()); + } + + m_contourGraphs.reserve(contours.count()); + + for(int i = 0; i < contours.count(); i++) + { + const QColor color(rand() % 0xff, rand() % 0xff, rand() % 0xff); + const QPen contourPen(color, 4); + + QCPGraph * c; + + // create new + if(i >= m_contourGraphs.count()) + { + c = m_plot->addGraph(); + + c->setLineStyle(QCPGraph::lsNone); + c->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 2)); + c->setPen(contourPen); + + m_contourGraphs << c; + } + // use existing graph object + else + { + c = m_contourGraphs[i]; + } + + // set data + const auto & contourToAdd = contours.at(i); + + QVector x; //(qsizetype(contourToAdd.count())); + QVector y; //(qsizetype(contourToAdd.count())); + + for(const auto & p : contourToAdd) + { + x << p.x(); + y << p.y() + 5; + } + + c->setData(x, y); + } +} + +void QmlCustomPlot::setFps(int fps) +{ + m_fps = fps; + emit fpsChanged(); +} + +//void QmlCustomPlot::setPlot(QCustomPlot *plot) +//{ + +//} + +void QmlCustomPlot::paint(QPainter* painter) +{ + if(m_plot) + { + + QPixmap picture(boundingRect().size().toSize()); + QCPPainter qcpPainter(&picture); + + m_plot->toPainter(&qcpPainter); + + // m_bg->topLeft->setCoords(m_plot->xAxis->range().minRange, m_plot->yAxis->range().minRange); + // m_bg->bottomRight->setCoords(m_plot->xAxis->range().maxRange, m_plot->yAxis->range().maxRange); + // m_bg->topLeft->setCoords(0, 0); + // m_bg->bottomRight->setCoords(640, 480); + + painter->drawPixmap(QPoint(), picture); + + // qDebug() << m_plot->axisRect(); + } +} + +QCustomPlot *QmlCustomPlot::plot() const +{ + return m_plot; +} + +int QmlCustomPlot::fps() const +{ + return m_fps; +} + +void QmlCustomPlot::mousePressEvent(QMouseEvent* event) +{ + routeMouseEvents(event); +} + +void QmlCustomPlot::mouseReleaseEvent(QMouseEvent* event) +{ + routeMouseEvents(event); +} + +void QmlCustomPlot::mouseMoveEvent(QMouseEvent* event) +{ + routeMouseEvents(event); +} + +void QmlCustomPlot::mouseDoubleClickEvent(QMouseEvent* event) +{ + qDebug() << Q_FUNC_INFO; + routeMouseEvents(event); +} + +void QmlCustomPlot::wheelEvent(QWheelEvent *event) +{ + routeWheelEvents(event); +} + +void QmlCustomPlot::timerEvent(QTimerEvent *event) +{ + // static double t, U; + // U = ((double)rand() / RAND_MAX) * 5; + // m_plot->graph(0)->addData(t, U); + // qDebug() << Q_FUNC_INFO << QString("Adding dot t = %1, S = %2").arg(t).arg(U); + // t++; + m_plot->replot(); +} + +void QmlCustomPlot::graphClicked(QCPAbstractPlottable* plottable) +{ + qDebug() << Q_FUNC_INFO << QString("Clicked on graph '%1 ").arg(plottable->name()); +} + +void QmlCustomPlot::routeMouseEvents(QMouseEvent* event) +{ + if(m_plot) + { + QMouseEvent* newEvent = new QMouseEvent( + event->type(), + event->position(), + event->scenePosition(), + event->globalPosition(), + event->button(), + event->buttons(), + event->modifiers(), + event->source()); + QCoreApplication::postEvent(m_plot, newEvent); + } +} + +void QmlCustomPlot::routeWheelEvents(QWheelEvent* event) +{ + if(m_plot) + { + QWheelEvent* newEvent = new QWheelEvent( + event->position(), + event->globalPosition(), + event->pixelDelta(), + event->angleDelta(), + event->buttons(), + event->modifiers(), + event->phase(), + false); + QCoreApplication::postEvent(m_plot, newEvent); + } +} + +void QmlCustomPlot::updateCustomPlotSize() +{ + if(m_plot) + { + const QRect r(0, 0, int(width()), int(height())); + m_plot->setGeometry(r); + m_plot->setViewport(r); + } +} + +void QmlCustomPlot::onCustomReplot() +{ + // qDebug() << Q_FUNC_INFO; + m_fpsCounter++; + update(); +} -- cgit v1.2.3-70-g09d2