[apps/regression] More intuitive curve/dot vertical navigation

This commit is contained in:
Léa Saviot
2018-12-12 10:44:37 +01:00
committed by EmilieNumworks
parent 96c6143c6e
commit 460c21801f
2 changed files with 22 additions and 45 deletions

View File

@@ -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;
}
}
}