From e05a1bd658a7bacb4e13f05b7125ceed7a33dd4b Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Thu, 3 Sep 2015 14:31:52 -0300 Subject: Updated Scatteplot's drawing code. - All glyphs use the same geometry, placement is done via affine transforms - Geometry memory handled using unique_ptr - Added outline to each glyph, avoiding color issues with the background --- scatterplot.cpp | 52 +++++++++++++++++++++++++++++++++++++--------------- scatterplot.h | 2 ++ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/scatterplot.cpp b/scatterplot.cpp index 0a252e1..ce8f590 100644 --- a/scatterplot.cpp +++ b/scatterplot.cpp @@ -1,10 +1,14 @@ #include "scatterplot.h" +#include #include static const qreal GLYPH_OPACITY = 0.4; static const qreal GLYPH_OPACITY_SELECTED = 1.0; -static const QColor SELECTION_COLOR(QColor(128, 128, 128, 96)); + +static const QColor OUTLINE_COLOR(0, 0, 0); +static const QColor SELECTION_COLOR(128, 128, 128, 96); + static const int GLYPH_SIZE = 8; static const float PADDING = 10; static const float PI = 3.1415f; @@ -123,22 +127,40 @@ QSGNode *Scatterplot::createGlyphNodeTree() QSGNode *node = new QSGNode; int vertexCount = calculateCircleVertexCount(GLYPH_SIZE / 2); - for (arma::uword i = 0; i < m_xy.n_rows; i++) { - QSGGeometryNode *glyphNode = new QSGGeometryNode; + m_glyphGeometryPtr.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), vertexCount)); + QSGGeometry *glyphGeometry = m_glyphGeometryPtr.get(); + glyphGeometry->setDrawingMode(GL_POLYGON); + updateCircleGeometry(glyphGeometry, GLYPH_SIZE, 0, 0); + + m_glyphOutlineGeometryPtr.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), vertexCount)); + QSGGeometry *glyphOutlineGeometry = m_glyphOutlineGeometryPtr.get(); + glyphOutlineGeometry->setDrawingMode(GL_LINE_LOOP); + updateCircleGeometry(glyphOutlineGeometry, GLYPH_SIZE + 1, 0, 0); - QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), vertexCount); - geometry->setDrawingMode(GL_POLYGON); - glyphNode->setGeometry(geometry); - glyphNode->setFlag(QSGNode::OwnsGeometry); + for (arma::uword i = 0; i < m_xy.n_rows; i++) { + QSGGeometryNode *glyphOutlineNode = new QSGGeometryNode; + glyphOutlineNode->setGeometry(glyphOutlineGeometry); QSGFlatColorMaterial *material = new QSGFlatColorMaterial; + material->setColor(OUTLINE_COLOR); + glyphOutlineNode->setMaterial(material); + glyphOutlineNode->setFlag(QSGNode::OwnsMaterial); + + QSGGeometryNode *glyphNode = new QSGGeometryNode; + glyphNode->setGeometry(glyphGeometry); + + material = new QSGFlatColorMaterial; material->setColor(QColor()); glyphNode->setMaterial(material); glyphNode->setFlag(QSGNode::OwnsMaterial); + QSGTransformNode *transformNode = new QSGTransformNode; + transformNode->appendChildNode(glyphNode); + transformNode->appendChildNode(glyphOutlineNode); + // Place the glyph geometry node under an opacity node QSGOpacityNode *glyphOpacityNode = new QSGOpacityNode; - glyphOpacityNode->appendChildNode(glyphNode); + glyphOpacityNode->appendChildNode(transformNode); node->appendChildNode(glyphOpacityNode); } @@ -150,7 +172,8 @@ QSGNode *Scatterplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) if (m_xy.n_rows < 1) return 0; - qreal x, y, tx, ty, moveTranslationF; + QMatrix4x4 matrix; + qreal tx, ty, moveTranslationF; QSGNode *root = 0; if (!oldNode) { @@ -173,16 +196,15 @@ QSGNode *Scatterplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) QSGOpacityNode *glyphOpacityNode = static_cast(node); glyphOpacityNode->setOpacity(isSelected ? GLYPH_OPACITY_SELECTED : GLYPH_OPACITY); - QSGGeometryNode *glyphNode = static_cast(node->firstChild()); + QSGTransformNode *transformNode = static_cast(node->firstChild()); if (m_shouldUpdateGeometry) { - QSGGeometry *geometry = glyphNode->geometry(); moveTranslationF = isSelected ? 1.0 : 0.0; - x = fromDataXToScreenX(row[0]) + tx * moveTranslationF; - y = fromDataYToScreenY(row[1]) + ty * moveTranslationF; - updateCircleGeometry(geometry, GLYPH_SIZE, x, y); - glyphNode->markDirty(QSGNode::DirtyGeometry); + matrix(0, 3) = fromDataXToScreenX(row[0]) + tx * moveTranslationF; + matrix(1, 3) = fromDataYToScreenY(row[1]) + ty * moveTranslationF; + transformNode->setMatrix(matrix); } if (m_shouldUpdateMaterials) { + QSGGeometryNode *glyphNode = static_cast(transformNode->firstChild()); QSGFlatColorMaterial *material = static_cast(glyphNode->material()); material->setColor(m_colorScale->color(m_colorData[i])); glyphNode->setMaterial(material); diff --git a/scatterplot.h b/scatterplot.h index 7ed58c8..4275561 100644 --- a/scatterplot.h +++ b/scatterplot.h @@ -1,6 +1,7 @@ #ifndef SCATTERPLOT_H #define SCATTERPLOT_H +#include #include #include @@ -54,6 +55,7 @@ private: QSet m_selectedGlyphs; + std::unique_ptr m_glyphGeometryPtr, m_glyphOutlineGeometryPtr; bool m_shouldUpdateGeometry, m_shouldUpdateMaterials; arma::vec m_colorData; -- cgit v1.2.3