mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[apps/regression] More intuitive curve/dot vertical navigation
This commit is contained in:
committed by
EmilieNumworks
parent
96c6143c6e
commit
460c21801f
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user