aboutsummaryrefslogtreecommitdiff
path: root/scatterplot.cpp
diff options
context:
space:
mode:
authorSamuel Fadel <samuelfadel@gmail.com>2015-05-18 13:10:34 -0300
committerSamuel Fadel <samuelfadel@gmail.com>2015-05-18 13:10:34 -0300
commitaafcab1e7237d3ccbc80945eb8379a985d567a53 (patch)
tree3d41130be33ea023d11364f276ca07bcf8bd697d /scatterplot.cpp
parent0b6df071d94ae8f7c9cdd3c96506a1420129e471 (diff)
ForceScheme now (hopefully) does not produce NaNs. Removed the Glyph class and placed all scatterplot drawing code inside the Scatterplot class.
Diffstat (limited to 'scatterplot.cpp')
-rw-r--r--scatterplot.cpp94
1 files changed, 77 insertions, 17 deletions
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 <cmath>
#include <cstdio>
-#include "glyph.h"
#include <QSGNode>
+#include <QSGGeometry>
#include <QSGGeometryNode>
+#include <QSGMaterial>
+#include <QSGFlatColorMaterial>
-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<Glyph *>(*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<QSGNode *>(oldNode);
+ node = oldNode;
}
+ childNode = static_cast<QSGGeometryNode *>(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<QSGGeometryNode *>(childNode->nextSibling());
+ }
node->markDirty(QSGNode::DirtyGeometry);
return node;