summaryrefslogtreecommitdiffstats
path: root/stats
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2021-01-03 18:57:43 +0100
committerGravatar Dirk Hohndel <dirk@hohndel.org>2021-01-03 13:56:05 -0800
commitbea289e3141a982cc80623f509619e56e189b6c1 (patch)
tree9334828d1fbcea63c365f3e3ddccab88060dc9fe /stats
parent9beec46e22cbe53b011c10f204d56b3750a87edb (diff)
downloadsubsurface-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.cpp22
-rw-r--r--stats/statsview.h2
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;