From 95a77b04a6855b26d340aaca5e3030a7d1a7cb3c Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Fri, 12 Feb 2016 18:01:27 -0200 Subject: Many bugfixes related to ProjectionObserver. * Correct handling of relative metrics in UI * undo(), reset() methods added * Main class responsible for undoing and resetting both history and the observer (MUST BE AT THE SAME TIME! -- this might indicate a design issue to be addressed in the future) --- main.cpp | 8 ++------ main.h | 25 ++++++++++++++++++----- main_view.qml | 24 ++++++++++++++++------ projectionobserver.cpp | 54 +++++++++++++++++++++++++++++++++++++------------- projectionobserver.h | 14 +++++++------ 5 files changed, 88 insertions(+), 37 deletions(-) diff --git a/main.cpp b/main.cpp index 6eed197..a5aaf68 100644 --- a/main.cpp +++ b/main.cpp @@ -247,14 +247,10 @@ int main(int argc, char **argv) m->rpBarChart, &BarChart::brushItem); // Recompute values whenever projection changes - ProjectionObserver projectionObserver(X, cpIndices, m->projectionHistory); + ProjectionObserver projectionObserver(X, cpIndices); m->projectionObserver = &projectionObserver; QObject::connect(m->projectionHistory, &ProjectionHistory::mapAdded, - m->projectionObserver, &ProjectionObserver::setMap); - QObject::connect(m->projectionHistory, &ProjectionHistory::undoPerformed, - m->projectionObserver, &ProjectionObserver::setMap); - QObject::connect(m->projectionHistory, &ProjectionHistory::resetPerformed, - m->projectionObserver, &ProjectionObserver::setMap); + m->projectionObserver, &ProjectionObserver::addMap); QObject::connect(m->projectionObserver, &ProjectionObserver::cpValuesChanged, m->cpPlot, &Scatterplot::setColorData); QObject::connect(m->projectionObserver, &ProjectionObserver::rpValuesChanged, diff --git a/main.h b/main.h index c4699c4..e1964e7 100644 --- a/main.h +++ b/main.h @@ -83,7 +83,16 @@ public: }; Q_INVOKABLE bool setObserverType(ObserverType observerType) { - return projectionObserver->setType((int) observerType); + switch (observerType) { + case ObserverCurrent: + return projectionObserver->setType(ProjectionObserver::ObserverCurrent); + case ObserverDiffPrevious: + return projectionObserver->setType(ProjectionObserver::ObserverDiffPrevious); + case ObserverDiffFirst: + return projectionObserver->setType(ProjectionObserver::ObserverDiffFirst); + } + + return false; } enum ColorScaleType { @@ -130,12 +139,18 @@ public: Scatterplot *cpPlot, *rpPlot; VoronoiSplat *splat; - ProjectionObserver *projectionObserver; - // Shared object that controls manipulation history ProjectionHistory *projectionHistory; - Q_INVOKABLE void undoManipulation() { projectionHistory->undo(); } - Q_INVOKABLE void resetManipulation() { projectionHistory->reset(); } + ProjectionObserver *projectionObserver; + + Q_INVOKABLE void undoManipulation() { + projectionHistory->undo(); + projectionObserver->undo(); + } + Q_INVOKABLE void resetManipulation() { + projectionHistory->reset(); + projectionObserver->reset(); + } public slots: void setCPIndices(const arma::uvec &indices) { diff --git a/main_view.qml b/main_view.qml index 65e1095..fd4bd4a 100644 --- a/main_view.qml +++ b/main_view.qml @@ -217,6 +217,7 @@ ApplicationWindow { Layout.alignment: Qt.AlignTop | Qt.AlignLeft GroupBox { + Layout.fillWidth: true title: "Control points" checkable: true __checkbox.onClicked: { @@ -285,6 +286,7 @@ ApplicationWindow { } GroupBox { + Layout.fillWidth: true title: "Regular points" checked: true checkable: true @@ -392,7 +394,9 @@ ApplicationWindow { GroupBox { Layout.fillWidth: true + id: metricsGroupBox title: "Projection metrics" + property RadioButton current: currentMetricRadioButton Column { ExclusiveGroup { id: wrtMetricsGroup } @@ -402,7 +406,13 @@ ApplicationWindow { text: "Current" exclusiveGroup: wrtMetricsGroup checked: true - onClicked: Main.setObserverType(Main.ObserverCurrent) + onClicked: { + if (!Main.setObserverType(Main.ObserverCurrent)) { + metricsGroupBox.current.checked = true; + } else { + metricsGroupBox.current = this; + } + } } RadioButton { id: diffPreviousMetricRadioButton @@ -410,19 +420,21 @@ ApplicationWindow { exclusiveGroup: wrtMetricsGroup onClicked: { if (!Main.setObserverType(Main.ObserverDiffPrevious)) { - this.checked = false; - currentMetricRadioButton.checked = true; + metricsGroupBox.current.checked = true; + } else { + metricsGroupBox.current = this; } } } RadioButton { - id: diffOriginalMetricRadioButton + id: diffFirstMetricRadioButton text: "Diff. to first" exclusiveGroup: wrtMetricsGroup onClicked: { if (!Main.setObserverType(Main.ObserverDiffFirst)) { - this.checked = false; - currentMetricRadioButton.checked = true; + metricsGroupBox.current.checked = true; + } else { + metricsGroupBox.current = this; } } } diff --git a/projectionobserver.cpp b/projectionobserver.cpp index a6b280f..94f266a 100644 --- a/projectionobserver.cpp +++ b/projectionobserver.cpp @@ -7,7 +7,7 @@ #include "numericrange.h" ProjectionObserver::ProjectionObserver(const arma::mat &X, - const arma::uvec &cpIndices, ProjectionHistory *history) + const arma::uvec &cpIndices) : m_type(ObserverCurrent) , m_X(X) , m_cpIndices(cpIndices) @@ -17,10 +17,9 @@ ProjectionObserver::ProjectionObserver(const arma::mat &X, , m_values(X.n_rows) , m_prevValues(X.n_rows) , m_firstValues(X.n_rows) - , m_history(history) + , m_hasFirst(false) + , m_hasPrev(false) { - Q_ASSERT(history); - m_distX = mp::dist(m_X); NumericRange allIndices(0, m_X.n_rows); @@ -50,10 +49,36 @@ void ProjectionObserver::computeAlphas() } } -void ProjectionObserver::setMap(const arma::mat &Y) +void ProjectionObserver::undo() +{ + if (m_hasPrev) { + m_hasPrev = false; + m_distY = m_prevDistY; + m_values = m_prevValues; + + if (m_cpSelectionEmpty && m_rpSelectionEmpty) { + emitValuesChanged(); + } + } +} + +void ProjectionObserver::reset() +{ + if (m_hasFirst) { + m_hasPrev = false; + m_distY = m_firstDistY; + m_values = m_firstValues; + + if (m_cpSelectionEmpty && m_rpSelectionEmpty) { + emitValuesChanged(); + } + } +} + +void ProjectionObserver::addMap(const arma::mat &Y) { - // update data of previous map - if (m_history->hasFirst()) { + if (m_hasFirst) { + m_hasPrev = true; m_prevDistY = m_distY; m_prevValues = m_values; } @@ -62,8 +87,8 @@ void ProjectionObserver::setMap(const arma::mat &Y) mp::aggregatedError(m_distX, m_distY, m_values); - // update data of first map - if (!m_history->hasFirst()) { + if (!m_hasFirst) { + m_hasFirst = true; m_firstDistY = m_distY; m_firstValues = m_values; } @@ -73,13 +98,14 @@ void ProjectionObserver::setMap(const arma::mat &Y) } } -bool ProjectionObserver::setType(int type) +bool ProjectionObserver::setType(ObserverType type) { if (m_type == type) { return true; } - if (type == ObserverDiffPrevious && !m_history->hasPrev()) { + if ((type == ObserverDiffPrevious && !m_hasPrev) + || (type == ObserverDiffFirst && !m_hasFirst)) { return false; } @@ -151,7 +177,7 @@ bool ProjectionObserver::emitValuesChanged() const emit valuesChanged(m_values); return true; case ObserverDiffPrevious: - if (m_history->hasPrev()) { + if (m_hasPrev) { arma::vec diff = m_values - m_prevValues; emit rpValuesChanged(diff(m_rpIndices)); emit valuesChanged(diff); @@ -159,7 +185,7 @@ bool ProjectionObserver::emitValuesChanged() const } return false; case ObserverDiffFirst: - if (m_history->hasFirst()) { + if (m_hasFirst) { arma::vec diff = m_values - m_firstValues; emit rpValuesChanged(diff(m_rpIndices)); emit valuesChanged(diff); @@ -173,7 +199,7 @@ bool ProjectionObserver::emitValuesChanged() const void ProjectionObserver::setRewind(double t) { - if (!m_history->hasPrev() || !m_cpSelectionEmpty || !m_rpSelectionEmpty) { + if (!m_hasPrev || !m_cpSelectionEmpty || !m_rpSelectionEmpty) { return; } diff --git a/projectionobserver.h b/projectionobserver.h index 7e9239d..c021482 100644 --- a/projectionobserver.h +++ b/projectionobserver.h @@ -18,8 +18,10 @@ public: }; ProjectionObserver(const arma::mat &X, - const arma::uvec &cpIndices, - ProjectionHistory *history); + const arma::uvec &cpIndices); + + void undo(); + void reset(); signals: void valuesChanged(const arma::vec &values) const; @@ -30,8 +32,8 @@ signals: void rpValuesRewound(const arma::vec &values) const; public slots: - void setMap(const arma::mat &Y); - bool setType(int type); + void addMap(const arma::mat &Y); + bool setType(ObserverType type); void setCPSelection(const std::vector &cpSelection); void setRPSelection(const std::vector &rpSelection); void setRewind(double t); @@ -39,7 +41,7 @@ public slots: private: bool emitValuesChanged() const; - int m_type; + ObserverType m_type; arma::mat m_X; arma::mat m_distX, m_distY, m_firstDistY, m_prevDistY; arma::uvec m_cpIndices, m_rpIndices; @@ -53,7 +55,7 @@ private: // TODO: one per implemented measure arma::vec m_values, m_firstValues, m_prevValues; - ProjectionHistory *m_history; + bool m_hasFirst, m_hasPrev; }; #endif // PROJECTIONOBSERVER_H -- cgit v1.2.3