diff options
24 files changed, 332 insertions, 41 deletions
diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc index 3dc5beea..b26f0818 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc @@ -407,3 +407,22 @@ * \sa Scene3D::graphPositionQuery */ +/*! + * \qmlproperty real AbstractGraph3D::margin + * \since QtDataVisualization 1.2 + * + * This property contains the absolute value used for graph margin. The graph margin is the space + * left between the edge of the plottable graph area and the edge of the graph background. + * If the margin value is negative, the margins are determined automatically and can vary according + * to size of the items in the series and the type of the graph. + * The value is interpreted as a fraction of Y-axis range, provided the graph aspect ratios have + * not beed changed from the defaults. + * Defaults to \c{-1.0}. + * + * \note Having smaller than the automatically determined margin on scatter graph can cause + * the scatter items at the edges of the graph to overlap with the graph background. + * + * \note On scatter and surface graphs, if the margin is comparatively small to the axis label + * size, the positions of the edge labels of the axes are adjusted to avoid overlap with + * the edge labels of the neighboring axes. + */ diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index 44f1208b..27d01029 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -61,7 +61,8 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen m_currentFps(0.0), m_clickedType(QAbstract3DGraph::ElementNone), m_selectedLabelIndex(-1), - m_selectedCustomItemIndex(-1) + m_selectedCustomItemIndex(-1), + m_margin(-1.0) { if (!m_scene) m_scene = new Q3DScene; @@ -482,6 +483,11 @@ void Abstract3DController::synchDataToRenderer() m_changeTracker.axisZTitleFixedChanged = false; } + if (m_changeTracker.marginChanged) { + m_renderer->updateMargin(float(m_margin)); + m_changeTracker.marginChanged = false; + } + if (m_changedSeriesList.size()) { m_renderer->modifiedSeriesList(m_changedSeriesList); m_changedSeriesList.clear(); @@ -1685,5 +1691,20 @@ QVector3D Abstract3DController::queriedGraphPosition() const return m_queriedGraphPosition; } +void Abstract3DController::setMargin(qreal margin) +{ + if (m_margin != margin) { + m_margin = margin; + m_changeTracker.marginChanged = true; + emit marginChanged(margin); + emitNeedRender(); + } +} + +qreal Abstract3DController::margin() const +{ + return m_margin; +} + QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index 6db774bd..4d7b36a3 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -96,6 +96,7 @@ struct Abstract3DChangeBitField { bool radialLabelOffsetChanged : 1; bool reflectionChanged : 1; bool reflectivityChanged : 1; + bool marginChanged : 1; Abstract3DChangeBitField() : themeChanged(true), @@ -144,7 +145,8 @@ struct Abstract3DChangeBitField { polarChanged(true), radialLabelOffsetChanged(true), reflectionChanged(true), - reflectivityChanged(true) + reflectivityChanged(true), + marginChanged(true) { } }; @@ -208,6 +210,7 @@ protected: QAbstract3DGraph::ElementType m_clickedType; int m_selectedLabelIndex; int m_selectedCustomItemIndex; + qreal m_margin; explicit Abstract3DController(QRect initialViewport, Q3DScene *scene, QObject *parent = 0); @@ -310,6 +313,9 @@ public: QVector3D queriedGraphPosition() const; + void setMargin(qreal margin); + qreal margin() const; + void emitNeedRender(); virtual void clearSelection() = 0; @@ -394,6 +400,7 @@ signals: void reflectivityChanged(qreal reflectivity); void localeChanged(const QLocale &locale); void queriedGraphPositionChanged(const QVector3D &data); + void marginChanged(qreal margin); protected: virtual QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation); diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index ab086b5f..aaf5418f 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -92,8 +92,12 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) m_zRightAngleRotationNeg(QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, -90.0f)), m_xFlipRotation(QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -180.0f)), m_zFlipRotation(QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, -180.0f)), + m_requestedMargin(-1.0f), m_vBackgroundMargin(0.1f), m_hBackgroundMargin(0.1f), + m_scaleXWithBackground(0.0f), + m_scaleYWithBackground(0.0f), + m_scaleZWithBackground(0.0f), m_oldCameraTarget(QVector3D(2000.0f, 2000.0f, 2000.0f)), // Just random invalid target m_reflectionEnabled(false), m_reflectivity(0.5) @@ -459,6 +463,11 @@ void Abstract3DRenderer::updateRadialLabelOffset(float offset) m_radialLabelOffset = offset; } +void Abstract3DRenderer::updateMargin(float margin) +{ + m_requestedMargin = margin; +} + void Abstract3DRenderer::updateOptimizationHint(QAbstract3DGraph::OptimizationHints hint) { m_cachedOptimizationHint = hint; diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index 6d134ee3..997362d5 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -136,6 +136,7 @@ public: virtual void updateHorizontalAspectRatio(float ratio); virtual void updatePolar(bool enable); virtual void updateRadialLabelOffset(float offset); + virtual void updateMargin(float margin); virtual QVector3D convertPositionToTranslation(const QVector3D &position, bool isAbsolute) = 0; @@ -297,8 +298,12 @@ protected: QQuaternion m_xFlipRotation; QQuaternion m_zFlipRotation; + float m_requestedMargin; float m_vBackgroundMargin; float m_hBackgroundMargin; + float m_scaleXWithBackground; + float m_scaleYWithBackground; + float m_scaleZWithBackground; QVector3D m_oldCameraTarget; diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index 2d394d57..47c9b84c 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -1702,7 +1702,8 @@ void Bars3DRenderer::drawBackground(GLfloat backgroundRotation, QMatrix4x4 MVPMatrix; QMatrix4x4 itModelMatrix; - QVector3D backgroundScaler(m_xScaleFactor, 1.0f, m_zScaleFactor); + QVector3D backgroundScaler(m_scaleXWithBackground, m_scaleYWithBackground, + m_scaleZWithBackground); QVector4D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor()); if (m_reflectionEnabled) backgroundColor.setW(backgroundColor.w() * m_reflectivity); @@ -1845,7 +1846,7 @@ void Bars3DRenderer::drawGridLines(const QMatrix4x4 &depthProjectionViewMatrix, if (m_yFlipped) yFloorLinePosition = -yFloorLinePosition; - QVector3D gridLineScaler(m_xScaleFactor, gridLineWidth, gridLineWidth); + QVector3D gridLineScaler(m_scaleXWithBackground, gridLineWidth, gridLineWidth); if (m_yFlipped) lineRotation = m_xRightAngleRotation; @@ -1894,7 +1895,7 @@ void Bars3DRenderer::drawGridLines(const QMatrix4x4 &depthProjectionViewMatrix, #if defined(QT_OPENGL_ES_2) lineRotation = m_yRightAngleRotation; #endif - gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, m_zScaleFactor); + gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, m_scaleZWithBackground); for (GLfloat bar = 0.0f; bar <= m_cachedColumnCount; bar++) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -1936,11 +1937,11 @@ void Bars3DRenderer::drawGridLines(const QMatrix4x4 &depthProjectionViewMatrix, // Wall lines: back wall int gridLineCount = m_axisCacheY.gridLineCount(); - GLfloat zWallLinePosition = -m_zScaleFactor + gridLineOffset; + GLfloat zWallLinePosition = -m_scaleZWithBackground + gridLineOffset; if (m_zFlipped) zWallLinePosition = -zWallLinePosition; - gridLineScaler = QVector3D(m_xScaleFactor, gridLineWidth, gridLineWidth); + gridLineScaler = QVector3D(m_scaleXWithBackground, gridLineWidth, gridLineWidth); for (int line = 0; line < gridLineCount; line++) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -1981,7 +1982,7 @@ void Bars3DRenderer::drawGridLines(const QMatrix4x4 &depthProjectionViewMatrix, } // Wall lines: side wall - GLfloat xWallLinePosition = -m_xScaleFactor + gridLineOffset; + GLfloat xWallLinePosition = -m_scaleXWithBackground + gridLineOffset; if (m_xFlipped) xWallLinePosition = -xWallLinePosition; @@ -1990,7 +1991,7 @@ void Bars3DRenderer::drawGridLines(const QMatrix4x4 &depthProjectionViewMatrix, else lineRotation = m_yRightAngleRotation; - gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, m_zScaleFactor); + gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, m_scaleZWithBackground); for (int line = 0; line < gridLineCount; line++) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -2064,8 +2065,8 @@ void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamer int labelCount = m_axisCacheY.labelCount(); GLfloat labelMarginXTrans = labelMargin; GLfloat labelMarginZTrans = labelMargin; - GLfloat labelXTrans = m_xScaleFactor; - GLfloat labelZTrans = m_zScaleFactor; + GLfloat labelXTrans = m_scaleXWithBackground; + GLfloat labelZTrans = m_scaleZWithBackground; QVector3D backLabelRotation(0.0f, -90.0f, 0.0f); QVector3D sideLabelRotation(0.0f, 0.0f, 0.0f); Qt::AlignmentFlag backAlignment = (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight; @@ -2169,10 +2170,8 @@ void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamer fractionCamY = activeCamera->yRotation() * labelAngleFraction; fractionCamX = activeCamera->xRotation() * labelAngleFraction; GLfloat labelYAdjustment = 0.005f; - GLfloat scaledRowWidth = m_xScaleFactor; - GLfloat scaledColumnDepth = m_zScaleFactor; - GLfloat colPosValue = scaledRowWidth + labelMargin; - GLfloat rowPosValue = scaledColumnDepth + labelMargin; + GLfloat colPosValue = m_scaleXWithBackground + labelMargin; + GLfloat rowPosValue = m_scaleZWithBackground + labelMargin; GLfloat rowPos = 0.0f; GLfloat colPos = 0.0f; Qt::AlignmentFlag alignment = (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight; @@ -2599,6 +2598,18 @@ void Bars3DRenderer::calculateSceneScalingFactors() m_xScaleFactor = m_rowWidth / m_scaleFactor; m_zScaleFactor = m_columnDepth / m_scaleFactor; + if (m_requestedMargin < 0.0f) { + m_hBackgroundMargin = 0.0f; + m_vBackgroundMargin = 0.0f; + } else { + m_hBackgroundMargin = m_requestedMargin; + m_vBackgroundMargin = m_requestedMargin; + } + + m_scaleXWithBackground = m_xScaleFactor + m_hBackgroundMargin; + m_scaleYWithBackground = 1.0f + m_vBackgroundMargin; + m_scaleZWithBackground = m_zScaleFactor + m_hBackgroundMargin; + updateCameraViewport(); updateCustomItemPositions(); } @@ -2858,4 +2869,10 @@ void Bars3DRenderer::updateFloorLevel(float level) calculateHeightAdjustment(); } +void Bars3DRenderer::updateMargin(float margin) +{ + Abstract3DRenderer::updateMargin(margin); + calculateSceneScalingFactors(); +} + QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index 92dae311..fea4e52e 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -118,6 +118,7 @@ public: void updateAspectRatio(float ratio); void updateFloorLevel(float level); + void updateMargin(float margin); protected: virtual void initializeOpenGL(); diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp index 8473f708..9fb71d59 100644 --- a/src/datavisualization/engine/qabstract3dgraph.cpp +++ b/src/datavisualization/engine/qabstract3dgraph.cpp @@ -821,6 +821,35 @@ QVector3D QAbstract3DGraph::queriedGraphPosition() const } /*! + * \property QAbstract3DGraph::margin + * \since QtDataVisualization 1.2 + * + * This property contains the absolute value used for graph margin. The graph margin is the space + * left between the edge of the plottable graph area and the edge of the graph background. + * If the margin value is negative, the margins are determined automatically and can vary according + * to size of the items in the series and the type of the graph. + * The value is interpreted as a fraction of Y-axis range, provided the graph aspect ratios have + * not beed changed from the defaults. + * Defaults to \c{-1.0}. + * + * \note Having smaller than the automatically determined margin on scatter graph can cause + * the scatter items at the edges of the graph to overlap with the graph background. + * + * \note On scatter and surface graphs, if the margin is comparatively small to the axis label + * size, the positions of the edge labels of the axes are adjusted to avoid overlap with + * the edge labels of the neighboring axes. + */ +void QAbstract3DGraph::setMargin(qreal margin) +{ + d_ptr->m_visualController->setMargin(margin); +} + +qreal QAbstract3DGraph::margin() const +{ + return d_ptr->m_visualController->margin(); +} + +/*! * \internal */ bool QAbstract3DGraph::event(QEvent *event) @@ -985,6 +1014,8 @@ void QAbstract3DGraphPrivate::setVisualController(Abstract3DController *controll &QAbstract3DGraph::localeChanged); QObject::connect(m_visualController, &Abstract3DController::queriedGraphPositionChanged, q_ptr, &QAbstract3DGraph::queriedGraphPositionChanged); + QObject::connect(m_visualController, &Abstract3DController::marginChanged, q_ptr, + &QAbstract3DGraph::marginChanged); } void QAbstract3DGraphPrivate::handleDevicePixelRatioChange() diff --git a/src/datavisualization/engine/qabstract3dgraph.h b/src/datavisualization/engine/qabstract3dgraph.h index 79eb3893..a0c26a42 100644 --- a/src/datavisualization/engine/qabstract3dgraph.h +++ b/src/datavisualization/engine/qabstract3dgraph.h @@ -58,6 +58,7 @@ class QT_DATAVISUALIZATION_EXPORT QAbstract3DGraph : public QWindow, protected Q Q_PROPERTY(qreal reflectivity READ reflectivity WRITE setReflectivity NOTIFY reflectivityChanged) Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged) Q_PROPERTY(QVector3D queriedGraphPosition READ queriedGraphPosition NOTIFY queriedGraphPositionChanged) + Q_PROPERTY(qreal margin READ margin WRITE setMargin NOTIFY marginChanged) protected: explicit QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format, @@ -179,6 +180,9 @@ public: QVector3D queriedGraphPosition() const; + void setMargin(qreal margin); + qreal margin() const; + protected: bool event(QEvent *event); void resizeEvent(QResizeEvent *event); @@ -209,6 +213,7 @@ signals: void reflectivityChanged(qreal reflectivity); void localeChanged(const QLocale &locale); void queriedGraphPositionChanged(const QVector3D &data); + void marginChanged(qreal margin); private: Q_DISABLE_COPY(QAbstract3DGraph) diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index d1dca8c6..3bae9879 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -60,9 +60,6 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) m_scaleX(0.0f), m_scaleY(0.0f), m_scaleZ(0.0f), - m_scaleXWithBackground(0.0f), - m_scaleYWithBackground(0.0f), - m_scaleZWithBackground(0.0f), m_selectedItemIndex(Scatter3DController::invalidSelectionIndex()), m_selectedSeriesCache(0), m_oldSelectedSeriesCache(0), @@ -399,6 +396,12 @@ void Scatter3DRenderer::updateOptimizationHint(QAbstract3DGraph::OptimizationHin #endif } +void Scatter3DRenderer::updateMargin(float margin) +{ + Abstract3DRenderer::updateMargin(margin); + calculateSceneScalingFactors(); +} + void Scatter3DRenderer::resetClickedStatus() { m_clickedIndex = Scatter3DController::invalidSelectionIndex(); @@ -1689,6 +1692,23 @@ void Scatter3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa } else { labelTrans.setZ(m_axisCacheZ.labelPosition(label)); } + if (label == 0 || label == (labelCount - 1)) { + // If the margin is small, adjust the position of the edge labels to avoid overlapping + // with labels of the other axes. + float scaleFactor = m_drawer->scaledFontSize() / axisLabelItem.size().height(); + float labelOverlap = qAbs(labelTrans.z()) + + (scaleFactor * axisLabelItem.size().height() / 2.0f) + - m_scaleZWithBackground + labelMargin; + // No need to adjust quite as much on the front edges + if (label != startIndex) + labelOverlap /= 2.0f; + if (labelOverlap > 0.0f) { + if (label == 0) + labelTrans.setZ(labelTrans.z() - labelOverlap); + else + labelTrans.setZ(labelTrans.z() + labelOverlap); + } + } m_dummyRenderItem.setTranslation(labelTrans); if (drawSelection) { @@ -1860,8 +1880,25 @@ void Scatter3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa } else { labelTrans.setX(m_axisCacheX.labelPosition(label)); } - m_dummyRenderItem.setTranslation(labelTrans); const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(label); + if (label == 0 || label == (labelCount - 1)) { + // If the margin is small, adjust the position of the edge labels to avoid overlapping + // with labels of the other axes. + float scaleFactor = m_drawer->scaledFontSize() / axisLabelItem.size().height(); + float labelOverlap = qAbs(labelTrans.x()) + + (scaleFactor * axisLabelItem.size().height() / 2.0f) + - m_scaleXWithBackground + labelMargin; + // No need to adjust quite as much on the front edges + if (label != startIndex) + labelOverlap /= 2.0f; + if (labelOverlap > 0.0f) { + if (label == 0) + labelTrans.setX(labelTrans.x() + labelOverlap); + else + labelTrans.setX(labelTrans.x() - labelOverlap); + } + } + m_dummyRenderItem.setTranslation(labelTrans); if (drawSelection) { QVector4D labelColor = QVector4D(0.0f, label / 255.0f, 0.0f, @@ -1965,7 +2002,7 @@ void Scatter3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa float offsetValue = 0.0f; for (int label = startIndex; label != endIndex; label = label + indexStep) { const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(label); - const float labelYTrans = m_axisCacheY.labelPosition(label); + float labelYTrans = m_axisCacheY.labelPosition(label); glPolygonOffset(offsetValue++ / -10.0f, 1.0f); @@ -1975,6 +2012,21 @@ void Scatter3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa shader->setUniformValue(shader->color(), labelColor); } + if (label == startIndex) { + // If the margin is small, adjust the position of the edge label to avoid + // overlapping with labels of the other axes. + float scaleFactor = m_drawer->scaledFontSize() / axisLabelItem.size().height(); + float labelOverlap = qAbs(labelYTrans) + + (scaleFactor * axisLabelItem.size().height() / 2.0f) + - m_scaleYWithBackground + labelMargin; + if (labelOverlap > 0.0f) { + if (label == 0) + labelYTrans += labelOverlap; + else + labelYTrans -= labelOverlap; + } + } + // Back wall labelTransBack.setY(labelYTrans); m_dummyRenderItem.setTranslation(labelTransBack); @@ -2121,11 +2173,16 @@ void Scatter3DRenderer::calculateTranslation(ScatterRenderItem &item) void Scatter3DRenderer::calculateSceneScalingFactors() { - if (m_maxItemSize > defaultMaxSize) - m_hBackgroundMargin = m_maxItemSize / itemScaler; - else - m_hBackgroundMargin = defaultMaxSize; - m_vBackgroundMargin = m_hBackgroundMargin; + if (m_requestedMargin < 0.0f) { + if (m_maxItemSize > defaultMaxSize) + m_hBackgroundMargin = m_maxItemSize / itemScaler; + else + m_hBackgroundMargin = defaultMaxSize; + m_vBackgroundMargin = m_hBackgroundMargin; + } else { + m_hBackgroundMargin = m_requestedMargin; + m_vBackgroundMargin = m_requestedMargin; + } if (m_polarGraph) { float polarMargin = calculatePolarBackgroundMargin(); m_hBackgroundMargin = qMax(m_hBackgroundMargin, polarMargin); diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index d8908e59..d882d59f 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -70,9 +70,6 @@ private: float m_scaleX; float m_scaleY; float m_scaleZ; - float m_scaleXWithBackground; - float m_scaleYWithBackground; - float m_scaleZWithBackground; int m_selectedItemIndex; ScatterSeriesRenderCache *m_selectedSeriesCache; ScatterSeriesRenderCache *m_oldSelectedSeriesCache; @@ -99,6 +96,7 @@ public: void updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientation orientation, bool visible); void updateOptimizationHint(QAbstract3DGraph::OptimizationHints hint); + void updateMargin(float margin); QVector3D convertPositionToTranslation(const QVector3D &position, bool isAbsolute); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 3d39a71d..02add48f 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -53,9 +53,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_scaleX(0.0f), m_scaleY(0.0f), m_scaleZ(0.0f), - m_scaleXWithBackground(0.0f), - m_scaleYWithBackground(0.0f), - m_scaleZWithBackground(0.0f), m_depthModelTexture(0), m_depthFrameBuffer(0), m_selectionFrameBuffer(0), @@ -2089,6 +2086,23 @@ void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa } else { labelTrans.setZ(m_axisCacheZ.labelPosition(label)); } + if (label == 0 || label == (labelCount - 1)) { + // If the margin is small, adjust the position of the edge labels to avoid overlapping + // with labels of the other axes. + float scaleFactor = m_drawer->scaledFontSize() / axisLabelItem.size().height(); + float labelOverlap = qAbs(labelTrans.z()) + + (scaleFactor * axisLabelItem.size().height() / 2.0f) + - m_scaleZWithBackground + labelMargin; + // No need to adjust quite as much on the front edges + if (label != startIndex) + labelOverlap /= 2.0f; + if (labelOverlap > 0.0f) { + if (label == 0) + labelTrans.setZ(labelTrans.z() - labelOverlap); + else + labelTrans.setZ(labelTrans.z() + labelOverlap); + } + } m_dummyRenderItem.setTranslation(labelTrans); if (drawSelection) { @@ -2264,8 +2278,25 @@ void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa } else { labelTrans.setX(m_axisCacheX.labelPosition(label)); } - m_dummyRenderItem.setTranslation(labelTrans); const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(label); + if (label == 0 || label == (labelCount - 1)) { + // If the margin is small, adjust the position of the edge labels to avoid overlapping + // with labels of the other axes. + float scaleFactor = m_drawer->scaledFontSize() / axisLabelItem.size().height(); + float labelOverlap = qAbs(labelTrans.x()) + + (scaleFactor * axisLabelItem.size().height() / 2.0f) + - m_scaleXWithBackground + labelMargin; + // No need to adjust quite as much on the front edges + if (label != startIndex) + labelOverlap /= 2.0f; + if (labelOverlap > 0.0f) { + if (label == 0) + labelTrans.setX(labelTrans.x() + labelOverlap); + else + labelTrans.setX(labelTrans.x() - labelOverlap); + } + } + m_dummyRenderItem.setTranslation(labelTrans); if (drawSelection) { QVector4D labelColor = QVector4D(0.0f, label / 255.0f, 0.0f, @@ -2368,7 +2399,7 @@ void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa float offsetValue = 0.0f; for (int label = startIndex; label != endIndex; label = label + indexStep) { const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(label); - const float labelYTrans = m_axisCacheY.labelPosition(label); + float labelYTrans = m_axisCacheY.labelPosition(label); glPolygonOffset(offsetValue++ / -10.0f, 1.0f); @@ -2378,6 +2409,21 @@ void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa shader->setUniformValue(shader->color(), labelColor); } + if (label == startIndex) { + // If the margin is small, adjust the position of the edge label to avoid + // overlapping with labels of the other axes. + float scaleFactor = m_drawer->scaledFontSize() / axisLabelItem.size().height(); + float labelOverlap = qAbs(labelYTrans) + + (scaleFactor * axisLabelItem.size().height() / 2.0f) + - m_scaleYWithBackground + labelMargin; + if (labelOverlap > 0.0f) { + if (label == 0) + labelYTrans += labelOverlap; + else + labelYTrans -= labelOverlap; + } + } + // Back wall labelTransBack.setY(labelYTrans); m_dummyRenderItem.setTranslation(labelTransBack); @@ -2514,9 +2560,15 @@ void Surface3DRenderer::idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a void Surface3DRenderer::calculateSceneScalingFactors() { - // Margin for background (0.10 make it 10% larger to avoid + // Margin for background (the default 0.10 makes it 10% larger to avoid // selection ball being drawn inside background) - m_hBackgroundMargin = 0.1f; + if (m_requestedMargin < 0.0f) { + m_hBackgroundMargin = 0.1f; + m_vBackgroundMargin = 0.1f; + } else { + m_hBackgroundMargin = m_requestedMargin; + m_vBackgroundMargin = m_requestedMargin; + } if (m_polarGraph) { float polarMargin = calculatePolarBackgroundMargin(); m_hBackgroundMargin = qMax(m_hBackgroundMargin, polarMargin); @@ -3032,4 +3084,10 @@ void Surface3DRenderer::updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientati calculateSceneScalingFactors(); } +void Surface3DRenderer::updateMargin(float margin) +{ + Abstract3DRenderer::updateMargin(margin); + calculateSceneScalingFactors(); +} + QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index cba1b959..b02bd456 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -61,9 +61,6 @@ private: float m_scaleX; float m_scaleY; float m_scaleZ; - float m_scaleXWithBackground; - float m_scaleYWithBackground; - float m_scaleZWithBackground; GLuint m_depthModelTexture; GLuint m_depthFrameBuffer; GLuint m_selectionFrameBuffer; @@ -104,6 +101,7 @@ public: const QStringList &labels); void updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientation orientation, bool visible); + void updateMargin(float margin); void render(GLuint defaultFboHandle = 0); diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp index 9206973a..6c6cdb90 100644 --- a/src/datavisualizationqml2/abstractdeclarative.cpp +++ b/src/datavisualizationqml2/abstractdeclarative.cpp @@ -343,6 +343,8 @@ void AbstractDeclarative::setSharedController(Abstract3DController *controller) &AbstractDeclarative::localeChanged); QObject::connect(m_controller.data(), &Abstract3DController::queriedGraphPositionChanged, this, &AbstractDeclarative::queriedGraphPositionChanged); + QObject::connect(m_controller.data(), &Abstract3DController::marginChanged, this, + &AbstractDeclarative::marginChanged); } void AbstractDeclarative::activateOpenGLContext(QQuickWindow *window) @@ -803,6 +805,16 @@ QVector3D AbstractDeclarative::queriedGraphPosition() const return m_controller->queriedGraphPosition(); } +void AbstractDeclarative::setMargin(qreal margin) +{ + m_controller->setMargin(margin); +} + +qreal AbstractDeclarative::margin() const +{ + return m_controller->margin(); +} + void AbstractDeclarative::windowDestroyed(QObject *obj) { // Remove destroyed window from window lists diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h index 8dc260c2..04db21f4 100644 --- a/src/datavisualizationqml2/abstractdeclarative_p.h +++ b/src/datavisualizationqml2/abstractdeclarative_p.h @@ -79,6 +79,7 @@ class AbstractDeclarative : public QQuickItem Q_PROPERTY(qreal reflectivity READ reflectivity WRITE setReflectivity NOTIFY reflectivityChanged REVISION 2) Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged REVISION 2) Q_PROPERTY(QVector3D queriedGraphPosition READ queriedGraphPosition NOTIFY queriedGraphPositionChanged REVISION 2) + Q_PROPERTY(qreal margin READ margin WRITE setMargin NOTIFY marginChanged REVISION 2) public: enum SelectionFlag { @@ -220,6 +221,9 @@ public: QVector3D queriedGraphPosition() const; + void setMargin(qreal margin); + qreal margin() const; + public slots: virtual void handleAxisXChanged(QAbstract3DAxis *axis) = 0; virtual void handleAxisYChanged(QAbstract3DAxis *axis) = 0; @@ -264,6 +268,7 @@ signals: Q_REVISION(2) void reflectivityChanged(qreal reflectivity); Q_REVISION(2) void localeChanged(const QLocale &locale); Q_REVISION(2) void queriedGraphPositionChanged(const QVector3D &data); + Q_REVISION(2) void marginChanged(qreal margin); private: QPointer<Abstract3DController> m_controller; diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp index d7b23719..6be5e66d 100644 --- a/tests/barstest/chart.cpp +++ b/tests/barstest/chart.cpp @@ -1531,6 +1531,12 @@ void GraphModifier::setFloorLevel(int value) qDebug() << "Floor level:" << value; } +void GraphModifier::setGraphMargin(int value) +{ + m_graph->setMargin(qreal(value) / 100.0); + qDebug() << "Setting margin:" << m_graph->margin() << value; +} + void GraphModifier::populateFlatSeries(QBar3DSeries *series, int rows, int columns, float value) { QBarDataArray *dataArray = new QBarDataArray; diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h index 93abbfa4..9713d06c 100644 --- a/tests/barstest/chart.h +++ b/tests/barstest/chart.h @@ -126,6 +126,7 @@ public slots: void setCameraTargetY(int value); void setCameraTargetZ(int value); void setFloorLevel(int value); + void setGraphMargin(int value); signals: void shadowQualityChanged(int quality); diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp index cffbf4b4..a468cb57 100644 --- a/tests/barstest/main.cpp +++ b/tests/barstest/main.cpp @@ -368,6 +368,11 @@ int main(int argc, char **argv) cameraTargetSliderZ->setValue(0); cameraTargetSliderZ->setMaximum(100); + QSlider *marginSlider = new QSlider(Qt::Horizontal, widget); + marginSlider->setMinimum(-1); + marginSlider->setValue(-1); + marginSlider->setMaximum(100); + vLayout->addWidget(addSeriesButton, 0, Qt::AlignTop); vLayout->addWidget(addDataButton, 0, Qt::AlignTop); vLayout->addWidget(addMultiDataButton, 0, Qt::AlignTop); @@ -447,7 +452,9 @@ int main(int argc, char **argv) vLayout3->addWidget(reflectivitySlider, 0, Qt::AlignTop); vLayout3->addWidget(toggleCustomItemButton, 0, Qt::AlignTop); vLayout3->addWidget(new QLabel(QStringLiteral("Adjust floor level")), 0, Qt::AlignTop); - vLayout3->addWidget(floorLevelSlider, 1, Qt::AlignTop); + vLayout3->addWidget(floorLevelSlider, 0, Qt::AlignTop); + vLayout3->addWidget(new QLabel(QStringLiteral("Adjust margin")), 0, Qt::AlignTop); + vLayout3->addWidget(marginSlider, 1, Qt::AlignTop); widget->show(); @@ -584,6 +591,8 @@ int main(int argc, char **argv) &GraphModifier::setReflectivity); QObject::connect(floorLevelSlider, &QSlider::valueChanged, modifier, &GraphModifier::setFloorLevel); + QObject::connect(marginSlider, &QSlider::valueChanged, modifier, + &GraphModifier::setGraphMargin); QObject::connect(toggleCustomItemButton, &QPushButton::clicked, modifier, &GraphModifier::toggleCustomItem); diff --git a/tests/scattertest/main.cpp b/tests/scattertest/main.cpp index 116a4dc2..811c7f3b 100644 --- a/tests/scattertest/main.cpp +++ b/tests/scattertest/main.cpp @@ -294,6 +294,11 @@ int main(int argc, char **argv) cameraTargetSliderZ->setValue(0); cameraTargetSliderZ->setMaximum(100); + QSlider *marginSlider = new QSlider(Qt::Horizontal, widget); + marginSlider->setMinimum(-1); + marginSlider->setValue(-1); + marginSlider->setMaximum(100); + vLayout->addWidget(themeButton, 0, Qt::AlignTop); vLayout->addWidget(labelButton, 0, Qt::AlignTop); vLayout->addWidget(styleButton, 0, Qt::AlignTop); @@ -357,7 +362,9 @@ int main(int argc, char **argv) vLayout3->addWidget(new QLabel(QStringLiteral("Camera target")), 0, Qt::AlignTop); vLayout3->addWidget(cameraTargetSliderX, 0, Qt::AlignTop); vLayout3->addWidget(cameraTargetSliderY, 0, Qt::AlignTop); - vLayout3->addWidget(cameraTargetSliderZ, 1, Qt::AlignTop); + vLayout3->addWidget(cameraTargetSliderZ, 0, Qt::AlignTop); + vLayout3->addWidget(new QLabel(QStringLiteral("Adjust margin")), 0, Qt::AlignTop); + vLayout3->addWidget(marginSlider, 1, Qt::AlignTop); ScatterDataModifier *modifier = new ScatterDataModifier(chart); @@ -469,6 +476,8 @@ int main(int argc, char **argv) &ScatterDataModifier::setCameraTargetY); QObject::connect(cameraTargetSliderZ, &QSlider::valueChanged, modifier, &ScatterDataModifier::setCameraTargetZ); + QObject::connect(marginSlider, &QSlider::valueChanged, modifier, + &ScatterDataModifier::setGraphMargin); modifier->setFpsLabel(fpsLabel); diff --git a/tests/scattertest/scatterchart.cpp b/tests/scattertest/scatterchart.cpp index a45c090b..c7b93c32 100644 --- a/tests/scattertest/scatterchart.cpp +++ b/tests/scattertest/scatterchart.cpp @@ -1023,6 +1023,12 @@ void ScatterDataModifier::setCameraTargetZ(int value) qDebug() << "m_cameraTarget:" << m_cameraTarget; } +void ScatterDataModifier::setGraphMargin(int value) +{ + m_chart->setMargin(qreal(value) / 100.0); + qDebug() << "Setting margin:" << m_chart->margin() << value; +} + void ScatterDataModifier::changeShadowQuality(int quality) { QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality); diff --git a/tests/scattertest/scatterchart.h b/tests/scattertest/scatterchart.h index 1a97c5f0..a2b0f58e 100644 --- a/tests/scattertest/scatterchart.h +++ b/tests/scattertest/scatterchart.h @@ -101,6 +101,7 @@ public slots: void setCameraTargetX(int value); void setCameraTargetY(int value); void setCameraTargetZ(int value); + void setGraphMargin(int value); signals: void shadowQualityChanged(int quality); diff --git a/tests/surfacetest/graphmodifier.cpp b/tests/surfacetest/graphmodifier.cpp index 1a069cf4..2d0e9357 100644 --- a/tests/surfacetest/graphmodifier.cpp +++ b/tests/surfacetest/graphmodifier.cpp @@ -836,6 +836,12 @@ void GraphModifier::setCameraTargetZ(int value) qDebug() << "m_cameraTarget:" << m_cameraTarget; } +void GraphModifier::setGraphMargin(int value) +{ + m_graph->setMargin(qreal(value) / 100.0); + qDebug() << "Setting margin:" << m_graph->margin() << value; +} + void GraphModifier::resetArrayAndSliders(QSurfaceDataArray *array, float minZ, float maxZ, float minX, float maxX) { m_axisMinSliderX->setValue(minX); diff --git a/tests/surfacetest/graphmodifier.h b/tests/surfacetest/graphmodifier.h index d1c77940..f85fbc15 100644 --- a/tests/surfacetest/graphmodifier.h +++ b/tests/surfacetest/graphmodifier.h @@ -137,6 +137,7 @@ public slots: void setCameraTargetX(int value); void setCameraTargetY(int value); void setCameraTargetZ(int value); + void setGraphMargin(int value); private: void fillSeries(); diff --git a/tests/surfacetest/main.cpp b/tests/surfacetest/main.cpp index 9e14c665..d1328e4e 100644 --- a/tests/surfacetest/main.cpp +++ b/tests/surfacetest/main.cpp @@ -425,6 +425,11 @@ int main(int argc, char *argv[]) cameraTargetSliderZ->setValue(0); cameraTargetSliderZ->setMaximum(100); + QSlider *marginSlider = new QSlider(Qt::Horizontal, widget); + marginSlider->setMinimum(-1); + marginSlider->setValue(-1); + marginSlider->setMaximum(100); + // Add controls to the layout #ifdef MULTI_SERIES vLayout->addWidget(series1CB); @@ -491,7 +496,9 @@ int main(int argc, char *argv[]) vLayout2->addWidget(new QLabel(QStringLiteral("Camera target"))); vLayout2->addWidget(cameraTargetSliderX); vLayout2->addWidget(cameraTargetSliderY); - vLayout2->addWidget(cameraTargetSliderZ, 1, Qt::AlignTop); + vLayout2->addWidget(cameraTargetSliderZ); + vLayout2->addWidget(new QLabel(QStringLiteral("Adjust margin")), 0, Qt::AlignTop); + vLayout2->addWidget(marginSlider, 1, Qt::AlignTop); vLayout3->addWidget(labelButton); vLayout3->addWidget(meshButton); @@ -707,6 +714,8 @@ int main(int argc, char *argv[]) &GraphModifier::setCameraTargetY); QObject::connect(cameraTargetSliderZ, &QSlider::valueChanged, modifier, &GraphModifier::setCameraTargetZ); + QObject::connect(marginSlider, &QSlider::valueChanged, modifier, + &GraphModifier::setGraphMargin); #ifdef MULTI_SERIES modifier->setSeries1CB(series1CB); |