From 87339612d27fab342a01663bf00c15f5e92b3e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomi=20Korpip=C3=A4=C3=A4?= Date: Mon, 14 Nov 2016 11:15:00 +0200 Subject: Ensure that the formatter is respected for zero and negative values This also ensures that INF and NaN numbers are also handled correctly Task-number: QTBUG-57075 Change-Id: I8db693cb28303bc13f936c818147fe31b7ee1199 Reviewed-by: Miikka Heikkinen --- src/datavisualization/axis/qabstract3daxis.h | 2 + src/datavisualization/axis/qabstract3daxis_p.h | 2 + src/datavisualization/data/qscatterdataproxy.cpp | 25 +++++++-- src/datavisualization/data/qscatterdataproxy_p.h | 7 ++- src/datavisualization/data/qsurfacedataproxy.cpp | 61 ++++++++++++++++++---- src/datavisualization/data/qsurfacedataproxy_p.h | 6 ++- .../engine/scatter3dcontroller.cpp | 2 +- .../engine/surface3dcontroller.cpp | 2 +- 8 files changed, 88 insertions(+), 19 deletions(-) (limited to 'src/datavisualization') diff --git a/src/datavisualization/axis/qabstract3daxis.h b/src/datavisualization/axis/qabstract3daxis.h index 63dd0340..ff587acf 100644 --- a/src/datavisualization/axis/qabstract3daxis.h +++ b/src/datavisualization/axis/qabstract3daxis.h @@ -124,6 +124,8 @@ private: friend class Abstract3DController; friend class Bars3DController; + friend class QScatterDataProxyPrivate; + friend class QSurfaceDataProxyPrivate; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/axis/qabstract3daxis_p.h b/src/datavisualization/axis/qabstract3daxis_p.h index deb53266..418fa449 100644 --- a/src/datavisualization/axis/qabstract3daxis_p.h +++ b/src/datavisualization/axis/qabstract3daxis_p.h @@ -84,6 +84,8 @@ protected: friend class QAbstract3DAxis; friend class QValue3DAxis; friend class QCategory3DAxis; + friend class QScatterDataProxyPrivate; + friend class QSurfaceDataProxyPrivate; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/data/qscatterdataproxy.cpp b/src/datavisualization/data/qscatterdataproxy.cpp index 167c074a..1fe5b3fc 100644 --- a/src/datavisualization/data/qscatterdataproxy.cpp +++ b/src/datavisualization/data/qscatterdataproxy.cpp @@ -29,6 +29,7 @@ #include "qscatterdataproxy_p.h" #include "qscatter3dseries_p.h" +#include "qabstract3daxis_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION @@ -366,7 +367,9 @@ void QScatterDataProxyPrivate::removeItems(int index, int removeCount) m_dataArray->remove(index, removeCount); } -void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) const +void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues, + QAbstract3DAxis *axisX, QAbstract3DAxis *axisY, + QAbstract3DAxis *axisZ) const { if (m_dataArray->isEmpty()) return; @@ -385,19 +388,25 @@ void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxV const QVector3D &pos = m_dataArray->at(i).position(); float value = pos.x(); - if (minX > value) + if (qIsNaN(value) || qIsInf(value)) + continue; + if (isValidValue(minX, value, axisX)) minX = value; if (maxX < value) maxX = value; value = pos.y(); - if (minY > value) + if (qIsNaN(value) || qIsInf(value)) + continue; + if (isValidValue(minY, value, axisY)) minY = value; if (maxY < value) maxY = value; value = pos.z(); - if (minZ > value) + if (qIsNaN(value) || qIsInf(value)) + continue; + if (isValidValue(minZ, value, axisZ)) minZ = value; if (maxZ < value) maxZ = value; @@ -413,6 +422,14 @@ void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxV maxValues.setZ(maxZ); } +bool QScatterDataProxyPrivate::isValidValue(float axisValue, float value, + QAbstract3DAxis *axis) const +{ + return (axisValue > value && (value > 0.0f + || (value == 0.0f && axis->d_ptr->allowZero()) + || (value < 0.0f && axis->d_ptr->allowNegatives()))); +} + void QScatterDataProxyPrivate::setSeries(QAbstract3DSeries *series) { QAbstractDataProxyPrivate::setSeries(series); diff --git a/src/datavisualization/data/qscatterdataproxy_p.h b/src/datavisualization/data/qscatterdataproxy_p.h index 49ab7362..157152b0 100644 --- a/src/datavisualization/data/qscatterdataproxy_p.h +++ b/src/datavisualization/data/qscatterdataproxy_p.h @@ -46,6 +46,8 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION +class QAbstract3DAxis; + class QScatterDataProxyPrivate : public QAbstractDataProxyPrivate { Q_OBJECT @@ -61,8 +63,9 @@ public: void insertItem(int index, const QScatterDataItem &item); void insertItems(int index, const QScatterDataArray &items); void removeItems(int index, int removeCount); - - void limitValues(QVector3D &minValues, QVector3D &maxValues) const; + void limitValues(QVector3D &minValues, QVector3D &maxValues, QAbstract3DAxis *axisX, + QAbstract3DAxis *axisY, QAbstract3DAxis *axisZ) const; + bool isValidValue(float axisValue, float value, QAbstract3DAxis *axis) const; virtual void setSeries(QAbstract3DSeries *series); private: diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp index c983ead7..fa7990b1 100644 --- a/src/datavisualization/data/qsurfacedataproxy.cpp +++ b/src/datavisualization/data/qsurfacedataproxy.cpp @@ -29,6 +29,7 @@ #include "qsurfacedataproxy_p.h" #include "qsurface3dseries_p.h" +#include "qabstract3daxis_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION @@ -504,7 +505,9 @@ QSurfaceDataProxy *QSurfaceDataProxyPrivate::qptr() return static_cast(q_ptr); } -void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) const +void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues, + QAbstract3DAxis *axisX, QAbstract3DAxis *axisY, + QAbstract3DAxis *axisZ) const { float min = 0.0f; float max = 0.0f; @@ -524,7 +527,9 @@ void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxV if (row) { for (int j = 0; j < columns; j++) { float itemValue = m_dataArray->at(i)->at(j).y(); - if (min > itemValue) + if (qIsNaN(itemValue) || qIsInf(itemValue)) + continue; + if (min > itemValue && isValidValue(itemValue, axisY)) min = itemValue; if (max < itemValue) max = itemValue; @@ -534,23 +539,59 @@ void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxV minValues.setY(min); maxValues.setY(max); + if (columns) { + // Have some defaults float xLow = m_dataArray->at(0)->at(0).x(); float xHigh = m_dataArray->at(0)->last().x(); float zLow = m_dataArray->at(0)->at(0).z(); float zHigh = m_dataArray->last()->at(0).z(); - minValues.setX(qMin(xLow, xHigh)); - minValues.setZ(qMin(zLow, zHigh)); - maxValues.setX(qMax(xLow, xHigh)); - maxValues.setZ(qMax(zLow, zHigh)); + for (int i = 0; i < columns; i++) { + float zItemValue = m_dataArray->at(0)->at(i).z(); + if (qIsNaN(zItemValue) || qIsInf(zItemValue)) + continue; + else if (isValidValue(zItemValue, axisZ)) + zLow = qMin(zLow,zItemValue); + } + for (int i = 0; i < columns; i++) { + float zItemValue = m_dataArray->last()->at(i).z(); + if (qIsNaN(zItemValue) || qIsInf(zItemValue)) + continue; + else if (isValidValue(zItemValue, axisZ)) + zHigh = qMax(zHigh, zItemValue); + } + for (int i = 0; i < rows; i++) { + float xItemValue = m_dataArray->at(i)->at(0).x(); + if (qIsNaN(xItemValue) || qIsInf(xItemValue)) + continue; + else if (isValidValue(xItemValue, axisX)) + xLow = qMin(xLow, xItemValue); + } + for (int i = 0; i < rows; i++) { + float xItemValue = m_dataArray->at(i)->last().x(); + if (qIsNaN(xItemValue) || qIsInf(xItemValue)) + continue; + else if (isValidValue(xItemValue, axisX)) + xHigh = qMax(xHigh, xItemValue); + } + minValues.setX(xLow); + minValues.setZ(zLow); + maxValues.setX(xHigh); + maxValues.setZ(zHigh); } else { - minValues.setX(0.0f); - minValues.setZ(0.0f); - maxValues.setX(0.0f); - maxValues.setZ(0.0f); + minValues.setX(axisX->d_ptr->allowZero() ? 0.0f : 1.0f); + minValues.setZ(axisZ->d_ptr->allowZero() ? 0.0f : 1.0f); + maxValues.setX(axisX->d_ptr->allowZero() ? 0.0f : 1.0f); + maxValues.setZ(axisZ->d_ptr->allowZero() ? 0.0f : 1.0f); } } +bool QSurfaceDataProxyPrivate::isValidValue(float value, QAbstract3DAxis *axis) const +{ + return (value > 0.0f || (value == 0.0f && axis->d_ptr->allowZero()) + || (value < 0.0f && axis->d_ptr->allowNegatives())); +} + void QSurfaceDataProxyPrivate::clearRow(int rowIndex) { if (m_dataArray->at(rowIndex)) { diff --git a/src/datavisualization/data/qsurfacedataproxy_p.h b/src/datavisualization/data/qsurfacedataproxy_p.h index 808e27df..80443aec 100644 --- a/src/datavisualization/data/qsurfacedataproxy_p.h +++ b/src/datavisualization/data/qsurfacedataproxy_p.h @@ -45,6 +45,8 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION +class QAbstract3DAxis; + class QSurfaceDataProxyPrivate : public QAbstractDataProxyPrivate { Q_OBJECT @@ -61,7 +63,9 @@ public: void insertRow(int rowIndex, QSurfaceDataRow *row); void insertRows(int rowIndex, const QSurfaceDataArray &rows); void removeRows(int rowIndex, int removeCount); - void limitValues(QVector3D &minValues, QVector3D &maxValues) const; + void limitValues(QVector3D &minValues, QVector3D &maxValues, QAbstract3DAxis *axisX, + QAbstract3DAxis *axisY, QAbstract3DAxis *axisZ) const; + bool isValidValue(float value, QAbstract3DAxis *axis) const; virtual void setSeries(QAbstract3DSeries *series); diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp index ee190196..46249c3c 100644 --- a/src/datavisualization/engine/scatter3dcontroller.cpp +++ b/src/datavisualization/engine/scatter3dcontroller.cpp @@ -394,7 +394,7 @@ void Scatter3DController::adjustAxisRanges() if (scatterSeries->isVisible() && proxy) { QVector3D minLimits; QVector3D maxLimits; - proxy->dptrc()->limitValues(minLimits, maxLimits); + proxy->dptrc()->limitValues(minLimits, maxLimits, valueAxisX, valueAxisY, valueAxisZ); if (adjustX) { if (!series) { // First series initializes the values diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index b0cdef14..28327086 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -510,7 +510,7 @@ void Surface3DController::adjustAxisRanges() if (surfaceSeries->isVisible() && proxy) { QVector3D minLimits; QVector3D maxLimits; - proxy->dptrc()->limitValues(minLimits, maxLimits); + proxy->dptrc()->limitValues(minLimits, maxLimits, valueAxisX, valueAxisY, valueAxisZ); if (adjustX) { if (first) { // First series initializes the values -- cgit v1.2.3