File PointCloud.hpp¶
File List > QAccelPlot > src > QAccelPlot > series > PointCloud.hpp
Go to the documentation of this file
//
// SPDX-FileCopyrightText: 2026 Michal Grabarczyk
// SPDX-License-Identifier: GPL-3.0-only WITH Universal-FOSS-exception-1.0
//
// This file is also available under a separate commercial license.
// See COMMERCIAL-LICENSING.md for contact information.
//
#pragma once
#include "QAccelPlot/series/ColormappedSeries.hpp"
#include "QAccelPlot/series/PointSpatialIndex.hpp"
#include "QAccelPlot/series/SeriesMarker.hpp"
#include "QAccelPlot/theme/ColorPalette.hpp"
#include "QAccelPlot/transitions/DataTransition.hpp"
#include <QColor>
#include <QList>
#include <QPointF>
#include <memory>
#include <optional>
#include <vector>
namespace QAccelPlot {
namespace Internal {
class HoverIndexBudget;
}
class TransitionRunner;
class PointCloud : public ColormappedSeries {
Q_OBJECT
QML_NAMED_ELEMENT(PointCloud)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(SeriesMarker* marker READ marker CONSTANT)
Q_PROPERTY(qreal antialiasingFeather READ antialiasingFeather WRITE setAntialiasingFeather NOTIFY antialiasingFeatherChanged)
Q_PROPERTY(qreal hoverRadius READ hoverRadius WRITE setHoverRadius NOTIFY hoverRadiusChanged)
Q_PROPERTY(DataTransition* transition READ transition WRITE setTransition NOTIFY transitionChanged)
Q_PROPERTY(int hoveredIndex READ hoveredIndex NOTIFY hoveredIndexChanged)
public:
explicit PointCloud(QQuickItem* parent = nullptr);
~PointCloud() override;
QColor color() const;
void setColor(const QColor& color);
SeriesMarker* marker() const;
qreal antialiasingFeather() const;
void setAntialiasingFeather(qreal feather);
qreal hoverRadius() const;
void setHoverRadius(qreal radius);
DataTransition* transition() const;
void setTransition(DataTransition* transition);
int hoveredIndex() const;
Q_INVOKABLE void setData(const QList<QPointF>& points);
Q_INVOKABLE void setValues(const QList<qreal>& values);
Q_INVOKABLE QPointF pointAt(int index) const;
Q_INVOKABLE qreal valueAt(int index) const;
void setData(std::vector<double>&& xyInterleaved, std::vector<float>&& values, int pointCount);
void setDataF(std::vector<float>&& xyInterleaved, std::vector<float>&& values, int pointCount);
using PlotSeries::postData;
using PlotSeries::setData;
using PlotSeries::setDataF;
void postData(std::vector<double>&& xyInterleaved, std::vector<float>&& values, int pointCount);
void postData(std::vector<float>&& xyInterleaved, std::vector<float>&& values, int pointCount);
Q_INVOKABLE void clearData() override;
std::optional<LegendEntry> legendEntry() const override;
int pointIndexAt(const QPointF& position) const;
bool contains(const QPointF& point) const override;
signals:
void colorChanged();
void antialiasingFeatherChanged();
void hoverRadiusChanged();
void transitionChanged();
void hoveredIndexChanged();
protected:
Internal::InspectionSource inspectionSource() const override;
QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* updatePaintNodeData) override;
void hoverEnterEvent(QHoverEvent* event) override;
void hoverMoveEvent(QHoverEvent* event) override;
void hoverLeaveEvent(QHoverEvent* event) override;
protected:
void applyDataPoints(DataPointInput&& input) override;
void onAxisScaleChanged() override;
void onDataPointsChanged(DataChange change, int previousCount) override;
std::optional<ValueSpan> scanValueRange() const override;
private:
struct Points {
std::vector<double> values;
int count{0};
int stride{2};
};
bool hasValues() const;
bool validateValues(std::size_t valueCount, int pointCount) const;
void applyData(std::vector<float>&& xyInterleaved, std::vector<float>&& values, int pointCount);
void applyFloatData(std::vector<float>&& xyInterleaved, std::vector<float>&& values, int pointCount);
void applyDoubleData(std::vector<double>&& xyInterleaved, std::vector<float>&& values, int pointCount);
void finishValueChange(int previousCount);
void setHoveredIndex(int index);
int hoverPointCount() const;
void invalidateSpatialIndex();
bool spatialIndexReady(PointSpatialIndex::Mapping mapping) const;
struct HoverQuery {
double x;
double y;
double radiusX;
double radiusY;
PointSpatialIndex::Mapping mapping;
bool operator==(const HoverQuery& other) const;
};
int nearestPoint(const HoverQuery& query) const;
void animateValues(std::vector<float>&& values);
std::vector<double> interleavedData() const;
Points drawnPoints() const;
void startTransition(Points&& drawn);
void advanceTransition();
void endTransition();
void discardTransition();
QColor color_{ColorPalette::dark().seriesPrimary};
SeriesMarker* marker_{new SeriesMarker{MarkerShape::Circle, 3.0, SeriesMarker::NoneShape::Rejected, this}};
qreal antialiasingFeather_{1.0};
qreal hoverRadius_{6.0};
int hoveredIndex_{-1};
std::unique_ptr<TransitionRunner> transition_;
// The previous transition frame, reused for the next one.
std::vector<double> frameBuffer_;
// Render revision of the data points last uploaded to the GPU.
std::uint64_t uploadedRevision_{0};
mutable PointSpatialIndex spatialIndex_;
mutable bool spatialIndexValid_{false};
// Render revision of the data points the spatial index holds.
mutable std::uint64_t indexedRevision_{0};
std::unique_ptr<Internal::HoverIndexBudget> spatialIndexBudget_;
// The last hover query and its answer. Qt tests contains() several times per hover event
// before the handler asks again, each time at the same position.
mutable std::optional<HoverQuery> lastHoverQuery_;
mutable int lastHoverIndex_{-1};
};
} // namespace QAccelPlot