From c90ba8c1b158c745709b8598cadf1b2067995f65 Mon Sep 17 00:00:00 2001 From: Kevin Hogan Date: Wed, 14 Apr 2021 18:48:50 -0400 Subject: [PATCH] QCustomPlot: Fix adaptive sampling performance on scatterplots QCustomPlot's adaptive sampling decimates the data to be plotted based on the screen resolution. Specifically, if many data points fit within the same pixel on the X (key) axis, then QCustomPlot attempts to plot only the min value, the max value, and a few values in-between to maintain a good "density" on the Y (value) axis. The density QCustomPlot wants is about one datapoint for every 4 pixels covered by the value range of a single X (key) pixel. Unfortunately, this calculation is flawed if all values also fit within a single pixel on the Y (value) axis - so this change fixes that bug. (cherry picked from commit 92e652ebfaa65fc31747cf1036fa4ca6832d4527) --- ui/qt/widgets/qcustomplot.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/qt/widgets/qcustomplot.cpp b/ui/qt/widgets/qcustomplot.cpp index edee873332..db2d3c9fc3 100644 --- a/ui/qt/widgets/qcustomplot.cpp +++ b/ui/qt/widgets/qcustomplot.cpp @@ -21854,8 +21854,10 @@ void QCPGraph::getOptimizedScatterData(QVector *scatterData, QCPGr if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them { // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): - double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); - int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average + // [ However, make sure that the span is at least 1 pixel ] + double valuePixelSpan = qMax(1.0, qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue))); + double pointsToAdd = valuePixelSpan/4.0; // add approximately one data point for every 4 value pixels + int dataModulo = qMax(1, qRound(intervalDataCount/pointsToAdd)); QCPGraphDataContainer::const_iterator intervalIt = currentIntervalStart; int c = 0; while (intervalIt != it) @@ -21897,8 +21899,10 @@ void QCPGraph::getOptimizedScatterData(QVector *scatterData, QCPGr if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them { // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): + // [ However, make sure that the span is at least 1 pixel ] double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); - int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average + double pointsToAdd = valuePixelSpan/4.0; // add approximately one data point for every 4 value pixels + int dataModulo = qMax(1, qRound(intervalDataCount/pointsToAdd)); QCPGraphDataContainer::const_iterator intervalIt = currentIntervalStart; int intervalItIndex = int(intervalIt-mDataContainer->constBegin()); int c = 0;