summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/data/qheightmapsurfacedataproxy.cpp
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2013-09-30 11:06:58 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2013-10-01 09:03:24 +0300
commit822a19d3e2650c7a9326b69ff4621ccd556e16cc (patch)
tree064fba99ba0e4ec7a3113c5fb051d3cd50972360 /src/datavisualization/data/qheightmapsurfacedataproxy.cpp
parent52fcca463e63500bea81b0ac3615d4779bc7682c (diff)
Refactor surface data item to have X, Y, and Z values.
Task-number: QTRD-2332 Change-Id: I086d3a422ff444cbcede1aa238107ebcbce68729 Reviewed-by: Mika Salmela <mika.salmela@digia.com>
Diffstat (limited to 'src/datavisualization/data/qheightmapsurfacedataproxy.cpp')
-rw-r--r--src/datavisualization/data/qheightmapsurfacedataproxy.cpp253
1 files changed, 245 insertions, 8 deletions
diff --git a/src/datavisualization/data/qheightmapsurfacedataproxy.cpp b/src/datavisualization/data/qheightmapsurfacedataproxy.cpp
index c0b0723c..05b44a17 100644
--- a/src/datavisualization/data/qheightmapsurfacedataproxy.cpp
+++ b/src/datavisualization/data/qheightmapsurfacedataproxy.cpp
@@ -20,6 +20,10 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+// Default ranges correspond value axis defaults
+const float defaultMinValue = 0.0f;
+const float defaultMaxValue = 10.0f;
+
/*!
* \class QHeightMapSurfaceDataProxy
* \inmodule QtDataVisualization
@@ -29,6 +33,11 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* QHeightMapSurfaceDataProxy takes care of surface related height map data handling. It provides a
* way for giving the surface plot a height map to be visualized.
*
+ * Since height maps do not contain values for X or Z axes, those values need to be given
+ * separately using minXValue, maxXValue, minZValue, and maxZValue properties. X-value corresponds
+ * to image horizontal direction and Z-value to the vertical. Setting any of these
+ * properties triggers asynchronous re-resolving of any existing height map.
+ *
* \sa QSurfaceDataProxy
*/
@@ -55,6 +64,11 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* otherwise it is an average calculated from red, green and blue components of the pixels. Using
* grayscale images may improve data conversion speed for large images.
*
+ * Since height maps do not contain values for X or Z axes, those values need to be given
+ * separately using minXValue, maxXValue, minZValue, and maxZValue properties. X-value corresponds
+ * to image horizontal direction and Z-value to the vertical. Setting any of these
+ * properties triggers asynchronous re-resolving of any existing height map.
+ *
* Not recommended formats: all mono formats (for example QImage::Format_Mono).
*/
@@ -68,6 +82,38 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
+ * \qmlproperty qreal HeightMapSurfaceDataProxy::minXValue
+ *
+ * The minimum X value for the generated surface points.
+ * When setting this property the corresponding maximum value is adjusted if necessary,
+ * to ensure that the range remains valid.
+ */
+
+/*!
+ * \qmlproperty qreal HeightMapSurfaceDataProxy::maxXValue
+ *
+ * The maximum X value for the generated surface points.
+ * When setting this property the corresponding minimum value is adjusted if necessary,
+ * to ensure that the range remains valid.
+ */
+
+/*!
+ * \qmlproperty qreal HeightMapSurfaceDataProxy::minZValue
+ *
+ * The minimum Z value for the generated surface points.
+ * When setting this property the corresponding maximum value is adjusted if necessary,
+ * to ensure that the range remains valid.
+ */
+
+/*!
+ * \qmlproperty qreal HeightMapSurfaceDataProxy::maxZValue
+ *
+ * The maximum Z value for the generated surface points.
+ * When setting this property the corresponding minimum value is adjusted if necessary,
+ * to ensure that the range remains valid.
+ */
+
+/*!
* Constructs QHeightMapSurfaceDataProxy with the given \a parent.
*/
QHeightMapSurfaceDataProxy::QHeightMapSurfaceDataProxy(QObject *parent) :
@@ -154,6 +200,85 @@ QString QHeightMapSurfaceDataProxy::heightMapFile() const
{
return dptrc()->m_heightMapFile;
}
+
+/*!
+ * A convenience function for setting all minimum and maximum values at the same time
+ * The minimum values must be smaller than the corresponding maximum value. Otherwise
+ * the values get adjusted so that they are valid.
+ */
+void QHeightMapSurfaceDataProxy::setValueRanges(float minX, float maxX, float minZ, float maxZ)
+{
+ dptr()->setValueRanges(minX, maxX, minZ, maxZ);
+}
+
+/*!
+ * \property QHeightMapSurfaceDataProxy::minXValue
+ *
+ * The minimum X value for the generated surface points.
+ * When setting this property the corresponding maximum value is adjusted if necessary,
+ * to ensure that the range remains valid.
+ */
+void QHeightMapSurfaceDataProxy::setMinXValue(float min)
+{
+ dptr()->setMinXValue(min);
+}
+
+float QHeightMapSurfaceDataProxy::minXValue() const
+{
+ return dptrc()->m_minXValue;
+}
+
+/*!
+ * \property QHeightMapSurfaceDataProxy::maxXValue
+ *
+ * The maximum X value for the generated surface points.
+ * When setting this property the corresponding minimum value is adjusted if necessary,
+ * to ensure that the range remains valid.
+ */
+void QHeightMapSurfaceDataProxy::setMaxXValue(float max)
+{
+ dptr()->setMaxXValue(max);
+}
+
+float QHeightMapSurfaceDataProxy::maxXValue() const
+{
+ return dptrc()->m_maxXValue;
+}
+
+/*!
+ * \property QHeightMapSurfaceDataProxy::minZValue
+ *
+ * The minimum Z value for the generated surface points.
+ * When setting this property the corresponding maximum value is adjusted if necessary,
+ * to ensure that the range remains valid.
+ */
+void QHeightMapSurfaceDataProxy::setMinZValue(float min)
+{
+ dptr()->setMinZValue(min);
+}
+
+float QHeightMapSurfaceDataProxy::minZValue() const
+{
+ return dptrc()->m_minZValue;
+}
+
+/*!
+ * \property QHeightMapSurfaceDataProxy::maxZValue
+ *
+ * The maximum Z value for the generated surface points.
+ * When setting this property the corresponding minimum value is adjusted if necessary,
+ * to ensure that the range remains valid.
+ */
+void QHeightMapSurfaceDataProxy::setMaxZValue(float max)
+{
+ dptr()->setMaxZValue(max);
+}
+
+float QHeightMapSurfaceDataProxy::maxZValue() const
+{
+ return dptrc()->m_maxZValue;
+}
+
/*!
* \internal
*/
@@ -175,7 +300,11 @@ const QHeightMapSurfaceDataProxyPrivate *QHeightMapSurfaceDataProxy::dptrc() con
//
QHeightMapSurfaceDataProxyPrivate::QHeightMapSurfaceDataProxyPrivate(QHeightMapSurfaceDataProxy *q)
- : QSurfaceDataProxyPrivate(q)
+ : QSurfaceDataProxyPrivate(q),
+ m_minXValue(defaultMinValue),
+ m_maxXValue(defaultMaxValue),
+ m_minZValue(defaultMinValue),
+ m_maxZValue(defaultMaxValue)
{
m_resolveTimer.setSingleShot(true);
QObject::connect(&m_resolveTimer, &QTimer::timeout,
@@ -191,6 +320,109 @@ QHeightMapSurfaceDataProxy *QHeightMapSurfaceDataProxyPrivate::qptr()
return static_cast<QHeightMapSurfaceDataProxy *>(q_ptr);
}
+void QHeightMapSurfaceDataProxyPrivate::setValueRanges(float minX, float maxX, float minZ, float maxZ)
+{
+ bool changed = false;
+ if (m_minXValue != minX || m_minZValue != minZ) {
+ m_minXValue = minX;
+ m_minZValue = minZ;
+ changed = true;
+ }
+ if (m_maxXValue != maxX || minX >= maxX) {
+ if (minX >= maxX) {
+ m_maxXValue = minX + 1.0;
+ qWarning() << "Warning: Tried to set invalid range for X value range."
+ " Range automatically adjusted to a valid one:"
+ << minX << "-" << maxX << "-->" << m_minXValue << "-" << m_maxXValue;
+ } else {
+ m_maxXValue = maxX;
+ }
+ changed = true;
+ }
+ if (m_maxZValue != maxZ || minZ >= maxZ) {
+ if (minZ >= maxZ) {
+ m_maxZValue = minZ + 1.0;
+ qWarning() << "Warning: Tried to set invalid range for Z value range."
+ " Range automatically adjusted to a valid one:"
+ << minZ << "-" << maxZ << "-->" << m_minZValue << "-" << m_maxZValue;
+ } else {
+ m_maxZValue = maxZ;
+ }
+ changed = true;
+ }
+
+ if (changed && !m_resolveTimer.isActive())
+ m_resolveTimer.start(0);
+}
+
+void QHeightMapSurfaceDataProxyPrivate::setMinXValue(float min)
+{
+ if (min != m_minXValue) {
+ if (min >= m_maxXValue) {
+ qreal oldMax = m_maxXValue;
+ m_maxXValue = min + 1.0;
+ qWarning() << "Warning: Tried to set minimum X to equal or larger than maximum X for"
+ " value range. Maximum automatically adjusted to a valid one:"
+ << oldMax << "-->" << m_maxXValue;
+ }
+ m_minXValue = min;
+
+ if (!m_resolveTimer.isActive())
+ m_resolveTimer.start(0);
+ }
+}
+
+void QHeightMapSurfaceDataProxyPrivate::setMaxXValue(float max)
+{
+ if (m_maxXValue != max) {
+ if (max <= m_minXValue) {
+ qreal oldMin = m_minXValue;
+ m_minXValue = max - 1.0;
+ qWarning() << "Warning: Tried to set maximum X to equal or smaller than minimum X for"
+ " value range. Minimum automatically adjusted to a valid one:"
+ << oldMin << "-->" << m_minXValue;
+ }
+ m_maxXValue = max;
+
+ if (!m_resolveTimer.isActive())
+ m_resolveTimer.start(0);
+ }
+}
+
+void QHeightMapSurfaceDataProxyPrivate::setMinZValue(float min)
+{
+ if (min != m_minZValue) {
+ if (min >= m_maxZValue) {
+ qreal oldMax = m_maxZValue;
+ m_maxZValue = min + 1.0;
+ qWarning() << "Warning: Tried to set minimum Z to equal or larger than maximum Z for"
+ " value range. Maximum automatically adjusted to a valid one:"
+ << oldMax << "-->" << m_maxZValue;
+ }
+ m_minZValue = min;
+
+ if (!m_resolveTimer.isActive())
+ m_resolveTimer.start(0);
+ }
+}
+
+void QHeightMapSurfaceDataProxyPrivate::setMaxZValue(float max)
+{
+ if (m_maxZValue != max) {
+ if (max <= m_minZValue) {
+ qreal oldMin = m_minZValue;
+ m_minZValue = max - 1.0;
+ qWarning() << "Warning: Tried to set maximum Z to equal or smaller than minimum Z for"
+ " value range. Minimum automatically adjusted to a valid one:"
+ << oldMin << "-->" << m_minZValue;
+ }
+ m_maxZValue = max;
+
+ if (!m_resolveTimer.isActive())
+ m_resolveTimer.start(0);
+ }
+}
+
void QHeightMapSurfaceDataProxyPrivate::handlePendingResolve()
{
QImage heightImage = m_heightMap;
@@ -204,7 +436,7 @@ void QHeightMapSurfaceDataProxyPrivate::handlePendingResolve()
int imageWidth = heightImage.width();
int bitCount = imageWidth * 4 * (imageHeight - 1);
int widthBits = imageWidth * 4;
- qreal height = 0;
+ float height = 0;
// Do not recreate array if dimensions have not changed
QSurfaceDataArray *dataArray = m_dataArray;
@@ -217,12 +449,16 @@ void QHeightMapSurfaceDataProxyPrivate::handlePendingResolve()
}
}
+ float xMul = (m_maxXValue - m_minXValue) / float(imageWidth - 1);
+ float zMul = (m_maxZValue - m_minZValue) / float(imageHeight - 1);
+
if (heightImage.isGrayscale()) {
// Grayscale, it's enough to read Red byte
for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) {
QSurfaceDataRow &newRow = *dataArray->at(i);
for (int j = 0; j < imageWidth; j++)
- newRow[j] = qreal(bits[bitCount + (j * 4)]);
+ newRow[j].setPosition(QVector3D((float(j) * xMul) + m_minXValue, float(bits[bitCount + (j * 4)]),
+ (float(i) * zMul) + m_minZValue));
}
} else {
// Not grayscale, we'll need to calculate height from RGB
@@ -230,15 +466,16 @@ void QHeightMapSurfaceDataProxyPrivate::handlePendingResolve()
QSurfaceDataRow &newRow = *dataArray->at(i);
for (int j = 0; j < imageWidth; j++) {
int nextpixel = j * 4;
- height = (qreal(bits[bitCount + nextpixel])
- + qreal(bits[1 + bitCount + nextpixel])
- + qreal(bits[2 + bitCount + nextpixel]));
- newRow[j] = height / 3.0;
+ height = (float(bits[bitCount + nextpixel])
+ + float(bits[1 + bitCount + nextpixel])
+ + float(bits[2 + bitCount + nextpixel]));
+ newRow[j].setPosition(QVector3D((float(j) * xMul) + m_minXValue, height / 3.0f,
+ (float(i) * zMul) + m_minZValue));
}
}
}
- qptr()->resetArray(dataArray, 0.0, imageHeight, 0.0, imageWidth);
+ qptr()->resetArray(dataArray);
}
QT_DATAVISUALIZATION_END_NAMESPACE