aboutsummaryrefslogtreecommitdiff
path: root/scatterplot.cpp
diff options
context:
space:
mode:
authorSamuel Fadel <samuel@nihil.ws>2023-05-23 11:22:33 +0200
committerSamuel Fadel <samuel@nihil.ws>2023-05-23 11:22:33 +0200
commit0f34fd437efb936ef29ac91186321aa7251fbfb1 (patch)
tree271e994828f4bb19c35b2630f2705cb64b8d4552 /scatterplot.cpp
parentbedf6936885694688ddb8bd3452f6bd68ef8d29c (diff)
Massive changes in initial port away from Qt.
Diffstat (limited to 'scatterplot.cpp')
-rw-r--r--scatterplot.cpp281
1 files changed, 59 insertions, 222 deletions
diff --git a/scatterplot.cpp b/scatterplot.cpp
index 460e738..fc31daa 100644
--- a/scatterplot.cpp
+++ b/scatterplot.cpp
@@ -2,62 +2,37 @@
#include <algorithm>
#include <cmath>
-#include <limits>
-
-#include <QSGGeometryNode>
-#include <QSGSimpleRectNode>
#include "continuouscolorscale.h"
#include "geometry.h"
// Glyphs settings
-static const QColor DEFAULT_GLYPH_COLOR(255, 255, 255);
+static const Color DEFAULT_GLYPH_COLOR(255, 255, 255);
static const float DEFAULT_GLYPH_SIZE = 8.0f;
-static const qreal GLYPH_OPACITY = 1.0;
-static const qreal GLYPH_OPACITY_SELECTED = 1.0;
+static const float GLYPH_OPACITY = 1.0f;
+static const float GLYPH_OPACITY_SELECTED = 1.0f;
static const float GLYPH_OUTLINE_WIDTH = 2.0f;
-static const QColor GLYPH_OUTLINE_COLOR(0, 0, 0);
-static const QColor GLYPH_OUTLINE_COLOR_SELECTED(20, 255, 225);
+static const Color GLYPH_OUTLINE_COLOR(0, 0, 0);
+static const Color GLYPH_OUTLINE_COLOR_SELECTED(20, 255, 225);
// Brush settings
-static const float BRUSHING_MAX_DIST = 20.0f;
+// BRUSHING_MAX_DIST in quadtree.cpp
static const float CROSSHAIR_LENGTH = 8.0f;
static const float CROSSHAIR_THICKNESS1 = 1.0f;
static const float CROSSHAIR_THICKNESS2 = 0.5f;
-static const QColor CROSSHAIR_COLOR1(255, 255, 255);
-static const QColor CROSSHAIR_COLOR2(0, 0, 0);
+static const Color CROSSHAIR_COLOR1(255, 255, 255);
+static const Color CROSSHAIR_COLOR2(0, 0, 0);
// Selection settings
-static const QColor SELECTION_COLOR(128, 128, 128, 96);
+static const Color SELECTION_COLOR(128, 128, 128, 96);
// Mouse buttons
-static const Qt::MouseButton NORMAL_BUTTON = Qt::LeftButton;
-static const Qt::MouseButton SPECIAL_BUTTON = Qt::RightButton;
+// static const Qt::MouseButton NORMAL_BUTTON = Qt::LeftButton;
+// static const Qt::MouseButton SPECIAL_BUTTON = Qt::RightButton;
-class QuadTree
-{
-public:
- QuadTree(const QRectF &bounds);
- ~QuadTree();
- bool insert(float x, float y, int value);
- int query(float x, float y) const;
- void query(const QRectF &rect, std::vector<int> &result) const;
- int nearestTo(float x, float y) const;
-
-private:
- bool subdivide();
- void nearestTo(float x, float y, int &nearest, float &dist) const;
-
- QRectF m_bounds;
- float m_x, m_y;
- int m_value;
- QuadTree *m_nw, *m_ne, *m_sw, *m_se;
-};
-
-Scatterplot::Scatterplot(QQuickItem *parent)
- : QQuickItem(parent)
- , m_glyphSize(DEFAULT_GLYPH_SIZE)
+Scatterplot::Scatterplot()
+ : m_glyphSize(DEFAULT_GLYPH_SIZE)
, m_colorScale(0)
, m_autoScale(true)
, m_sx(0, 1, 0, 1)
@@ -68,20 +43,10 @@ Scatterplot::Scatterplot(QQuickItem *parent)
, m_dragEnabled(false)
, m_shouldUpdateGeometry(false)
, m_shouldUpdateMaterials(false)
- , m_quadtree(0)
{
- setClip(true);
- setFlag(QQuickItem::ItemHasContents);
}
-Scatterplot::~Scatterplot()
-{
- if (m_quadtree) {
- delete m_quadtree;
- }
-}
-
-void Scatterplot::setColorScale(const ColorScale *colorScale)
+void Scatterplot::setColorScale(std::shared_ptr<const ColorScale> colorScale)
{
m_colorScale = colorScale;
if (m_colorData.n_elem > 0) {
@@ -102,7 +67,7 @@ void Scatterplot::setXY(const arma::mat &xy)
}
m_xy = xy;
- emit xyChanged(m_xy);
+ xyChanged(m_xy);
if (m_autoScale) {
autoScale();
@@ -118,7 +83,7 @@ void Scatterplot::setXY(const arma::mat &xy)
// Reset opacity data
m_opacityData.resize(xy.n_rows);
m_opacityData.fill(GLYPH_OPACITY);
- emit opacityDataChanged(m_opacityData);
+ opacityDataChanged(m_opacityData);
}
m_shouldUpdateGeometry = true;
@@ -133,7 +98,7 @@ void Scatterplot::setColorData(const arma::vec &colorData)
}
m_colorData = colorData;
- emit colorDataChanged(m_colorData);
+ colorDataChanged(m_colorData);
m_shouldUpdateMaterials = true;
update();
@@ -146,7 +111,7 @@ void Scatterplot::setOpacityData(const arma::vec &opacityData)
}
m_opacityData = opacityData;
- emit opacityDataChanged(m_opacityData);
+ opacityDataChanged(m_opacityData);
update();
}
@@ -154,7 +119,7 @@ void Scatterplot::setScale(const LinearScale<float> &sx, const LinearScale<float
{
m_sx = sx;
m_sy = sy;
- emit scaleChanged(m_sx, m_sy);
+ scaleChanged(m_sx, m_sy);
updateQuadTree();
@@ -174,7 +139,7 @@ void Scatterplot::autoScale()
{
m_sx.setDomain(m_xy.col(0).min(), m_xy.col(0).max());
m_sy.setDomain(m_xy.col(1).min(), m_xy.col(1).max());
- emit scaleChanged(m_sx, m_sy);
+ scaleChanged(m_sx, m_sy);
}
void Scatterplot::setGlyphSize(float glyphSize)
@@ -184,12 +149,17 @@ void Scatterplot::setGlyphSize(float glyphSize)
}
m_glyphSize = glyphSize;
- emit glyphSizeChanged(m_glyphSize);
+ glyphSizeChanged(m_glyphSize);
m_shouldUpdateGeometry = true;
update();
}
+void Scatterplot::update()
+{
+}
+
+/*
QSGNode *Scatterplot::newSceneGraph()
{
// NOTE:
@@ -235,7 +205,9 @@ QSGNode *Scatterplot::newSceneGraph()
return root;
}
+*/
+/*
QSGNode *Scatterplot::newGlyphTree()
{
// NOTE:
@@ -282,7 +254,9 @@ QSGNode *Scatterplot::newGlyphTree()
return node;
}
+*/
+/*
QSGNode *Scatterplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
QSGNode *root = oldNode ? oldNode : newSceneGraph();
@@ -321,7 +295,9 @@ QSGNode *Scatterplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
return root;
}
+*/
+/*
void Scatterplot::updateGlyphs(QSGNode *glyphsNode)
{
qreal x, y, tx, ty, moveTranslationF;
@@ -388,7 +364,9 @@ void Scatterplot::updateGlyphs(QSGNode *glyphsNode)
// though.
glyphsNode->markDirty(QSGNode::DirtyForceUpdate);
}
+*/
+/*
void Scatterplot::updateBrush(QSGNode *node)
{
QMatrix4x4 transform;
@@ -404,7 +382,9 @@ void Scatterplot::updateBrush(QSGNode *node)
QSGTransformNode *brushNode = static_cast<QSGTransformNode *>(node);
brushNode->setMatrix(transform);
}
+*/
+/*
void Scatterplot::mousePressEvent(QMouseEvent *event)
{
switch (m_interactionState) {
@@ -425,7 +405,7 @@ void Scatterplot::mousePressEvent(QMouseEvent *event)
case SPECIAL_BUTTON:
m_interactionState = StateNone;
m_selection.assign(m_selection.size(), false);
- emit selectionInteractivelyChanged(m_selection);
+ selectionInteractivelyChanged(m_selection);
m_shouldUpdateMaterials = true;
update();
break;
@@ -438,7 +418,9 @@ void Scatterplot::mousePressEvent(QMouseEvent *event)
break;
}
}
+*/
+/*
void Scatterplot::mouseMoveEvent(QMouseEvent *event)
{
switch (m_interactionState) {
@@ -461,7 +443,9 @@ void Scatterplot::mouseMoveEvent(QMouseEvent *event)
break;
}
}
+*/
+/*
void Scatterplot::mouseReleaseEvent(QMouseEvent *event)
{
bool mergeSelection = (event->modifiers() == Qt::ControlModifier);
@@ -478,7 +462,7 @@ void Scatterplot::mouseReleaseEvent(QMouseEvent *event)
m_interactionState = StateNone;
if (m_anySelected && !mergeSelection) {
m_anySelected = false;
- emit selectionInteractivelyChanged(m_selection);
+ selectionInteractivelyChanged(m_selection);
m_shouldUpdateMaterials = true;
update();
}
@@ -489,7 +473,7 @@ void Scatterplot::mouseReleaseEvent(QMouseEvent *event)
m_anySelected = true;
}
- emit selectionInteractivelyChanged(m_selection);
+ selectionInteractivelyChanged(m_selection);
m_shouldUpdateMaterials = true;
update();
}
@@ -503,7 +487,7 @@ void Scatterplot::mouseReleaseEvent(QMouseEvent *event)
QPoint pos = event->pos();
m_brushedItem = m_quadtree->nearestTo(pos.x(), pos.y());
- emit itemInteractivelyBrushed(m_brushedItem);
+ itemInteractivelyBrushed(m_brushedItem);
m_shouldUpdateMaterials = true;
update();
}
@@ -522,32 +506,39 @@ void Scatterplot::mouseReleaseEvent(QMouseEvent *event)
break;
}
}
+*/
+/*
void Scatterplot::hoverEnterEvent(QHoverEvent *event)
{
QPointF pos = event->posF();
m_brushedItem = m_quadtree->nearestTo(pos.x(), pos.y());
- emit itemInteractivelyBrushed(m_brushedItem);
+ itemInteractivelyBrushed(m_brushedItem);
update();
}
+*/
+/*
void Scatterplot::hoverMoveEvent(QHoverEvent *event)
{
QPointF pos = event->posF();
m_brushedItem = m_quadtree->nearestTo(pos.x(), pos.y());
- emit itemInteractivelyBrushed(m_brushedItem);
+ itemInteractivelyBrushed(m_brushedItem);
update();
}
+*/
+/*
void Scatterplot::hoverLeaveEvent(QHoverEvent *event)
{
m_brushedItem = -1;
- emit itemInteractivelyBrushed(m_brushedItem);
+ itemInteractivelyBrushed(m_brushedItem);
update();
}
+*/
void Scatterplot::interactiveSelection(bool mergeSelection)
{
@@ -556,7 +547,7 @@ void Scatterplot::interactiveSelection(bool mergeSelection)
}
std::vector<int> selected;
- m_quadtree->query(QRectF(m_dragOriginPos, m_dragCurrentPos), selected);
+ m_quadtree->query(RectF(m_dragOriginPos, m_dragCurrentPos), selected);
for (auto i: selected) {
m_selection[i] = true;
}
@@ -568,7 +559,7 @@ void Scatterplot::interactiveSelection(bool mergeSelection)
}
}
- emit selectionInteractivelyChanged(m_selection);
+ selectionInteractivelyChanged(m_selection);
}
void Scatterplot::setSelection(const std::vector<bool> &selection)
@@ -578,7 +569,7 @@ void Scatterplot::setSelection(const std::vector<bool> &selection)
}
m_selection = selection;
- emit selectionChanged(m_selection);
+ selectionChanged(m_selection);
m_shouldUpdateMaterials = true;
update();
@@ -613,7 +604,7 @@ void Scatterplot::applyManipulation()
updateQuadTree();
- emit xyInteractivelyChanged(m_xy);
+ xyInteractivelyChanged(m_xy);
}
void Scatterplot::updateQuadTree()
@@ -621,163 +612,9 @@ void Scatterplot::updateQuadTree()
m_sx.setRange(PADDING, width() - PADDING);
m_sy.setRange(height() - PADDING, PADDING);
- if (m_quadtree) {
- delete m_quadtree;
- }
-
- m_quadtree = new QuadTree(QRectF(x(), y(), width(), height()));
+ m_quadtree.reset(new QuadTree(RectF(x(), y(), width(), height())));
for (arma::uword i = 0; i < m_xy.n_rows; i++) {
const arma::rowvec &row = m_xy.row(i);
m_quadtree->insert(m_sx(row[0]), m_sy(row[1]), (int) i);
}
}
-
-QuadTree::QuadTree(const QRectF &bounds)
- : m_bounds(bounds)
- , m_value(-1)
- , m_nw(0), m_ne(0), m_sw(0), m_se(0)
-{
-}
-
-QuadTree::~QuadTree()
-{
- if (m_nw) {
- delete m_nw;
- delete m_ne;
- delete m_sw;
- delete m_se;
- }
-}
-
-bool QuadTree::subdivide()
-{
- float halfWidth = m_bounds.width() / 2;
- float halfHeight = m_bounds.height() / 2;
-
- m_nw = new QuadTree(QRectF(m_bounds.x(),
- m_bounds.y(),
- halfWidth,
- halfHeight));
- m_ne = new QuadTree(QRectF(m_bounds.x() + halfWidth,
- m_bounds.y(),
- halfWidth,
- halfHeight));
- m_sw = new QuadTree(QRectF(m_bounds.x(),
- m_bounds.y() + halfHeight,
- halfWidth,
- halfHeight));
- m_se = new QuadTree(QRectF(m_bounds.x() + halfWidth,
- m_bounds.y() + halfHeight,
- halfWidth,
- halfHeight));
-
- int value = m_value;
- m_value = -1;
- return m_nw->insert(m_x, m_y, value)
- || m_ne->insert(m_x, m_y, value)
- || m_sw->insert(m_x, m_y, value)
- || m_se->insert(m_x, m_y, value);
-}
-
-bool QuadTree::insert(float x, float y, int value)
-{
- if (!m_bounds.contains(x, y)) {
- return false;
- }
-
- if (m_nw) {
- return m_nw->insert(x, y, value)
- || m_ne->insert(x, y, value)
- || m_sw->insert(x, y, value)
- || m_se->insert(x, y, value);
- }
-
- if (m_value >= 0) {
- subdivide();
- return insert(x, y, value);
- }
-
- m_x = x;
- m_y = y;
- m_value = value;
- return true;
-}
-
-int QuadTree::nearestTo(float x, float y) const
-{
- if (!m_bounds.contains(x, y)) {
- return -1;
- }
-
- int q;
- if (m_nw) {
- q = m_nw->nearestTo(x, y);
- if (q >= 0) return q;
- q = m_ne->nearestTo(x, y);
- if (q >= 0) return q;
- q = m_sw->nearestTo(x, y);
- if (q >= 0) return q;
- q = m_se->nearestTo(x, y);
- if (q >= 0) return q;
- }
-
- float dist = std::numeric_limits<float>::infinity();
- nearestTo(x, y, q, dist);
- if (dist < BRUSHING_MAX_DIST * BRUSHING_MAX_DIST)
- return q;
- return -1;
-}
-
-void QuadTree::nearestTo(float x, float y, int &nearest, float &dist) const
-{
- if (m_nw) {
- m_nw->nearestTo(x, y, nearest, dist);
- m_ne->nearestTo(x, y, nearest, dist);
- m_sw->nearestTo(x, y, nearest, dist);
- m_se->nearestTo(x, y, nearest, dist);
- } else if (m_value >= 0) {
- float d = (m_x - x)*(m_x - x) + (m_y - y)*(m_y - y);
- if (d < dist) {
- nearest = m_value;
- dist = d;
- }
- }
-}
-
-int QuadTree::query(float x, float y) const
-{
- if (!m_bounds.contains(x, y)) {
- // There is no way we could find the point
- return -1;
- }
-
- if (m_nw) {
- int q = -1;
- q = m_nw->query(x, y);
- if (q >= 0) return q;
- q = m_ne->query(x, y);
- if (q >= 0) return q;
- q = m_sw->query(x, y);
- if (q >= 0) return q;
- q = m_se->query(x, y);
- return q;
- }
-
- return m_value;
-}
-
-void QuadTree::query(const QRectF &rect, std::vector<int> &result) const
-{
- if (!m_bounds.intersects(rect)) {
- return;
- }
-
- if (m_nw) {
- m_nw->query(rect, result);
- m_ne->query(rect, result);
- m_sw->query(rect, result);
- m_se->query(rect, result);
- } else if (rect.contains(m_x, m_y) && m_value != -1) {
- result.push_back(m_value);
- }
-}