aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Fadel <samuelfadel@gmail.com>2015-05-18 18:33:50 -0300
committerSamuel Fadel <samuelfadel@gmail.com>2015-05-21 18:09:02 -0300
commita96f9f1a2688c215c478cfbee5748b4bb2043a43 (patch)
tree0f46c89bc7eaa08994faa1095b480baaa1f64c72
parent54571b4a4dcc076923325ee09ad348f389fc25a5 (diff)
Updated UI.
- Removed unnecessary UI elements from QML file; - Added the ColorScale class and implemented glyph color mapping from class labels; - Mark geometry nodes of individual glyphs as dirty when updating the scene graph.
-rw-r--r--colorscale.cpp72
-rw-r--r--colorscale.h24
-rw-r--r--main.cpp9
-rw-r--r--main_view.qml27
-rw-r--r--pm.pro5
-rw-r--r--scatterplot.cpp45
-rw-r--r--scatterplot.h9
7 files changed, 136 insertions, 55 deletions
diff --git a/colorscale.cpp b/colorscale.cpp
new file mode 100644
index 0000000..50fedae
--- /dev/null
+++ b/colorscale.cpp
@@ -0,0 +1,72 @@
+#include "colorscale.h"
+
+ColorScale::ColorScale(const QColor &firstColor, const QColor &lastColor)
+ : m_colors{firstColor, lastColor}
+{
+ setExtents(0, 1);
+}
+
+ColorScale::ColorScale(std::initializer_list<QColor> colors)
+ : m_colors(colors)
+{
+ setExtents(0, 1);
+}
+
+ColorScale::ColorScale(const QList<QColor> &colors)
+ : m_colors(colors)
+{
+ setExtents(0, 1);
+}
+
+ColorScale::~ColorScale()
+{
+}
+
+void ColorScale::setExtents(qreal min, qreal max)
+{
+ if (min >= max)
+ return;
+
+ m_min = min;
+ m_max = max;
+}
+
+static QColor lerp(const QColor &c1, const QColor &c2, qreal t)
+{
+ qreal r1, g1, b1, a1;
+ qreal r2, g2, b2, a2;
+
+ c1.getRgbF(&r1, &g1, &b1, &a1);
+ c2.getRgbF(&r2, &g2, &b2, &a2);
+ QColor color;
+ color.setRgbF(r1 * (1 - t) + r2 * t,
+ g1 * (1 - t) + g2 * t,
+ b1 * (1 - t) + b2 * t,
+ a1 * (1 - t) + a2 * t);
+ return color;
+}
+
+QColor ColorScale::color(qreal t) const
+{
+ if (t < m_min || t > m_max)
+ return QColor();
+
+ // normalize t
+ t = (t - m_min) / (m_max - m_min);
+
+ // two colors, use a simpler solution
+ if (m_colors.size() == 2)
+ return lerp(m_colors.first(), m_colors.last(), t);
+
+ // find which colors in the scale are adjacent to ours
+ qreal step = 1.0 / m_colors.size();
+ int i = (int) (t / step);
+ int j = i + 1;
+
+ if (i >= m_colors.size() - 1)
+ return QColor(m_colors.last());
+
+ // normalize t between the two colors
+ t = (t - i*step) / (j*step - i*step);
+ return lerp(m_colors[i], m_colors[j], t);
+}
diff --git a/colorscale.h b/colorscale.h
new file mode 100644
index 0000000..6e1212d
--- /dev/null
+++ b/colorscale.h
@@ -0,0 +1,24 @@
+#ifndef COLORSCALE_H
+#define COLORSCALE_H
+
+#include <initializer_list>
+#include <QColor>
+#include <QList>
+
+class ColorScale
+{
+public:
+ ColorScale(const QColor &firstColor, const QColor &lastColor);
+ ColorScale(std::initializer_list<QColor> colors);
+ ColorScale(const QList<QColor> &colors);
+ ~ColorScale();
+
+ void setExtents(qreal min, qreal max);
+ QColor color(qreal t) const;
+
+private:
+ qreal m_min, m_max;
+ QList<QColor> m_colors;
+};
+
+#endif // COLORSCALE_H
diff --git a/main.cpp b/main.cpp
index fb6ab1e..a00d884 100644
--- a/main.cpp
+++ b/main.cpp
@@ -35,9 +35,12 @@ int main(int argc, char **argv)
if (argc > 1) {
arma::mat X;
X.load(argv[1], arma::raw_ascii);
- arma::mat projection = getProjection(X);
- Scatterplot *plot = view.rootObject()->findChild<Scatterplot *>("plot", Qt::FindDirectChildrenOnly);
- plot->setData(projection);
+
+ Scatterplot *plot = view.rootObject()->findChild<Scatterplot *>("plot");
+ arma::mat scatterData(X.n_rows, 3);
+ scatterData.cols(0, 1) = getProjection(X.cols(0, X.n_cols - 2));
+ scatterData.col(2) = X.col(X.n_cols - 1);
+ plot->setData(scatterData);
}
view.show();
diff --git a/main_view.qml b/main_view.qml
index bf143fc..a9ff37e 100644
--- a/main_view.qml
+++ b/main_view.qml
@@ -10,31 +10,4 @@ Item {
objectName: "plot"
anchors.fill: parent
}
-
- Item {
- id: messageBox
- anchors.right: parent.right
- anchors.left: parent.left
- anchors.bottom: parent.bottom
-
- Rectangle {
- color: Qt.rgba(1, 1, 1, 0.7)
- radius: 5
- border.width: 1
- border.color: "white"
- anchors.fill: messageLabel
- anchors.margins: -10
- }
-
- Text {
- id: messageLabel
- color: "black"
- wrapMode: Text.WordWrap
- text: "The background here is a squircle rendered with raw OpenGL using the 'beforeRender()' signal in QQuickWindow. This text label and its border is rendered using QML"
- anchors.right: parent.right
- anchors.left: parent.left
- anchors.bottom: parent.bottom
- anchors.margins: 20
- }
- }
}
diff --git a/pm.pro b/pm.pro
index 2ba534d..1c6e26a 100644
--- a/pm.pro
+++ b/pm.pro
@@ -1,9 +1,12 @@
QT += qml quick
+QMAKE_CXXFLAGS += -std=c++11
QMAKE_LIBS += -larmadillo
-HEADERS += scatterplot.h \
+HEADERS += colorscale.h \
+ scatterplot.h \
mp.h
SOURCES += main.cpp \
+ colorscale.cpp \
scatterplot.cpp \
lamp.cpp \
forceScheme.cpp \
diff --git a/scatterplot.cpp b/scatterplot.cpp
index b5e8261..a3a0dfc 100644
--- a/scatterplot.cpp
+++ b/scatterplot.cpp
@@ -1,18 +1,22 @@
#include "scatterplot.h"
+#include <iostream>
+
#include <cmath>
-#include <cstdio>
#include <QSGNode>
#include <QSGGeometry>
#include <QSGGeometryNode>
#include <QSGMaterial>
#include <QSGFlatColorMaterial>
+#include <QSGSimpleRectNode>
-const int GLYPH_SIZE = 4;
-const float PADDING = 5;
+const int GLYPH_SIZE = 5;
+const float PADDING = 10;
const float PI = 3.1415f;
-Scatterplot::Scatterplot()
+Scatterplot::Scatterplot(QQuickItem *parent)
+ : QQuickItem(parent)
+ , m_colorScale{QColor("red"), QColor("green"), QColor("blue")}
{
setFlag(QQuickItem::ItemHasContents);
}
@@ -23,10 +27,11 @@ Scatterplot::~Scatterplot()
void Scatterplot::setData(const arma::mat &data)
{
- if (data.n_cols != 2)
+ if (data.n_cols != 3)
return;
m_data = data;
+ m_colorScale.setExtents(m_data.col(2).min(), m_data.col(2).max());
update();
}
@@ -68,10 +73,10 @@ void updateSquareGeometry(QSGGeometry *geometry, float size, float cx, float cy)
QSGNode *Scatterplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
+ if (m_data.n_rows < 1)
+ return 0;
+
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(),
@@ -82,19 +87,15 @@ QSGNode *Scatterplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
if (!oldNode) {
node = new QSGNode;
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;
+ QSGGeometryNode *childNode = new QSGGeometryNode;
- geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), vertexCount);
+ QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), vertexCount);
geometry->setDrawingMode(GL_POLYGON);
childNode->setGeometry(geometry);
childNode->setFlag(QSGNode::OwnsGeometry);
- material = new QSGFlatColorMaterial;
- material->setColor(QColor());
+ QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
+ material->setColor(m_colorScale.color(m_data(i, 2)));
childNode->setMaterial(material);
childNode->setFlag(QSGNode::OwnsMaterial);
@@ -104,17 +105,17 @@ QSGNode *Scatterplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
node = oldNode;
}
- childNode = static_cast<QSGGeometryNode *>(node->firstChild());
+ QSGNode *childNode = 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();
+ x = PADDING + (row[0] - xmin) / (xmax - xmin) * (width() - 2*PADDING);
+ y = PADDING + (row[1] - ymin) / (ymax - ymin) * (height() - 2*PADDING);
- geometry = childNode->geometry();
+ QSGGeometry *geometry = static_cast<QSGGeometryNode *>(childNode)->geometry();
updateCircleGeometry(geometry, GLYPH_SIZE, x, y);
- childNode = static_cast<QSGGeometryNode *>(childNode->nextSibling());
+ childNode->markDirty(QSGNode::DirtyGeometry);
+ childNode = childNode->nextSibling();
}
- node->markDirty(QSGNode::DirtyGeometry);
return node;
}
diff --git a/scatterplot.h b/scatterplot.h
index f38ce78..3f2fee6 100644
--- a/scatterplot.h
+++ b/scatterplot.h
@@ -5,22 +5,27 @@
#include <vector>
#include <QQuickItem>
+#include "colorscale.h"
+
class Scatterplot : public QQuickItem
{
Q_OBJECT
public:
- Scatterplot();
+ Scatterplot(QQuickItem *parent = 0);
~Scatterplot();
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
void setData(const arma::mat &data);
signals:
public slots:
+protected:
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
+
private:
arma::mat m_data;
+ ColorScale m_colorScale;
};
#endif // SCATTERPLOT_H