From aafcab1e7237d3ccbc80945eb8379a985d567a53 Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Mon, 18 May 2015 13:10:34 -0300 Subject: ForceScheme now (hopefully) does not produce NaNs. Removed the Glyph class and placed all scatterplot drawing code inside the Scatterplot class. --- scatterplot.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 17 deletions(-) (limited to 'scatterplot.cpp') diff --git a/scatterplot.cpp b/scatterplot.cpp index e775661..b5e8261 100644 --- a/scatterplot.cpp +++ b/scatterplot.cpp @@ -1,11 +1,16 @@ #include "scatterplot.h" +#include #include -#include "glyph.h" #include +#include #include +#include +#include -const int GLYPH_SIZE = 10; +const int GLYPH_SIZE = 4; +const float PADDING = 5; +const float PI = 3.1415f; Scatterplot::Scatterplot() { @@ -22,38 +27,93 @@ void Scatterplot::setData(const arma::mat &data) return; m_data = data; - qreal xmin = m_data.col(0).min(), - xmax = m_data.col(0).max(), - ymin = m_data.col(1).min(), - ymax = m_data.col(1).max(); + update(); +} - for (arma::uword i = 0; i < m_data.n_rows; i++) { - arma::rowvec row = m_data.row(i); +int calculateCircleVertexCount(qreal radius) +{ + // 10 * sqrt(r) \approx 2*pi / acos(1 - 1 / (4*r)) + return (int) (10.0 * sqrt(radius)); +} + +void updateCircleGeometry(QSGGeometry *geometry, float size, float cx, float cy) +{ + int vertexCount = geometry->vertexCount(); - Glyph *glyph = new Glyph(); + float theta = 2 * PI / float(vertexCount); + float c = cosf(theta); + float s = sinf(theta); + float x = size / 2; + float y = 0; - glyph->setSize(5); - glyph->setX((row[0] - xmin) / (xmax - xmin) * width()); - glyph->setY((row[1] - ymin) / (ymax - ymin) * height()); + QSGGeometry::Point2D *vertexData = geometry->vertexDataAsPoint2D(); + for (int i = 0; i < vertexCount; i++) { + vertexData[i].set(x + cx, y + cy); - glyph->setParent(this); + float t = x; + x = c*x - s*y; + y = s*t + c*y; } +} - update(); +void updateSquareGeometry(QSGGeometry *geometry, float size, float cx, float cy) +{ + float r = size / 2; + QSGGeometry::Point2D *vertexData = geometry->vertexDataAsPoint2D(); + vertexData[0].set(cx - r, cy - r); + vertexData[1].set(cx + r, cy - r); + vertexData[2].set(cx + r, cy + r); + vertexData[3].set(cx - r, cy + r); } QSGNode *Scatterplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { QSGNode *node = 0; + QSGGeometryNode *childNode = 0; + QSGGeometry *geometry = 0; + QSGFlatColorMaterial *material = 0; + int vertexCount = calculateCircleVertexCount(GLYPH_SIZE / 2); + qreal xmin = m_data.col(0).min(), + xmax = m_data.col(0).max(), + ymin = m_data.col(1).min(), + ymax = m_data.col(1).max(), + x, y; if (!oldNode) { node = new QSGNode; - for (QObjectList::const_iterator it = children().begin(); it != children().end(); it++) - node->appendChildNode(static_cast(*it)->updatePaintNode(0, 0)); + for (arma::uword i = 0; i < m_data.n_rows; i++) { + arma::rowvec row = m_data.row(i); + x = (row[0] - xmin) / (xmax - xmin) * width(); + y = (row[1] - ymin) / (ymax - ymin) * height(); + + childNode = new QSGGeometryNode; + + geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), vertexCount); + geometry->setDrawingMode(GL_POLYGON); + childNode->setGeometry(geometry); + childNode->setFlag(QSGNode::OwnsGeometry); + + material = new QSGFlatColorMaterial; + material->setColor(QColor()); + childNode->setMaterial(material); + childNode->setFlag(QSGNode::OwnsMaterial); + + node->appendChildNode(childNode); + } } else { - node = static_cast(oldNode); + node = oldNode; } + childNode = static_cast(node->firstChild()); + for (arma::uword i = 0; i < m_data.n_rows; i++) { + arma::rowvec row = m_data.row(i); + x = (row[0] - xmin) / (xmax - xmin) * width(); + y = (row[1] - ymin) / (ymax - ymin) * height(); + + geometry = childNode->geometry(); + updateCircleGeometry(geometry, GLYPH_SIZE, x, y); + childNode = static_cast(childNode->nextSibling()); + } node->markDirty(QSGNode::DirtyGeometry); return node; -- cgit v1.2.3