diff --git a/apps/regression/data.cpp b/apps/regression/data.cpp index 976991b2e..447993b47 100644 --- a/apps/regression/data.cpp +++ b/apps/regression/data.cpp @@ -10,6 +10,7 @@ Data::Data() : ::Data(), m_xCursorPosition(NAN), m_yCursorPosition(NAN), + m_dotsSelected(false), m_xMin(0.0f), m_xMax(10.0f), m_yMin(0.0f), @@ -79,6 +80,58 @@ float Data::yCursorPosition() { return m_yCursorPosition; } +bool Data::cursorSelectUp() { + float yRegressionCurve = yValueForXValue(m_xCursorPosition); + if (m_dotsSelected && m_yCursorPosition < yRegressionCurve) { + m_dotsSelected = false; + m_yCursorPosition = yRegressionCurve; + return true; + } + if (!m_dotsSelected) { + if (selectClosestDotRelativelyToCurve(1)) { + m_dotsSelected = true; + return true; + } + } + return false; +} + +bool Data::cursorSelectBottom() { + float yRegressionCurve = yValueForXValue(m_xCursorPosition); + if (m_dotsSelected && m_yCursorPosition > yRegressionCurve) { + m_dotsSelected = false; + m_yCursorPosition = yRegressionCurve; + return true; + } + if (!m_dotsSelected) { + if (selectClosestDotRelativelyToCurve(-1)) { + m_dotsSelected = true; + return true; + } + } + return false; +} + +bool Data::cursorSelectLeft() { + if (m_dotsSelected) { + return selectNextDot(-1); + } else { + m_xCursorPosition -= m_xGridUnit; + m_yCursorPosition = yValueForXValue(m_xCursorPosition); + return true; + } +} + +bool Data::cursorSelectRight() { + if (m_dotsSelected) { + return selectNextDot(1); + } else { + m_xCursorPosition += m_xGridUnit; + m_yCursorPosition = yValueForXValue(m_xCursorPosition); + return true; + } +} + /* CurveViewWindow */ float Data::xMin() { @@ -118,7 +171,7 @@ float Data::xSum() { float Data::ySum() { float result = 0; for (int k = 0; k < m_numberOfPairs; k++) { - result += m_xValues[k]; + result += m_yValues[k]; } return result; } @@ -165,6 +218,14 @@ float Data::yVariance() { return ySquaredValueSum()/m_numberOfPairs - mean*mean; } +float Data::xStandardDeviation() { + return sqrtf(xVariance()); +} + +float Data::yStandardDeviation() { + return sqrtf(yVariance()); +} + float Data::covariance() { return xyProductSum()/m_numberOfPairs - xMean()*yMean(); } @@ -181,6 +242,15 @@ float Data::yValueForXValue(float x) { return slope()*x+yIntercept(); } +float Data::correlationCoefficient() { + return covariance()/(xStandardDeviation()*yStandardDeviation()); +} + +float Data::squaredCorrelationCoefficient() { + float cov = covariance(); + return cov*cov/(xVariance()*yVariance()); +} + float Data::maxXValue() { float max = -FLT_MAX; for (int k = 0; k < m_numberOfPairs; k++) { @@ -224,6 +294,7 @@ float Data::minYValue() { void Data::initCursorPosition() { m_xCursorPosition = (m_xMin+m_xMax)/2.0f; m_yCursorPosition = yValueForXValue(m_xCursorPosition); + m_dotsSelected = false; } void Data::initWindowParameters() { @@ -235,4 +306,40 @@ void Data::initWindowParameters() { m_yGridUnit = computeGridUnit(Axis::Y, m_yMin, m_yMax); } +bool Data::selectClosestDotRelativelyToCurve(int direction) { + float nextX = INFINITY; + float nextY = INFINITY; + for (int index = 0; index < m_numberOfPairs; index++) { + if (fabsf(m_xValues[index] - m_xCursorPosition) < fabsf(nextX - m_xCursorPosition) && + ((direction > 0 && m_yValues[index] >= yValueForXValue(m_xValues[index])) || (direction < 0 && m_yValues[index] <= yValueForXValue(m_xValues[index])))) { + nextX = m_xValues[index]; + nextY = m_yValues[index]; + } + } + if (!isinf(nextX) && !isinf(nextY)) { + m_xCursorPosition = nextX; + m_yCursorPosition = nextY; + return true; + } + return false; +} + +bool Data::selectNextDot(int direction) { + float nextX = INFINITY; + float nextY = INFINITY; + for (int index = 0; index < m_numberOfPairs; index++) { + if (fabsf(m_xValues[index] - m_xCursorPosition) < fabsf(nextX - m_xCursorPosition) && + ((direction > 0 && m_xValues[index] > m_xCursorPosition) || (direction < 0 && m_xValues[index] < m_xCursorPosition))) { + nextX = m_xValues[index]; + nextY = m_yValues[index]; + } + } + if (!isinf(nextX) && !isinf(nextY)) { + m_xCursorPosition = nextX; + m_yCursorPosition = nextY; + return true; + } + return false; +} + } diff --git a/apps/regression/data.h b/apps/regression/data.h index c8faf1404..d16116eb8 100644 --- a/apps/regression/data.h +++ b/apps/regression/data.h @@ -22,6 +22,10 @@ public: // Cursor float xCursorPosition(); float yCursorPosition(); + bool cursorSelectUp(); + bool cursorSelectBottom(); + bool cursorSelectLeft(); + bool cursorSelectRight(); //CurveViewWindow float xMin() override; @@ -41,10 +45,14 @@ public: float yMean(); float xVariance(); float yVariance(); + float xStandardDeviation(); + float yStandardDeviation(); float covariance(); float slope(); float yIntercept(); float yValueForXValue(float x); + float correlationCoefficient(); + float squaredCorrelationCoefficient(); constexpr static int k_maxNumberOfPairs = 500; private: @@ -55,12 +63,17 @@ private: void initWindowParameters(); void initCursorPosition(); - // Raw numeric data + + bool selectClosestDotRelativelyToCurve(int direction); + bool selectNextDot(int direction); + +// Raw numeric data int m_xValues[k_maxNumberOfPairs]; float m_yValues[k_maxNumberOfPairs]; // Cursor float m_xCursorPosition; float m_yCursorPosition; + bool m_dotsSelected; // Window bounds of the data float m_xMin; float m_xMax;