diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-07 14:52:28 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-08 08:21:37 +0300 |
commit | ebee290095f9a32dbcf5956e9fed50d2610cbfe1 (patch) | |
tree | c9260232aa82517c12bbcd94ef3d004b29860959 /src | |
parent | b3e10fcc8403bc1a0d9d4c107b52eb10af0ecffa (diff) |
Tickcount and both automatic and explicit range setting via axes
- Tick count moved to QValueAxis.
- QValueAxis adjusts range to data by default on barcharts.
- QValueaxis explicit range setting now works for barchart.
Change-Id: I2c0afcab34b74a848144fda41d9135dcdb510354
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/datavis3d/axis/qvalueaxis.cpp | 91 | ||||
-rw-r--r-- | src/datavis3d/axis/qvalueaxis.h | 9 | ||||
-rw-r--r-- | src/datavis3d/axis/qvalueaxis_p.h | 8 | ||||
-rw-r--r-- | src/datavis3d/engine/abstract3dcontroller.cpp | 26 | ||||
-rw-r--r-- | src/datavis3d/engine/abstract3dcontroller_p.h | 3 | ||||
-rw-r--r-- | src/datavis3d/engine/abstract3drenderer.cpp | 8 | ||||
-rw-r--r-- | src/datavis3d/engine/abstract3drenderer_p.h | 1 | ||||
-rw-r--r-- | src/datavis3d/engine/axisrendercache.cpp | 30 | ||||
-rw-r--r-- | src/datavis3d/engine/axisrendercache_p.h | 13 | ||||
-rw-r--r-- | src/datavis3d/engine/bars3dcontroller.cpp | 49 | ||||
-rw-r--r-- | src/datavis3d/engine/bars3dcontroller_p.h | 14 | ||||
-rw-r--r-- | src/datavis3d/engine/bars3drenderer.cpp | 268 | ||||
-rw-r--r-- | src/datavis3d/engine/bars3drenderer_p.h | 11 | ||||
-rw-r--r-- | src/datavis3d/engine/q3dbars.cpp | 23 | ||||
-rw-r--r-- | src/datavis3d/engine/q3dbars.h | 12 | ||||
-rw-r--r-- | src/datavis3d/utils/abstractobjecthelper.cpp | 2 | ||||
-rw-r--r-- | src/datavis3d/utils/objecthelper.cpp | 1 | ||||
-rw-r--r-- | src/datavis3dqml2/declarativebars.cpp | 12 |
18 files changed, 342 insertions, 239 deletions
diff --git a/src/datavis3d/axis/qvalueaxis.cpp b/src/datavis3d/axis/qvalueaxis.cpp index a4e0c85f..f6ec52c4 100644 --- a/src/datavis3d/axis/qvalueaxis.cpp +++ b/src/datavis3d/axis/qvalueaxis.cpp @@ -55,33 +55,20 @@ QValueAxis::~QValueAxis() void QValueAxis::setRange(qreal min, qreal max) { - bool dirty = false; - if (dptr()->m_min != min) { - dptr()->m_min = min; - dirty = true; - } - if (dptr()->m_max != max) { - dptr()->m_max = max; - dirty = true; - } - if (dirty) - emit rangeChanged(min, max); + dptr()->setRange(min, max); + setAutoAdjustRange(false); } void QValueAxis::setMin(qreal min) { - if (dptr()->m_min != min) { - dptr()->m_min = min; - emit rangeChanged(min, dptr()->m_max); - } + dptr()->setMin(min); + setAutoAdjustRange(false); } void QValueAxis::setMax(qreal max) { - if (dptr()->m_max != max) { - dptr()->m_max = max; - emit rangeChanged(dptr()->m_min, max); - } + dptr()->setMax(max); + setAutoAdjustRange(false); } qreal QValueAxis::min() const @@ -94,6 +81,32 @@ qreal QValueAxis::max() const return dptrc()->m_max; } +void QValueAxis::setTickCount(int count) +{ + if (dptr()->m_tickCount != count){ + dptr()->m_tickCount = count; + emit tickCountChanged(count); + } +} + +int QValueAxis::tickCount() const +{ + return dptrc()->m_tickCount; +} + +void QValueAxis::setAutoAdjustRange(bool autoAdjust) +{ + if (dptr()->m_autoAdjust != autoAdjust) { + dptr()->m_autoAdjust = autoAdjust; + emit autoAdjustRangeChanged(autoAdjust); + } +} + +bool QValueAxis::isAutoAdjustRange() const +{ + return dptrc()->m_autoAdjust; +} + QValueAxisPrivate *QValueAxis::dptr() { return static_cast<QValueAxisPrivate *>(d_ptr.data()); @@ -107,7 +120,9 @@ const QValueAxisPrivate *QValueAxis::dptrc() const QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q) : QAbstractAxisPrivate(q, QAbstractAxis::AxisTypeValue), m_min(0.0), - m_max(0.0) + m_max(10.0), + m_tickCount(10), + m_autoAdjust(true) { } @@ -115,4 +130,40 @@ QValueAxisPrivate::~QValueAxisPrivate() { } +void QValueAxisPrivate::setRange(qreal min, qreal max) +{ + bool dirty = false; + if (m_min != min) { + m_min = min; + dirty = true; + } + if (m_max != max) { + m_max = max; + dirty = true; + } + if (dirty) + emit qptr()->rangeChanged(min, max); +} + +void QValueAxisPrivate::setMin(qreal min) +{ + if (m_min != min) { + m_min = min; + emit qptr()->rangeChanged(m_min, m_max); + } +} + +void QValueAxisPrivate::setMax(qreal max) +{ + if (m_max != max) { + m_max = max; + emit qptr()->rangeChanged(m_min, m_max); + } +} + +QValueAxis *QValueAxisPrivate::qptr() +{ + return static_cast<QValueAxis *>(q_ptr); +} + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qvalueaxis.h b/src/datavis3d/axis/qvalueaxis.h index 5467b81c..af410d9c 100644 --- a/src/datavis3d/axis/qvalueaxis.h +++ b/src/datavis3d/axis/qvalueaxis.h @@ -61,8 +61,16 @@ public: qreal min() const; qreal max() const; + void setTickCount(int count); + int tickCount() const; + + void setAutoAdjustRange(bool autoAdjust); + bool isAutoAdjustRange() const; + signals: void rangeChanged(qreal min, qreal max); + void tickCountChanged(int count); + void autoAdjustRangeChanged(bool autoAdjust); protected: QValueAxisPrivate *dptr(); @@ -70,6 +78,7 @@ protected: private: Q_DISABLE_COPY(QValueAxis) + friend class Bars3dController; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qvalueaxis_p.h b/src/datavis3d/axis/qvalueaxis_p.h index 22663eb8..ac5aae38 100644 --- a/src/datavis3d/axis/qvalueaxis_p.h +++ b/src/datavis3d/axis/qvalueaxis_p.h @@ -65,11 +65,19 @@ public: QValueAxisPrivate(QValueAxis *q); virtual ~QValueAxisPrivate(); + void setRange(qreal min, qreal max); + void setMin(qreal min); + void setMax (qreal max); + protected: qreal m_min; qreal m_max; + int m_tickCount; + bool m_autoAdjust; private: + QValueAxis *qptr(); + friend class QValueAxis; }; diff --git a/src/datavis3d/engine/abstract3dcontroller.cpp b/src/datavis3d/engine/abstract3dcontroller.cpp index 30e5e694..44022a4b 100644 --- a/src/datavis3d/engine/abstract3dcontroller.cpp +++ b/src/datavis3d/engine/abstract3dcontroller.cpp @@ -302,6 +302,25 @@ void Abstract3DController::handleAxisRangeChanged(qreal min, qreal max) qWarning() << __FUNCTION__ << "invoked for invalid axis"; } +void Abstract3DController::handleAxisTickCountChanged(int count) +{ + if (sender() == m_axisX) + emit axisTickCountChanged(QAbstractAxis::AxisOrientationX, count); + else if (sender() == m_axisY) + emit axisTickCountChanged(QAbstractAxis::AxisOrientationY, count); + else if (sender() == m_axisZ) + emit axisTickCountChanged(QAbstractAxis::AxisOrientationZ, count); + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; +} + +void Abstract3DController::handleAxisAutoAdjustRangeChanged(bool autoAdjust) +{ + Q_UNUSED(autoAdjust) + // Adjust axis range according to data. Default implementation does nothing, + // This needs to be implemented by subclass. +} + void Abstract3DController::setAxisHelper(QAbstractAxis::AxisOrientation orientation, QAbstractAxis *axis, QAbstractAxis **axisPtr) { @@ -324,9 +343,14 @@ void Abstract3DController::setAxisHelper(QAbstractAxis::AxisOrientation orientat QValueAxis *valueAxis = static_cast<QValueAxis *>(axis); QObject::connect(valueAxis, &QValueAxis::rangeChanged, this, &Abstract3DController::handleAxisRangeChanged); + QObject::connect(valueAxis, &QValueAxis::tickCountChanged, + this, &Abstract3DController::handleAxisTickCountChanged); + QObject::connect(valueAxis, &QValueAxis::autoAdjustRangeChanged, + this, &Abstract3DController::handleAxisAutoAdjustRangeChanged); emit axisRangeChanged(orientation, valueAxis->min(), valueAxis->max()); + emit axisTickCountChanged(orientation, valueAxis->tickCount()); + handleAxisAutoAdjustRangeChanged(valueAxis->isAutoAdjustRange()); } - } QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3dcontroller_p.h b/src/datavis3d/engine/abstract3dcontroller_p.h index abf4845a..7075cb7e 100644 --- a/src/datavis3d/engine/abstract3dcontroller_p.h +++ b/src/datavis3d/engine/abstract3dcontroller_p.h @@ -164,6 +164,8 @@ public slots: void handleAxisTitleChanged(const QString &title); void handleAxisLabelsChanged(); void handleAxisRangeChanged(qreal min, qreal max); + void handleAxisTickCountChanged(int count); + void handleAxisAutoAdjustRangeChanged(bool autoAdjust); signals: void boundingRectChanged(QRect boundingRect); @@ -178,6 +180,7 @@ signals: void axisTitleChanged(QAbstractAxis::AxisOrientation orientation, QString title); void axisLabelsChanged(QAbstractAxis::AxisOrientation orientation, QStringList labels); void axisRangeChanged(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + void axisTickCountChanged(QAbstractAxis::AxisOrientation orientation, int count); private: void setAxisHelper(QAbstractAxis::AxisOrientation orientation, QAbstractAxis *axis, QAbstractAxis **axisPtr); diff --git a/src/datavis3d/engine/abstract3drenderer.cpp b/src/datavis3d/engine/abstract3drenderer.cpp index e291419a..270b5937 100644 --- a/src/datavis3d/engine/abstract3drenderer.cpp +++ b/src/datavis3d/engine/abstract3drenderer.cpp @@ -76,6 +76,8 @@ void Abstract3DRenderer::initializePreOpenGL() &Abstract3DRenderer::updateAxisLabels); QObject::connect(m_controller, &Abstract3DController::axisRangeChanged, this, &Abstract3DRenderer::updateAxisRange); + QObject::connect(m_controller, &Abstract3DController::axisTickCountChanged, this, + &Abstract3DRenderer::updateAxisTickCount); updateTheme(m_controller->theme()); updateFont(m_controller->font()); @@ -206,6 +208,11 @@ void Abstract3DRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientat cache.setMax(max); } +void Abstract3DRenderer::updateAxisTickCount(QAbstractAxis::AxisOrientation orientation, int count) +{ + axisCacheForOrientation(orientation).setTickCount(count); +} + // This method needs to be called under the controller-renderer sync mutex void Abstract3DRenderer::initializeAxisCache(QAbstractAxis::AxisOrientation orientation, const QAbstractAxis *axis) { @@ -218,6 +225,7 @@ void Abstract3DRenderer::initializeAxisCache(QAbstractAxis::AxisOrientation orie if (axis->type() & QAbstractAxis::AxisTypeValue) { const QValueAxis *valueAxis = static_cast<const QValueAxis *>(axis); updateAxisRange(orientation, valueAxis->min(), valueAxis->max()); + updateAxisTickCount(orientation, valueAxis->tickCount()); } } } diff --git a/src/datavis3d/engine/abstract3drenderer_p.h b/src/datavis3d/engine/abstract3drenderer_p.h index e7764710..98a37d3c 100644 --- a/src/datavis3d/engine/abstract3drenderer_p.h +++ b/src/datavis3d/engine/abstract3drenderer_p.h @@ -104,6 +104,7 @@ protected: virtual void updateAxisTitle(QAbstractAxis::AxisOrientation orientation, const QString &title); virtual void updateAxisLabels(QAbstractAxis::AxisOrientation orientation, const QStringList &labels); virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + virtual void updateAxisTickCount(QAbstractAxis::AxisOrientation orientation, int count); void initializeAxisCache(QAbstractAxis::AxisOrientation orientation, const QAbstractAxis *axis); AxisRenderCache &axisCacheForOrientation(QAbstractAxis::AxisOrientation orientation); diff --git a/src/datavis3d/engine/axisrendercache.cpp b/src/datavis3d/engine/axisrendercache.cpp index 4997ed80..a5466aba 100644 --- a/src/datavis3d/engine/axisrendercache.cpp +++ b/src/datavis3d/engine/axisrendercache.cpp @@ -47,7 +47,8 @@ AxisRenderCache::AxisRenderCache() : m_type(QAbstractAxis::AxisTypeNone), m_min(0.0), m_max(0.0), - m_drawer(0) + m_drawer(0), + m_tickStep(0.0f) { } @@ -112,6 +113,24 @@ void AxisRenderCache::setLabels(const QStringList &labels) } } +void AxisRenderCache::setMin(qreal min) +{ + m_min = min; + updateTickStep(); +} + +void AxisRenderCache::setMax(qreal max) +{ + m_max = max; + updateTickStep(); +} + +void AxisRenderCache::setTickCount(int count) +{ + m_tickCount = count; + updateTickStep(); +} + void AxisRenderCache::updateTextures() { if (m_title.isEmpty()) @@ -127,4 +146,13 @@ void AxisRenderCache::updateTextures() } } +void AxisRenderCache::updateTickStep() +{ + if (m_tickCount > 0) + m_tickStep = (m_max - m_min) / m_tickCount; + else + m_tickStep = 0.0f; + +} + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/axisrendercache_p.h b/src/datavis3d/engine/axisrendercache_p.h index c8fa45d5..5f9a0292 100644 --- a/src/datavis3d/engine/axisrendercache_p.h +++ b/src/datavis3d/engine/axisrendercache_p.h @@ -74,31 +74,38 @@ public: inline const QString &title() { return m_title; } void setLabels(const QStringList &labels); inline const QStringList &labels() { return m_labels; } - inline void setMin(qreal min) { m_min = min; } + void setMin(qreal min); inline qreal min() { return m_min; } - inline void setMax(qreal max) { m_max = max; } + void setMax(qreal max); inline qreal max() { return m_max; } + void setTickCount(int count); + inline int tickCount() const { return m_tickCount; } inline LabelItem &titleItem() { return m_titleItem; } inline QList<LabelItem *> &labelItems() { return m_labelItems; } + inline GLfloat tickStep() const { return m_tickStep; } public slots: void updateTextures(); private: + void updateTickStep(); + // Cached axis values QAbstractAxis::AxisType m_type; QString m_title; QStringList m_labels; qreal m_min; qreal m_max; + int m_tickCount; // Renderer items Drawer *m_drawer; // Not owned LabelItem m_titleItem; QList<LabelItem *> m_labelItems; + GLfloat m_tickStep; - Q_DISABLE_COPY(AxisRenderCache); + Q_DISABLE_COPY(AxisRenderCache) }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/bars3dcontroller.cpp b/src/datavis3d/engine/bars3dcontroller.cpp index c1dc09ef..6188d203 100644 --- a/src/datavis3d/engine/bars3dcontroller.cpp +++ b/src/datavis3d/engine/bars3dcontroller.cpp @@ -44,7 +44,7 @@ #include "camerahelper_p.h" #include "utils_p.h" #include "qabstractaxis_p.h" -#include "qvalueaxis.h" +#include "qvalueaxis_p.h" #include "qcategoryaxis.h" #include "qbardataproxy_p.h" @@ -71,9 +71,6 @@ Bars3dController::Bars3dController(QRect boundRect) m_objFile(QStringLiteral(":/defaultMeshes/bar")), m_isGridEnabled(true), m_isBackgroundEnabled(true), - m_tickCount(0), - m_tickStep(0), - m_tickMinimum(0.0f), m_renderer(0), m_data(0), m_valuesDirty(false) @@ -284,7 +281,7 @@ QBarDataProxy *Bars3dController::dataProxy() void Bars3dController::handleArrayReset() { setSlicingActive(false); - handleLimitChange(); + adjustValueAxisRange(); m_valuesDirty = true; } @@ -295,7 +292,7 @@ void Bars3dController::handleRowsAdded(int startIndex, int count) // TODO check if affects data window // TODO should update slice instead of deactivating? setSlicingActive(false); - handleLimitChange(); + adjustValueAxisRange(); m_valuesDirty = true; } @@ -306,7 +303,7 @@ void Bars3dController::handleRowsChanged(int startIndex, int count) // TODO check if affects data window // TODO should update slice instead of deactivating? setSlicingActive(false); - handleLimitChange(); + adjustValueAxisRange(); m_valuesDirty = true; } @@ -317,7 +314,7 @@ void Bars3dController::handleRowsRemoved(int startIndex, int count) // TODO check if affects data window // TODO should update slice instead of deactivating? setSlicingActive(false); - handleLimitChange(); + adjustValueAxisRange(); m_valuesDirty = true; } @@ -328,10 +325,16 @@ void Bars3dController::handleRowsInserted(int startIndex, int count) // TODO check if affects data window // TODO should update slice instead of deactivating? setSlicingActive(false); - handleLimitChange(); + adjustValueAxisRange(); m_valuesDirty = true; } +void Bars3dController::handleAxisAutoAdjustRangeChanged(bool autoAdjust) +{ + Q_UNUSED(autoAdjust) + adjustValueAxisRange(); +} + void Bars3dController::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) { m_barThickness = thickness; @@ -416,6 +419,8 @@ void Bars3dController::setupSampleSpace(int rowCount, int columnCount) m_rowCount = rowCount; m_columnCount = columnCount; + adjustValueAxisRange(); + emit sampleSpaceChanged(rowCount, columnCount); } @@ -460,14 +465,6 @@ bool Bars3dController::backgroundEnabled() return m_isBackgroundEnabled; } -void Bars3dController::setTickCount(GLint tickCount, GLfloat step, GLfloat minimum) -{ - m_tickCount = tickCount; - m_tickStep = step; - m_tickMinimum = minimum; - emit tickCountChanged(m_tickCount, m_tickStep, m_tickMinimum); -} - int Bars3dController::columnCount() { return m_columnCount; @@ -478,12 +475,20 @@ int Bars3dController::rowCount() return m_rowCount; } -void Bars3dController::handleLimitChange() +void Bars3dController::adjustValueAxisRange() { - // Get the limits for data window - QPair<GLfloat, GLfloat> limits = m_data->dptr()->limitValues(0, m_rowCount, 0, m_columnCount); - - emit limitsChanged(limits); + QValueAxis *valueAxis = static_cast<QValueAxis *>(m_axisY); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + QPair<GLfloat, GLfloat> limits = m_data->dptr()->limitValues(0, m_rowCount, 0, m_columnCount); + if (limits.first < 0) { + // TODO: Currently we only support symmetric y-axis for bar chart if there are negative values + qreal maxAbs = qMax(qFabs(limits.first), qFabs(limits.second)); + // Call private implementation to avoid unsetting auto adjust flag + valueAxis->dptr()->setRange(-maxAbs, maxAbs); + } else { + valueAxis->dptr()->setRange(0.0, limits.second); + } + } } QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/bars3dcontroller_p.h b/src/datavis3d/engine/bars3dcontroller_p.h index 25d1d2f5..cf186ff1 100644 --- a/src/datavis3d/engine/bars3dcontroller_p.h +++ b/src/datavis3d/engine/bars3dcontroller_p.h @@ -103,9 +103,6 @@ private: QString m_objFile; bool m_isGridEnabled; bool m_isBackgroundEnabled; - GLint m_tickCount; - GLfloat m_tickStep; - GLfloat m_tickMinimum; Bars3dRenderer *m_renderer; QBarDataProxy *m_data; @@ -151,11 +148,6 @@ public: // how many samples per row and column, and names for axes void setupSampleSpace(int samplesRow, int samplesColumn); - // Set tick count and step. Note; tickCount * step should be the maximum possible value of data - // set. Minimum is the absolute minimum possible value a bar can have. This is especially - // important to set if values can be negative. - void setTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f); - // TODO: light placement API // Change selection mode; single bar, bar and row, bar and column, or all @@ -191,19 +183,19 @@ public slots: void handleRowsRemoved(int startIndex, int count); void handleRowsInserted(int startIndex, int count); + void handleAxisAutoAdjustRangeChanged(bool autoAdjust); + signals: void selectionModeChanged(SelectionMode mode); void slicingActiveChanged(bool isSlicing); - void limitsChanged(QPair<GLfloat, GLfloat> limits); // TODO should be handled via axis range void sampleSpaceChanged(int samplesRow, int samplesColumn); void barSpecsChanged(QSizeF thickness, QSizeF spacing, bool relative); void objFileChanged(QString fileName); void gridEnabledChanged(bool enable); // TODO should be handled via axis void backgroundEnabledChanged(bool enable); - void tickCountChanged(GLint tickCount, GLfloat step, GLfloat minimum); // TODO should be handled via axis private: - void handleLimitChange(); + void adjustValueAxisRange(); Q_DISABLE_COPY(Bars3dController) diff --git a/src/datavis3d/engine/bars3drenderer.cpp b/src/datavis3d/engine/bars3drenderer.cpp index 6ed63d9b..cb3dc875 100644 --- a/src/datavis3d/engine/bars3drenderer.cpp +++ b/src/datavis3d/engine/bars3drenderer.cpp @@ -84,8 +84,6 @@ Bars3dRenderer::Bars3dRenderer(Bars3dController *controller) m_sliceSelection(0), m_sliceCache(0), m_sliceTitleItem(0), - m_tickCount(0), - m_tickStep(0), m_xFlipped(false), m_zFlipped(false), m_yFlipped(false), @@ -161,8 +159,6 @@ void Bars3dRenderer::initializePreOpenGL() &Bars3dRenderer::updateSelectionMode); QObject::connect(m_controller, &Bars3dController::slicingActiveChanged, this, &Bars3dRenderer::updateSlicingActive); - QObject::connect(m_controller, &Bars3dController::limitsChanged, this, - &Bars3dRenderer::updateLimits); QObject::connect(m_controller, &Bars3dController::sampleSpaceChanged, this, &Bars3dRenderer::updateSampleSpace); QObject::connect(m_controller, &Bars3dController::barSpecsChanged, this, @@ -175,8 +171,6 @@ void Bars3dRenderer::initializePreOpenGL() &Bars3dRenderer::updateGridEnabled); QObject::connect(m_controller, &Bars3dController::backgroundEnabledChanged, this, &Bars3dRenderer::updateBackgroundEnabled); - QObject::connect(m_controller, &Bars3dController::tickCountChanged, this, - &Bars3dRenderer::updateTickCount); QObject::connect(m_controller, &Bars3dController::zoomLevelChanged, this, &Bars3dRenderer::updateZoomLevel); @@ -184,7 +178,6 @@ void Bars3dRenderer::initializePreOpenGL() updateSampleSpace(m_controller->rowCount(), m_controller->columnCount()); updateSelectionMode(m_controller->selectionMode()); updateSlicingActive(m_controller->isSlicingActive()); - updateLimits(m_controller->limits()); updateZoomLevel(m_controller->zoomLevel()); updateBarSpecs(m_controller->barThickness(), m_controller->barSpacing(), m_controller->isBarSpecRelative()); @@ -1161,121 +1154,119 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, } } - // Wall lines: back wall - GLfloat heightStep = m_heightNormalizer / 5.0f; // default to 5 lines - GLfloat startLine; + if (m_axisCacheY.tickCount() > 0) { + // Wall lines: back wall + GLfloat heightStep = m_axisCacheY.tickStep(); + GLfloat startLine; - if (m_tickCount > 0) - heightStep = m_tickStep; - - if (m_hasNegativeValues) - startLine = -m_heightNormalizer; - else - startLine = heightStep; - - for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer; - lineHeight += heightStep) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; + if (m_hasNegativeValues) + startLine = -m_heightNormalizer; + else + startLine = heightStep; - if (m_zFlipped) { - modelMatrix.translate(0.0f, - 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, - m_columnDepth / m_scaleFactor + zComp); - } else { - modelMatrix.translate(0.0f, - 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, - -m_columnDepth / m_scaleFactor + zComp); - } - modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, - gridLineWidth)); - itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, - gridLineWidth)); + for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer; + lineHeight += heightStep) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (m_zFlipped) { + modelMatrix.translate(0.0f, + 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, + m_columnDepth / m_scaleFactor + zComp); + } else { + modelMatrix.translate(0.0f, + 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, + -m_columnDepth / m_scaleFactor + zComp); + } + modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, + gridLineWidth)); + itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, + gridLineWidth)); - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + // Set the rest of the shader bindings + m_barShader->setUniformValue(m_barShader->model(), modelMatrix); + m_barShader->setUniformValue(m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > ShadowNone) { - // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + if (m_cachedShadowQuality > ShadowNone) { + // Set shadow shader bindings + m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); + m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); + m_barShader->setUniformValue(m_barShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); - } else + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + } else #endif - { - // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + { + // Set shadowless shader bindings + m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj); + } } - } - // Wall lines: side wall - for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer; - lineHeight += heightStep) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - if (m_xFlipped) { - modelMatrix.translate(m_rowWidth / m_scaleFactor, - 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, - zComp); - } else { - modelMatrix.translate(-m_rowWidth / m_scaleFactor, - 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, - zComp); - } - modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, - m_columnDepth / m_scaleFactor)); - itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, - m_columnDepth / m_scaleFactor)); + // Wall lines: side wall + for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer; + lineHeight += heightStep) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (m_xFlipped) { + modelMatrix.translate(m_rowWidth / m_scaleFactor, + 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, + zComp); + } else { + modelMatrix.translate(-m_rowWidth / m_scaleFactor, + 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, + zComp); + } + modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + m_columnDepth / m_scaleFactor)); + itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + m_columnDepth / m_scaleFactor)); - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + // Set the rest of the shader bindings + m_barShader->setUniformValue(m_barShader->model(), modelMatrix); + m_barShader->setUniformValue(m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > ShadowNone) { - // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + if (m_cachedShadowQuality > ShadowNone) { + // Set shadow shader bindings + m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); + m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); + m_barShader->setUniformValue(m_barShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); - } else + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + } else #endif - { - // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + { + // Set shadowless shader bindings + m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj); + } } } - // Release bar shader m_barShader->release(); } @@ -1514,6 +1505,33 @@ void Bars3dRenderer::updateMeshFileName(const QString &objFileName) loadBarMesh(); } +void Bars3dRenderer::updateAxisTickCount(QAbstractAxis::AxisOrientation orientation, int count) +{ + Abstract3DRenderer::updateAxisTickCount(orientation, count); + calculateHeightAdjustment(); +} + +void Bars3dRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max) +{ + Abstract3DRenderer::updateAxisRange(orientation, min, max); + calculateHeightAdjustment(); + + // Check if we have negative values + if (min < 0 && !m_hasNegativeValues) { + m_hasNegativeValues = true; + // Reload background + loadBackgroundMesh(); + } else if (min >= 0 && m_hasNegativeValues) { + m_hasNegativeValues = false; + // Reload background + loadBackgroundMesh(); + } + + // TODO Currently barchart only supports zero centered or zero minimum ranges + if (min > 0.0 || (min != 0.0 && (qFabs(min) != qFabs(max)))) + qWarning() << __FUNCTION__ << "Bar chart currently properly supports only zero-centered and zero minimum ranges for Y-axis."; +} + void Bars3dRenderer::updateSampleSpace(int rowCount, int columnCount) { // Destroy old render items and reallocate new array @@ -1633,17 +1651,6 @@ void Bars3dRenderer::updateShadowQuality(ShadowQuality quality) #endif } -void Bars3dRenderer::updateTickCount(GLint tickCount, GLfloat step, GLfloat minimum) -{ - m_tickCount = tickCount; - m_tickStep = step; - if (tickCount > 0 && step > 0) { - m_heightNormalizer = tickCount * step; - calculateHeightAdjustment(QPair<float, float>(minimum, m_heightNormalizer)); - m_valueUpdateNeeded = true; - } -} - void Bars3dRenderer::loadBarMesh() { QString objectFileName = m_cachedObjFile; @@ -1704,15 +1711,20 @@ void Bars3dRenderer::calculateSceneScalingFactors() //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension; } -void Bars3dRenderer::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits) +void Bars3dRenderer::calculateHeightAdjustment() { + m_heightNormalizer = (GLfloat)qMax(qFabs(m_axisCacheY.min()), qFabs(m_axisCacheY.max())); + // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer - GLfloat newAdjustment = 2.0f - ((limits.second - limits.first) / m_heightNormalizer); + GLfloat newAdjustment = 2.0f - ((m_heightNormalizer - m_axisCacheY.min()) / m_heightNormalizer); if (newAdjustment != m_yAdjustment) { m_hasHeightAdjustmentChanged = true; m_yAdjustment = newAdjustment; } //qDebug() << m_yAdjustment; + + // If this function needs to be called, then value update is also needed + m_valueUpdateNeeded = true; } Bars3dController::SelectionType Bars3dRenderer::isSelected(GLint row, GLint bar) @@ -1750,32 +1762,6 @@ Bars3dController::SelectionType Bars3dRenderer::isSelected(GLint row, GLint bar) return isSelectedType; } -void Bars3dRenderer::updateLimits(QPair<GLfloat, GLfloat> limits) -{ - m_limits.first = limits.first; - m_limits.second = limits.second; - - // TODO: What if we have only negative values? - - // Check if we have negative values - if (limits.first < 0 && !m_hasNegativeValues) { - m_hasNegativeValues = true; - // Reload background - loadBackgroundMesh(); - } else if (limits.first >= 0 && m_hasNegativeValues) { - m_hasNegativeValues = false; - // Reload background - loadBackgroundMesh(); - } - - // Don't auto-adjust height if tick count is set - if (m_tickCount == 0) { - m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - calculateHeightAdjustment(limits); - m_valueUpdateNeeded = true; - } -} - void Bars3dRenderer::updateSlicingActive(bool isSlicing) { m_cachedIsSlicingActivated = isSlicing; diff --git a/src/datavis3d/engine/bars3drenderer_p.h b/src/datavis3d/engine/bars3drenderer_p.h index f886a2ef..046efa4f 100644 --- a/src/datavis3d/engine/bars3drenderer_p.h +++ b/src/datavis3d/engine/bars3drenderer_p.h @@ -112,8 +112,6 @@ private: QList<BarRenderItem *> *m_sliceSelection; AxisRenderCache *m_sliceCache; // not owned const LabelItem *m_sliceTitleItem; // not owned - GLint m_tickCount; - GLfloat m_tickStep; bool m_xFlipped; bool m_zFlipped; bool m_yFlipped; @@ -152,7 +150,6 @@ private: bool m_isSelectionPointRequestActive; bool m_hasHeightAdjustmentChanged; - QPair<GLfloat,GLfloat> m_limits; BarRenderItem m_dummyBarRenderItem; QBarDataProxy *m_dataProxy; // Only valid during render @@ -180,14 +177,16 @@ public slots: bool relative = true); void updateSelectionMode(SelectionMode newMode); void updateSlicingActive(bool isSlicing); - void updateLimits(QPair<GLfloat, GLfloat> newLimits); void updateSampleSpace(int rowCount, int columnCount); void updateZoomLevel(int newZoomLevel); void updateGridEnabled(bool enable); void updateBackgroundEnabled(bool enable); - void updateTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f); void updateMeshFileName(const QString &objFileName); + // Overloaded from abstract renderer + virtual void updateAxisTickCount(QAbstractAxis::AxisOrientation orientation, int count); + virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + // Requests that upon next render pass the column and row under the given point is inspected for selection. // Only one request can be queued per render pass at this point. New request will override any pending requests. // After inspection the selectionUpdated signal is emitted. @@ -221,7 +220,7 @@ private: void updateDepthBuffer(); #endif void calculateSceneScalingFactors(); - void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits); + void calculateHeightAdjustment(); Bars3dController::SelectionType isSelected(GLint row, GLint bar); Q_DISABLE_COPY(Bars3dRenderer) diff --git a/src/datavis3d/engine/q3dbars.cpp b/src/datavis3d/engine/q3dbars.cpp index 2f3facee..33df8d2a 100644 --- a/src/datavis3d/engine/q3dbars.cpp +++ b/src/datavis3d/engine/q3dbars.cpp @@ -42,6 +42,7 @@ #include "q3dbars.h" #include "q3dbars_p.h" #include "bars3dcontroller_p.h" +#include "qvalueaxis.h" #include <QMouseEvent> @@ -466,16 +467,16 @@ QCategoryAxis *Q3DBars::columnAxis() return reinterpret_cast<QCategoryAxis *>(d_ptr->m_shared->axisZ()); } -void Q3DBars::setValueAxis(QAbstractAxis *axis) +void Q3DBars::setValueAxis(QValueAxis *axis) { Q_ASSERT(axis); return d_ptr->m_shared->setAxisY(axis); } -QAbstractAxis *Q3DBars::valueAxis() +QValueAxis *Q3DBars::valueAxis() { - return d_ptr->m_shared->axisY(); + return static_cast<QValueAxis *>(d_ptr->m_shared->axisY()); } void Q3DBars::setDataProxy(QBarDataProxy *proxy) @@ -488,22 +489,6 @@ QBarDataProxy *Q3DBars::dataProxy() return d_ptr->m_shared->dataProxy(); } -/*! - * \a tickCount How many ticks will be drawn. \c 5 by default. - * - * \a step How large a step each tick is. - * - * \a minimum Minimum value a bar in data set can have. Setting this correctly is especially - * important if values can be negative, or autoscaling won't work correctly. - * - * Sets tick count and step. Note; tickCount * step should be the maximum possible value of data - * set. - */ -void Q3DBars::setTickCount(int tickCount, qreal step, qreal minimum) -{ - d_ptr->m_shared->setTickCount(GLint(tickCount), GLfloat(step), GLfloat(minimum)); -} - Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect) : q_ptr(q), m_shared(new Bars3dController(rect)) diff --git a/src/datavis3d/engine/q3dbars.h b/src/datavis3d/engine/q3dbars.h index 4d71185b..53ba9bca 100644 --- a/src/datavis3d/engine/q3dbars.h +++ b/src/datavis3d/engine/q3dbars.h @@ -49,9 +49,8 @@ QT_DATAVIS3D_BEGIN_NAMESPACE class Q3DBarsPrivate; -class LabelItem; -class QAbstractAxis; class QCategoryAxis; +class QValueAxis; class QBarDataProxy; class QT_DATAVIS3D_EXPORT Q3DBars : public Q3DWindow @@ -104,11 +103,6 @@ public: void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform = true); - // Set tick count and step. Note; tickCount * step should be the maximum possible value of data - // set. Minimum is the absolute minimum possible value a bar can have. This is especially - // important to set if values can be negative. - void setTickCount(int tickCount, qreal step, qreal minimum = 0.0f); - // override bar type with own mesh void setMeshFileName(const QString &objFileName); // TODO: light placement API @@ -154,8 +148,8 @@ public: // customized. QCategoryAxis *rowAxis(); QCategoryAxis *columnAxis(); - void setValueAxis(QAbstractAxis *axis); - QAbstractAxis *valueAxis(); + void setValueAxis(QValueAxis *axis); + QValueAxis *valueAxis(); // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. void setDataProxy(QBarDataProxy *proxy); diff --git a/src/datavis3d/utils/abstractobjecthelper.cpp b/src/datavis3d/utils/abstractobjecthelper.cpp index c75d9cf5..b4e1e104 100644 --- a/src/datavis3d/utils/abstractobjecthelper.cpp +++ b/src/datavis3d/utils/abstractobjecthelper.cpp @@ -53,12 +53,10 @@ AbstractObjectHelper::AbstractObjectHelper() m_indexCount(0), m_meshDataLoaded(false) { - qDebug() << "AbstractObjectHelper::AbstractObjectHelper"; } AbstractObjectHelper::~AbstractObjectHelper() { - qDebug() << "AbstractObjectHelper::~AbstractObjectHelper"; glDeleteBuffers(1, &m_vertexbuffer); glDeleteBuffers(1, &m_uvbuffer); glDeleteBuffers(1, &m_normalbuffer); diff --git a/src/datavis3d/utils/objecthelper.cpp b/src/datavis3d/utils/objecthelper.cpp index aef1ddd0..8617ba06 100644 --- a/src/datavis3d/utils/objecthelper.cpp +++ b/src/datavis3d/utils/objecthelper.cpp @@ -56,7 +56,6 @@ ObjectHelper::ObjectHelper(const QString &objectFile) ObjectHelper::~ObjectHelper() { - qDebug() << "ObjectHelper::~ObjectHelper()"; } void ObjectHelper::setObjectFile(const QString &objectFile) diff --git a/src/datavis3dqml2/declarativebars.cpp b/src/datavis3dqml2/declarativebars.cpp index 3b6641dd..0f3ddd9a 100644 --- a/src/datavis3dqml2/declarativebars.cpp +++ b/src/datavis3dqml2/declarativebars.cpp @@ -42,6 +42,7 @@ #include "declarativebars.h" #include "bars3dcontroller_p.h" #include "qitemmodelbardataproxy.h" +#include "qvalueaxis.h" #include <QtQuick/QQuickWindow> #include <QtGui/QOpenGLFramebufferObject> @@ -128,9 +129,13 @@ QSGNode *DeclarativeBars::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData } if (m_cachedState->m_isTickCountSet) { - m_shared->setTickCount(GLint(m_cachedState->m_tickCount), - GLfloat(m_cachedState->m_tickStep), - GLfloat(m_cachedState->m_tickMin)); + // TODO needs proper axis support on QML side, too + QValueAxis *axis = static_cast<QValueAxis *>(m_shared->axisY()); + if (axis) { + axis->setTickCount(m_cachedState->m_tickCount); + axis->setRange(m_cachedState->m_tickMin, + (m_cachedState->m_tickCount * m_cachedState->m_tickStep)); + } m_cachedState->m_isTickCountSet = false; } @@ -253,6 +258,7 @@ bool DeclarativeBars::isBackgroundVisible() return m_shared->backgroundEnabled(); } +// TODO needs proper axis support also in QML void DeclarativeBars::setTickCount(int tickCount, qreal step, qreal minimum) { m_cachedState->m_isTickCountSet = true; |