diff options
author | Andre de la Rocha <andre.rocha@qt.io> | 2018-06-05 19:20:58 +0200 |
---|---|---|
committer | Andre de la Rocha <andre.rocha@qt.io> | 2018-06-06 08:55:00 +0000 |
commit | 94000dd2b17e64719df8614f25b8df4e0061a133 (patch) | |
tree | a80a41363e39f089c8463ab42b036d16afc1a1fb | |
parent | 247cd74b4cbe2769c189b29bcbbd68084de3fc18 (diff) |
Fix data normalization in GLXYSeriesDataManager
GLXYSeriesDataManager::setPoints() has an optimized path when it detects
a regular XY chart, which skips calculateGeometryPoints() and sets up
a shader-based transform instead of normalizing vertex data. However,
for some series data containing values far away from the origin, which are
represented with less absolute precision as floating-point values, by the
time the transform is used, precision was already lost in the conversion
from double to float, destroying the chart. This change performs proper
normalization inside the optimized path, while keeping the same level of
performance as before.
Task-number: QTBUG-59674
Change-Id: Idc57481815a409c19ca364e1721153483cbc2993
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r-- | src/charts/xychart/glxyseriesdata.cpp | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/src/charts/xychart/glxyseriesdata.cpp b/src/charts/xychart/glxyseriesdata.cpp index 54c533b2..8ec919b7 100644 --- a/src/charts/xychart/glxyseriesdata.cpp +++ b/src/charts/xychart/glxyseriesdata.cpp @@ -117,20 +117,26 @@ void GLXYSeriesDataManager::setPoints(QXYSeries *series, const AbstractDomain *d data->min = QVector2D(0, 0); data->delta = QVector2D(domain->size().width() / 2.0f, domain->size().height() / 2.0f); } else { - // Regular value axes, so we can do the math easily on shaders. + // Regular value axes, so we can optimize it a bit. if (reverseX) matrix.scale(-1.0, 1.0); if (reverseY) matrix.scale(1.0, -1.0); - QVector<QPointF> seriesPoints = series->pointsVector(); - for (int i = 0; i < count; i++) { - const QPointF &point = seriesPoints.at(i); - array[index++] = float(point.x()); - array[index++] = float(point.y()); + + const qreal mx = domain->minX(); + const qreal my = domain->minY(); + const qreal xd = domain->maxX() - mx; + const qreal yd = domain->maxY() - my; + + if (!qFuzzyIsNull(xd) && !qFuzzyIsNull(yd)) { + const QVector<QPointF> seriesPoints = series->pointsVector(); + for (const QPointF &point : seriesPoints) { + array[index++] = float((point.x() - mx) / xd); + array[index++] = float((point.y() - my) / yd); + } } - data->min = QVector2D(domain->minX(), domain->minY()); - data->delta = QVector2D((domain->maxX() - domain->minX()) / 2.0f, - (domain->maxY() - domain->minY()) / 2.0f); + data->min = QVector2D(0.0f, 0.0f); + data->delta = QVector2D(0.5f, 0.5f); } data->matrix = matrix; data->dirty = true; |