diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2021-01-03 18:57:43 +0100 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2021-01-03 13:56:05 -0800 |
commit | bea289e3141a982cc80623f509619e56e189b6c1 (patch) | |
tree | 9334828d1fbcea63c365f3e3ddccab88060dc9fe /stats | |
parent | 9beec46e22cbe53b011c10f204d56b3750a87edb (diff) | |
download | subsurface-bea289e3141a982cc80623f509619e56e189b6c1.tar.gz |
statistics: clip regression line
A steep regression line would shoot out of the chart. Therefore,
clip to the y = minY and y = maxY lines.
QtGraphicsScene has its own clipping routines, but they are
very general, so let's do this trivial case by hand.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'stats')
-rw-r--r-- | stats/statsview.cpp | 22 | ||||
-rw-r--r-- | stats/statsview.h | 2 |
2 files changed, 21 insertions, 3 deletions
diff --git a/stats/statsview.cpp b/stats/statsview.cpp index 6a12ca24d..490e37385 100644 --- a/stats/statsview.cpp +++ b/stats/statsview.cpp @@ -670,8 +670,25 @@ void StatsView::LineMarker::updatePosition() chart->mapToPosition(to, series))); } -void StatsView::addLinearRegression(double a, double b, double minX, double maxX, QtCharts::QAbstractSeries *series) +void StatsView::addLinearRegression(double a, double b, double minX, double maxX, double minY, double maxY, QtCharts::QAbstractSeries *series) { + // Sanity check: line above or below chart + double y1 = a * minX + b; + double y2 = a * maxX + b; + if ((y1 <= minY && y2 <= minY) || (y1 >= maxY && y2 >= maxY)) + return; + + // If not fully inside drawing region, do clipping. With the check above this guarantees that a != 0, + // but owing to floating point imprecision, let's test again. + if ((y1 < minY || y1 > maxY || y2 < minY || y2 > maxY) && fabs(a) > 0.0001) { + // Intersections with y = minY and y = maxY lines + double intersect_x1 = minY / a - b; + double intersect_x2 = maxY / a - b; + if (intersect_x1 < intersect_x2) + std::swap(intersect_x1, intersect_x2); + minX = std::max(minX, intersect_x1); + maxX = std::min(maxX, intersect_x2); + } lineMarkers.emplace_back(QPointF(minX, a * minX + b), QPointF(maxX, a * maxX + b), QPen(Qt::red), series); } @@ -981,6 +998,7 @@ void StatsView::plotScatter(const std::vector<dive *> &dives, const StatsVariabl auto [a, b] = linear_regression(points); if (!std::isnan(a)) { auto [minx, maxx] = axisX->minMax(); - addLinearRegression(a, b, minx, maxx, series); + auto [miny, maxy] = axisY->minMax(); + addLinearRegression(a, b, minx, maxx, miny, maxy, series); } } diff --git a/stats/statsview.h b/stats/statsview.h index c65a4232a..1ef88b96c 100644 --- a/stats/statsview.h +++ b/stats/statsview.h @@ -110,7 +110,7 @@ private: LineMarker(QPointF from, QPointF to, QPen pen, QtCharts::QAbstractSeries *series); }; - void addLinearRegression(double a, double b, double minX, double maxX, QtCharts::QAbstractSeries *series); + void addLinearRegression(double a, double b, double minX, double maxX, double minY, double maxY, QtCharts::QAbstractSeries *series); void addHistogramMarker(double pos, double low, double high, const QPen &pen, bool isHorizontal, QtCharts::QAbstractSeries *series); StatsState state; |