From 460c21801f91f29c0878d0e0322b4e435f852ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 12 Dec 2018 10:44:37 +0100 Subject: [PATCH] [apps/regression] More intuitive curve/dot vertical navigation --- apps/regression/graph_controller.cpp | 5 +-- apps/regression/store.cpp | 62 +++++++++------------------- 2 files changed, 22 insertions(+), 45 deletions(-) diff --git a/apps/regression/graph_controller.cpp b/apps/regression/graph_controller.cpp index 65df9f548..056fef230 100644 --- a/apps/regression/graph_controller.cpp +++ b/apps/regression/graph_controller.cpp @@ -291,8 +291,7 @@ bool GraphController::moveCursorVertically(int direction) { // Find the closest dot int closestDotSeries = -1; - double selectedDotY = *m_selectedDotIndex == -1 ? (direction > 0 ? -DBL_MAX : DBL_MAX) : y; - int dotSelected = m_store->closestVerticalDot(direction, x, selectedDotY, *m_selectedSeriesIndex, *m_selectedDotIndex, &closestDotSeries, context); + int dotSelected = m_store->closestVerticalDot(direction, x, y, *m_selectedSeriesIndex, *m_selectedDotIndex, &closestDotSeries, context); // Choose between selecting the regression or the dot bool validRegression = closestRegressionSeries > -1; @@ -316,7 +315,7 @@ bool GraphController::moveCursorVertically(int direction) { double dotDistanceY = (dotSelected == m_store->numberOfPairsOfSeries(closestDotSeries)) ? std::fabs(m_store->meanOfColumn(closestDotSeries, 1) - y) : std::fabs(m_store->get(closestDotSeries, 1, dotSelected) - y); - if (regressionDistanceY <= dotDistanceY) { + if (regressionDistanceY < dotDistanceY) { validDot = false; } else { validRegression = false; diff --git a/apps/regression/store.cpp b/apps/regression/store.cpp index 072eca522..affa87737 100644 --- a/apps/regression/store.cpp +++ b/apps/regression/store.cpp @@ -49,48 +49,26 @@ int Store::closestVerticalDot(int direction, double x, double y, int currentSeri double nextX = INFINITY; double nextY = INFINITY; int selectedDot = -1; - /* The conditions to test on all dots are in this order: - * - if the currentDot is valid, the next series should not be the current series - * - the next dot should not be the current dot - * - the next dot should be within the window abscissa bounds - * - the next dot is the closest one in abscissa to x - * - the next dot is above the regression curve if direction == 1 and below - * otherwise - * - the next dot is above/under y - * - if the current dot is valid, do not select a dot of the same series */ - for (int series = 0; series < k_numberOfSeries; series ++) { - if (!seriesIsEmpty(series) && (currentDot < 0 || currentSeries != series)) { - for (int index = 0; index < numberOfPairsOfSeries(series); index++) { - if ((currentSeries != series) || (index != currentDot)) { - double currentDataX = m_data[series][0][index]; - double currentDataY = m_data[series][1][index]; - if ((m_xMin <= currentDataX && currentDataX <= m_xMax) && - (std::fabs(currentDataX - x) <= std::fabs(nextX - x)) && - ((currentDataY - yValueForXValue(currentSeries, currentDataX, globalContext) >= 0) == (direction > 0)) && - ((currentDataY > y) == (direction > 0))) { - // Handle edge case: if 2 dots have the same abscissa but different ordinates - if (nextX != currentDataX || ((nextY - currentDataY >= 0) == (direction > 0))) { - nextX = currentDataX; - nextY = currentDataY; - selectedDot = index; - *nextSeries = series; - } - } - } - } - // Compare with the mean dot - if ((currentSeries != series) || (numberOfPairsOfSeries(series) != currentDot)) { - double meanX = meanOfColumn(series, 0); - double meanY = meanOfColumn(series, 1); - if (m_xMin <= meanX && meanX <= m_xMax && - (std::fabs(meanX - x) <= std::fabs(nextX - x)) && - ((meanY - yValueForXValue(currentSeries, meanX, globalContext) >= 0) == (direction > 0)) && - ((meanY > y) == (direction > 0))) { - if (nextX != meanX || ((nextY - meanY >= 0) == (direction > 0))) { - selectedDot = numberOfPairsOfSeries(series); - *nextSeries = series; - } - } + for (int series = 0; series < k_numberOfSeries; series++) { + if (seriesIsEmpty(series) || (currentDot >= 0 && currentSeries == series)) { + /* If the currentDot is valid, the next series should not be the current + * series */ + continue; + } + int numberOfPoints = numberOfPairsOfSeries(series); + for (int i = 0; i <= numberOfPoints; i++) { + double currentX = i < numberOfPoints ? m_data[series][0][i] : meanOfColumn(series, 0); + double currentY = i < numberOfPoints ? m_data[series][1][i] : meanOfColumn(series, 1); + if (m_xMin <= currentX && currentX <= m_xMax // The next dot is within the window abscissa bounds + && (std::fabs(currentX - x) <= std::fabs(nextX - x)) // The next dot is the closest to x in abscissa + && ((currentY >= y) == (direction > 0)) // The next dot is above/under y + && (nextX != currentX // Edge case: if 2 dots have the same abscissa but different ordinates + || ((currentY <= nextY) == (direction > 0)))) + { + nextX = currentX; + nextY = currentY; + selectedDot = i; + *nextSeries = series; } } }