diff options
author | Samuel Fadel <samuelfadel@gmail.com> | 2015-05-18 18:33:50 -0300 |
---|---|---|
committer | Samuel Fadel <samuelfadel@gmail.com> | 2015-05-21 18:09:02 -0300 |
commit | a96f9f1a2688c215c478cfbee5748b4bb2043a43 (patch) | |
tree | 0f46c89bc7eaa08994faa1095b480baaa1f64c72 | |
parent | 54571b4a4dcc076923325ee09ad348f389fc25a5 (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.cpp | 72 | ||||
-rw-r--r-- | colorscale.h | 24 | ||||
-rw-r--r-- | main.cpp | 9 | ||||
-rw-r--r-- | main_view.qml | 27 | ||||
-rw-r--r-- | pm.pro | 5 | ||||
-rw-r--r-- | scatterplot.cpp | 45 | ||||
-rw-r--r-- | scatterplot.h | 9 |
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 @@ -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 - } - } } @@ -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 |