From 0f34fd437efb936ef29ac91186321aa7251fbfb1 Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Tue, 23 May 2023 11:22:33 +0200 Subject: Massive changes in initial port away from Qt. --- scatterplot.cpp | 281 ++++++++++++-------------------------------------------- 1 file changed, 59 insertions(+), 222 deletions(-) (limited to 'scatterplot.cpp') diff --git a/scatterplot.cpp b/scatterplot.cpp index 460e738..fc31daa 100644 --- a/scatterplot.cpp +++ b/scatterplot.cpp @@ -2,62 +2,37 @@ #include #include -#include - -#include -#include #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 &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 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 &sx, const LinearScalemarkDirty(QSGNode::DirtyForceUpdate); } +*/ +/* void Scatterplot::updateBrush(QSGNode *node) { QMatrix4x4 transform; @@ -404,7 +382,9 @@ void Scatterplot::updateBrush(QSGNode *node) QSGTransformNode *brushNode = static_cast(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 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 &selection) @@ -578,7 +569,7 @@ void Scatterplot::setSelection(const std::vector &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::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 &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); - } -} -- cgit v1.2.3