aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Fadel <samuelfadel@gmail.com>2016-02-28 21:46:31 -0300
committerSamuel Fadel <samuelfadel@gmail.com>2016-02-28 21:46:31 -0300
commitd3d3526bab2ab051656a1b80b4e0f1337037b5de (patch)
tree1df83705676cfac7cc8f755d8025d05b1b1e43cd
parent5bd1fec462466d605f974fa27c3b00826a1bab57 (diff)
Added colormap orientation & improved UI.
* Colormap: orientation now enables vertical & horizontal colormap display * Two colormap components, one for each type of point (regular, control) * Improved controls grouping and cohesion
-rw-r--r--colormap.cpp77
-rw-r--r--colormap.h14
-rw-r--r--main.cpp14
-rw-r--r--main.h33
-rw-r--r--main_view.qml269
5 files changed, 246 insertions, 161 deletions
diff --git a/colormap.cpp b/colormap.cpp
index cc57048..3ebf5c8 100644
--- a/colormap.cpp
+++ b/colormap.cpp
@@ -1,5 +1,7 @@
#include "colormap.h"
+#include <algorithm>
+
#include <QOpenGLFunctions>
#include <QSGSimpleTextureNode>
@@ -7,7 +9,8 @@ class ColormapTexture
: public QSGDynamicTexture
{
public:
- ColormapTexture(const std::vector<float> *cmap);
+ ColormapTexture(const std::vector<float> *cmap,
+ Colormap::Orientation orientation = Colormap::Horizontal);
~ColormapTexture();
bool hasAlphaChannel() const { return false; }
@@ -18,26 +21,29 @@ public:
int textureId() const { return m_texture; }
QSize textureSize() const { return m_size; }
+ void setOrientation(Colormap::Orientation orientation);
+
private:
QOpenGLFunctions gl;
+ Colormap::Orientation m_orientation;
QSize m_size;
GLuint m_texture;
const std::vector<float> *m_cmap;
};
-ColormapTexture::ColormapTexture(const std::vector<float> *cmap)
+ColormapTexture::ColormapTexture(const std::vector<float> *cmap,
+ Colormap::Orientation orientation)
: gl(QOpenGLContext::currentContext())
- , m_size(cmap->size() / 3, 1)
, m_cmap(cmap)
{
// Setup OpenGL texture
gl.glGenTextures(1, &m_texture);
gl.glBindTexture(GL_TEXTURE_2D, m_texture);
- gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_size.width(), m_size.height(),
- 0, GL_RGB, GL_FLOAT, 0);
gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ setOrientation(orientation);
}
ColormapTexture::~ColormapTexture()
@@ -50,9 +56,28 @@ void ColormapTexture::bind()
gl.glBindTexture(GL_TEXTURE_2D, m_texture);
}
+void ColormapTexture::setOrientation(Colormap::Orientation orientation)
+{
+ if (m_orientation == orientation) {
+ return;
+ }
+
+ m_orientation = orientation;
+ updateTexture();
+}
+
bool ColormapTexture::updateTexture()
{
- m_size.setWidth(m_cmap->size() / 3);
+ switch (m_orientation) {
+ case Colormap::Horizontal:
+ m_size.setWidth(m_cmap->size() / 3);
+ m_size.setHeight(1);
+ break;
+ case Colormap::Vertical:
+ m_size.setWidth(1);
+ m_size.setHeight(m_cmap->size() / 3);
+ break;
+ }
gl.glBindTexture(GL_TEXTURE_2D, m_texture);
gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_size.width(), m_size.height(),
@@ -64,6 +89,7 @@ Colormap::Colormap(QQuickItem *parent)
: QQuickItem(parent)
, m_texture(0)
, m_shouldUpdateTexture(false)
+ , m_orientation(Colormap::Horizontal)
{
setFlag(QQuickItem::ItemHasContents);
}
@@ -75,11 +101,42 @@ Colormap::~Colormap()
}
}
+static void reverseCMap(std::vector<float> &cmap)
+{
+ decltype(cmap.size()) i = 0, j = cmap.size() - 3;
+
+ while (i < j) {
+ std::swap(cmap[i++], cmap[j++]);
+ std::swap(cmap[i++], cmap[j++]);
+ std::swap(cmap[i++], cmap[j++]);
+
+ j -= 6;
+ }
+}
+
+void Colormap::setOrientation(Colormap::Orientation orientation)
+{
+ if (m_orientation == orientation) {
+ return;
+ }
+
+ if (!m_cmap.empty()) {
+ reverseCMap(m_cmap);
+ }
+
+ m_orientation = orientation;
+ m_shouldUpdateOrientation = true;
+ update();
+}
void Colormap::setColorScale(const ColorScale &scale)
{
m_cmap.resize(scale.numColors() * 3);
scale.sample(scale.numColors(), m_cmap.data());
+ if (m_orientation == Colormap::Vertical) {
+ reverseCMap(m_cmap);
+ }
+
emit colorScaleChanged(scale);
m_shouldUpdateTexture = true;
@@ -107,8 +164,14 @@ QSGNode *Colormap::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(root);
node->setRect(x(), y(), width(), height());
+ ColormapTexture *texture = static_cast<ColormapTexture *>(m_texture);
+ if (m_shouldUpdateOrientation) {
+ texture->setOrientation(m_orientation);
+ m_shouldUpdateOrientation = false;
+ }
+
if (m_shouldUpdateTexture) {
- m_texture->updateTexture();
+ texture->updateTexture();
m_shouldUpdateTexture = false;
}
diff --git a/colormap.h b/colormap.h
index 806624a..eda4492 100644
--- a/colormap.h
+++ b/colormap.h
@@ -14,14 +14,25 @@ class Colormap
: public QQuickItem
{
Q_OBJECT
+ Q_ENUMS(Orientation)
+ Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
public:
static const int SAMPLES = 128;
+ enum Orientation {
+ Horizontal,
+ Vertical
+ };
+
Colormap(QQuickItem *parent = 0);
~Colormap();
+ void setOrientation(Orientation orientation);
+ Orientation orientation() const { return m_orientation; }
+
signals:
void colorScaleChanged(const ColorScale &scale) const;
+ void orientationChanged(Orientation orientation) const;
public slots:
void setColorScale(const ColorScale &scale);
@@ -33,7 +44,8 @@ private:
QSGNode *newSceneGraph();
QSGDynamicTexture *m_texture;
- bool m_shouldUpdateTexture;
+ bool m_shouldUpdateTexture, m_shouldUpdateOrientation;
+ Orientation m_orientation;
std::vector<float> m_cmap;
};
diff --git a/main.cpp b/main.cpp
index 407753c..235f036 100644
--- a/main.cpp
+++ b/main.cpp
@@ -151,7 +151,8 @@ int main(int argc, char **argv)
// Initialize pointers to visual components
m->cpPlot = engine.rootObjects()[0]->findChild<Scatterplot *>("cpPlot");
m->rpPlot = engine.rootObjects()[0]->findChild<Scatterplot *>("rpPlot");
- m->colormap = engine.rootObjects()[0]->findChild<Colormap *>("colormap");
+ m->cpColormap = engine.rootObjects()[0]->findChild<Colormap *>("cpColormap");
+ m->rpColormap = engine.rootObjects()[0]->findChild<Colormap *>("rpColormap");
m->splat = engine.rootObjects()[0]->findChild<VoronoiSplat *>("splat");
m->cpBarChart = engine.rootObjects()[0]->findChild<BarChart *>("cpBarChart");
m->rpBarChart = engine.rootObjects()[0]->findChild<BarChart *>("rpBarChart");
@@ -193,9 +194,6 @@ int main(int argc, char **argv)
QObject::connect(m->projectionHistory, &ProjectionHistory::currentMapChanged,
&mapScaleHandler, &MapScaleHandler::scaleToMap);
- QObject::connect(m->splat, &VoronoiSplat::colorScaleChanged,
- m->colormap, &Colormap::setColorScale);
-
// Linking between selections
SelectionHandler cpSelectionHandler(cpIndices.n_elem);
QObject::connect(m->cpPlot, &Scatterplot::selectionInteractivelyChanged,
@@ -276,12 +274,8 @@ int main(int argc, char **argv)
m->cpBarChart->setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
m->rpBarChart->setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
- m->setColormapColorScale(Main::ColorScaleRainbow);
- m->setCPPlotColorScale(Main::ColorScaleRainbow);
- m->setRPPlotColorScale(Main::ColorScaleRainbow);
- m->setSplatColorScale(Main::ColorScaleRainbow);
- m->setCPBarChartColorScale(Main::ColorScaleRainbow);
- m->setRPBarChartColorScale(Main::ColorScaleRainbow);
+ m->setCPColorScale(Main::ColorScaleRainbow);
+ m->setRPColorScale(Main::ColorScaleRainbow);
// This sets the initial CP configuration, triggering all the necessary
// signals to set up the helper objects and visual components
diff --git a/main.h b/main.h
index de3a7f4..b09b3b0 100644
--- a/main.h
+++ b/main.h
@@ -88,34 +88,27 @@ public:
ColorScale COLOR_SCALE_DIVERGENT;
ColorScale COLOR_SCALE_RAINBOW;
- Q_INVOKABLE void setCPPlotColorScale(ColorScaleType colorScaleType) {
- cpPlot->setColorScale(getColorScale(colorScaleType));
- }
-
- Q_INVOKABLE void setRPPlotColorScale(ColorScaleType colorScaleType) {
- rpPlot->setColorScale(getColorScale(colorScaleType));
- }
+ Q_INVOKABLE void setCPColorScale(ColorScaleType colorScaleType) {
+ ColorScale &scale = getColorScale(colorScaleType);
- Q_INVOKABLE void setColormapColorScale(ColorScaleType colorScaleType) {
- colormap->setColorScale(getColorScale(colorScaleType));
+ cpPlot->setColorScale(scale);
+ cpBarChart->setColorScale(scale);
+ cpColormap->setColorScale(scale);
}
- Q_INVOKABLE void setCPBarChartColorScale(ColorScaleType colorScaleType) {
- cpBarChart->setColorScale(getColorScale(colorScaleType));
- }
-
- Q_INVOKABLE void setRPBarChartColorScale(ColorScaleType colorScaleType) {
- rpBarChart->setColorScale(getColorScale(colorScaleType));
- }
+ Q_INVOKABLE void setRPColorScale(ColorScaleType colorScaleType) {
+ ColorScale &scale = getColorScale(colorScaleType);
- Q_INVOKABLE void setSplatColorScale(ColorScaleType colorScaleType) {
- splat->setColorScale(getColorScale(colorScaleType));
+ rpPlot->setColorScale(scale);
+ splat->setColorScale(scale);
+ rpBarChart->setColorScale(scale);
+ rpColormap->setColorScale(scale);
}
// Pointers to visual components whose values are set in the main() function
// after components are instantiated by the QtQuick engine
BarChart *cpBarChart, *rpBarChart;
- Colormap *colormap;
+ Colormap *cpColormap, *rpColormap;
Scatterplot *cpPlot, *rpPlot;
VoronoiSplat *splat;
@@ -184,6 +177,8 @@ private:
, COLOR_SCALE_RAINBOW{ContinuousColorScale::builtin(ContinuousColorScale::Rainbow)}
, cpBarChart(0)
, rpBarChart(0)
+ , cpColormap(0)
+ , rpColormap(0)
, cpPlot(0)
, rpPlot(0)
, splat(0)
diff --git a/main_view.qml b/main_view.qml
index fd4bd4a..66fdf44 100644
--- a/main_view.qml
+++ b/main_view.qml
@@ -97,26 +97,6 @@ ApplicationWindow {
anchors.fill: parent
}
- Colormap {
- id: colormap
- objectName: "colormap"
- x: parent.x + 5
- y: parent.y + 5
- z: 2
- width: 128
- height: 5
-
- Rectangle { // Adds a border around the colormap
- x: parent.x - 1
- y: parent.y - 1
- width: parent.width + 2
- height: parent.height + 2
- border.width: 1
- border.color: "#000000"
- color: "transparent"
- }
- }
-
TransitionControl {
id: plotTC
objectName: "plotTC"
@@ -135,79 +115,114 @@ ApplicationWindow {
}
}
- Rectangle {
+ RowLayout {
Layout.minimumHeight: 60
Layout.fillHeight: true
width: mainView.width
- color: "#ffffff"
- Item {
- id: bottomViewCP
- anchors.fill: parent
+ Colormap {
+ Layout.fillHeight: true
+ id: cpColormap
+ objectName: "cpColormap"
+ width: 5
+ orientation: Colormap.Vertical
+
+ Rectangle { // Adds a border around the colormap
+ x: parent.x - 1
+ y: parent.y - 1
+ width: parent.width + 2
+ height: parent.height + 2
+ border.width: 1
+ border.color: "#000000"
+ color: "transparent"
+ }
+ }
- BarChart {
- id: cpBarChart
- objectName: "cpBarChart"
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ color: "#ffffff"
+
+ Item {
+ id: bottomViewCP
anchors.fill: parent
- Label {
+ BarChart {
+ id: cpBarChart
+ objectName: "cpBarChart"
anchors.fill: parent
- anchors.margins: 5
- horizontalAlignment: Text.AlignRight
- text: "Control points"
+
+ Label {
+ anchors.fill: parent
+ anchors.margins: 5
+ horizontalAlignment: Text.AlignRight
+ text: "Control points"
+ }
}
}
- //HistoryGraph {
- // id: history
- // objectName: "history"
- // anchors.fill: parent
- //}
- }
-
- Rectangle {
- anchors.fill: parent
- border.width: 1
- border.color: "#cccccc"
- color: "transparent"
+ Rectangle {
+ anchors.fill: parent
+ border.width: 1
+ border.color: "#cccccc"
+ color: "transparent"
+ }
}
}
- Rectangle {
+ RowLayout {
Layout.minimumHeight: 60
Layout.fillHeight: true
width: mainView.width
- color: "#ffffff"
- Item {
- id: bottomViewRP
- anchors.fill: parent
+ Colormap {
+ Layout.fillHeight: true
+ id: rpColormap
+ objectName: "rpColormap"
+ width: 5
+ orientation: Colormap.Vertical
+
+ Rectangle { // Adds a border around the colormap
+ x: parent.x - 1
+ y: parent.y - 1
+ width: parent.width + 2
+ height: parent.height + 2
+ border.width: 1
+ border.color: "#000000"
+ color: "transparent"
+ }
+ }
+
+ Rectangle {
+ Layout.minimumHeight: 60
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ color: "#ffffff"
- BarChart {
- id: rpBarChart
- objectName: "rpBarChart"
+ Item {
+ id: bottomViewRP
anchors.fill: parent
- Label {
+ BarChart {
+ id: rpBarChart
+ objectName: "rpBarChart"
anchors.fill: parent
- anchors.margins: 5
- horizontalAlignment: Text.AlignRight
- text: "Regular points"
+
+ Label {
+ anchors.fill: parent
+ anchors.margins: 5
+ horizontalAlignment: Text.AlignRight
+ text: "Regular points"
+ }
}
}
- //HistoryGraph {
- // id: history
- // objectName: "history"
- // anchors.fill: parent
- //}
- }
-
- Rectangle {
- anchors.fill: parent
- border.width: 1
- border.color: "#cccccc"
- color: "transparent"
+ Rectangle {
+ anchors.fill: parent
+ border.width: 1
+ border.color: "#cccccc"
+ color: "transparent"
+ }
}
}
}
@@ -232,11 +247,8 @@ ApplicationWindow {
}
}
- GridLayout {
- columns: 2
-
+ ColumnLayout {
GroupBox {
- Layout.columnSpan: 2
flat: true
title: "Colors"
@@ -253,34 +265,41 @@ ApplicationWindow {
ComboBox {
id: cpPlotColormapCombo
model: colormapModel
- onActivated: {
- Main.setCPPlotColorScale(model.get(index).value);
- Main.setCPBarChartColorScale(model.get(index).value);
- }
+ onActivated:
+ Main.setCPColorScale(model.get(index).value);
}
}
}
- Label { text: "Glyph size:" }
- SpinBox {
- id: cpGlyphSizeSpinBox
- maximumValue: 100
- minimumValue: 6
- decimals: 1
- stepSize: 1
- value: cpPlot.glyphSize
- onValueChanged: cpPlot.glyphSize = this.value
- }
+ GroupBox {
+ flat: true
+ title: "Glyphs"
- Label { text: "Opacity:" }
- Slider {
- id: cpPlotOpacitySlider
- tickmarksEnabled: true
- stepSize: 0.1
- maximumValue: 1
- minimumValue: 0
- value: cpPlot.opacity
- onValueChanged: cpPlot.opacity = this.value
+ GridLayout {
+ columns: 2
+
+ Label { text: "Size:" }
+ SpinBox {
+ id: cpGlyphSizeSpinBox
+ maximumValue: 100
+ minimumValue: 6
+ decimals: 1
+ stepSize: 1
+ value: cpPlot.glyphSize
+ onValueChanged: cpPlot.glyphSize = this.value
+ }
+
+ Label { text: "Opacity:" }
+ Slider {
+ id: cpPlotOpacitySlider
+ tickmarksEnabled: true
+ stepSize: 0.1
+ maximumValue: 1
+ minimumValue: 0
+ value: cpPlot.opacity
+ onValueChanged: cpPlot.opacity = this.value
+ }
+ }
}
}
}
@@ -295,11 +314,8 @@ ApplicationWindow {
splat.visible = this.checked;
}
- GridLayout {
- columns: 2
-
+ ColumnLayout {
GroupBox {
- Layout.columnSpan: 2
flat: true
title: "Colors"
@@ -316,17 +332,13 @@ ApplicationWindow {
ComboBox {
id: rpPlotColormapCombo
model: colormapModel
- onActivated: {
- Main.setRPPlotColorScale(model.get(index).value);
- Main.setSplatColorScale(model.get(index).value);
- Main.setRPBarChartColorScale(model.get(index).value);
- }
+ onActivated:
+ Main.setRPColorScale(model.get(index).value);
}
}
}
GroupBox {
- Layout.columnSpan: 2
flat: true
title: "Splat"
@@ -368,26 +380,35 @@ ApplicationWindow {
}
}
- Label { text: "Glyph size:" }
- SpinBox {
- id: rpGlyphSizeSpinBox
- maximumValue: 100
- minimumValue: 2
- decimals: 1
- stepSize: 1
- value: rpPlot.glyphSize
- onValueChanged: rpPlot.glyphSize = this.value
- }
+ GroupBox {
+ flat: true
+ title: "Glyphs"
+
+ GridLayout {
+ columns: 2
+
+ Label { text: "Size:" }
+ SpinBox {
+ id: rpGlyphSizeSpinBox
+ maximumValue: 100
+ minimumValue: 2
+ decimals: 1
+ stepSize: 1
+ value: rpPlot.glyphSize
+ onValueChanged: rpPlot.glyphSize = this.value
+ }
- Label { text: "Opacity:" }
- Slider {
- id: rpPlotOpacitySlider
- tickmarksEnabled: true
- stepSize: 0.1
- maximumValue: 1
- minimumValue: 0
- value: rpPlot.opacity
- onValueChanged: rpPlot.opacity = this.value
+ Label { text: "Opacity:" }
+ Slider {
+ id: rpPlotOpacitySlider
+ tickmarksEnabled: true
+ stepSize: 0.1
+ maximumValue: 1
+ minimumValue: 0
+ value: rpPlot.opacity
+ onValueChanged: rpPlot.opacity = this.value
+ }
+ }
}
}
}