| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the Qt Data Visualization module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 or (at your option) any later version |
| ** approved by the KDE Free Qt Foundation. The licenses are as published by |
| ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "graphmodifier.h" |
| #include <QtDataVisualization/QValue3DAxis> |
| #include <QtDataVisualization/QSurfaceDataProxy> |
| #include <QtDataVisualization/QSurface3DSeries> |
| #include <QtDataVisualization/Q3DTheme> |
| #include <QtDataVisualization/Q3DInputHandler> |
| |
| #include <qmath.h> |
| #include <qrandom.h> |
| #include <QLinearGradient> |
| #include <QDebug> |
| #include <QComboBox> |
| #ifndef QT_NO_CURSOR |
| #include <QtGui/QCursor> |
| #endif |
| using namespace QtDataVisualization; |
| |
| //#define JITTER_PLANE |
| //#define WONKY_PLANE |
| |
| GraphModifier::GraphModifier(Q3DSurface *graph, QWidget *parentWidget) |
| : m_graph(graph), |
| m_series1(new QSurface3DSeries), |
| m_series2(new QSurface3DSeries), |
| m_series3(new QSurface3DSeries), |
| m_series4(new QSurface3DSeries), |
| m_gridSliderX(0), |
| m_gridSliderZ(0), |
| m_axisRangeSliderX(0), |
| m_axisRangeSliderZ(0), |
| m_axisMinSliderX(0), |
| m_axisMinSliderZ(0), |
| m_xCount(24), |
| m_zCount(24), |
| m_activeSample(0), |
| m_fontSize(40), |
| m_rangeX(34.0), |
| m_rangeY(16.0), |
| m_rangeZ(34.0), |
| m_minX(-17.0), |
| m_minY(-8.0), |
| m_minZ(-17.0), |
| m_addRowCounter(m_zCount), |
| m_insertTestZPos(0), |
| m_insertTestIndexPos(1), |
| m_planeArray(0), |
| m_theSeries(new QSurface3DSeries), |
| m_drawMode(QSurface3DSeries::DrawSurfaceAndWireframe), |
| m_drawMode2(QSurface3DSeries::DrawSurfaceAndWireframe), |
| m_drawMode3(QSurface3DSeries::DrawSurfaceAndWireframe), |
| m_drawMode4(QSurface3DSeries::DrawSurfaceAndWireframe), |
| m_offset(4.0f), |
| m_parentWidget(parentWidget), |
| m_ascendingX(true), |
| m_ascendingZ(true) |
| { |
| m_graph->setAxisX(new QValue3DAxis); |
| m_graph->axisX()->setTitle("X-Axis"); |
| m_graph->setAxisY(new QValue3DAxis); |
| m_graph->axisY()->setTitle("Value Axis"); |
| m_graph->setAxisZ(new QValue3DAxis); |
| m_graph->axisZ()->setTitle("Z-Axis"); |
| #ifdef MULTI_SERIES |
| m_limitX = float(m_xCount) / 2.0f; |
| m_limitZ = float(m_zCount) / 2.0f; |
| // Series 1 |
| m_multiSampleOffsetX[0] = -m_offset; |
| m_multiSampleOffsetZ[0] = -m_offset; |
| // Series 2 |
| m_multiSampleOffsetX[1] = -m_offset; |
| m_multiSampleOffsetZ[1] = m_offset; |
| // Series 3 |
| m_multiSampleOffsetX[2] = m_offset; |
| m_multiSampleOffsetZ[2] = -m_offset; |
| // Series 4 |
| m_multiSampleOffsetX[3] = m_offset; |
| m_multiSampleOffsetZ[3] = m_offset; |
| |
| // m_graph->axisX()->setRange(-m_limitX - m_offset, m_limitX + m_offset); |
| // m_graph->axisY()->setRange(-1.0f, 4.5f); |
| // m_graph->axisZ()->setRange(-m_limitZ - m_offset, m_limitZ + m_offset); |
| #else |
| m_graph->addSeries(m_theSeries); |
| #endif |
| m_graph->axisX()->setRange(m_minX, m_minX + m_rangeX); |
| m_graph->axisY()->setRange(m_minY, m_minY + m_rangeY); |
| m_graph->axisZ()->setRange(m_minZ, m_minZ + m_rangeZ); |
| |
| static_cast<Q3DInputHandler *>(m_graph->activeInputHandler())->setZoomAtTargetEnabled(true); |
| |
| for (int i = 0; i < 4; i++) { |
| m_multiseries[i] = new QSurface3DSeries; |
| m_multiseries[i]->setName(QStringLiteral("Series %1").arg(i+1)); |
| m_multiseries[i]->setItemLabelFormat(QStringLiteral("@seriesName: (@xLabel, @zLabel): @yLabel")); |
| } |
| |
| fillSeries(); |
| changeStyle(); |
| |
| m_theSeries->setItemLabelFormat(QStringLiteral("@seriesName: (@xLabel, @zLabel): @yLabel")); |
| |
| connect(&m_timer, &QTimer::timeout, this, &GraphModifier::timeout); |
| connect(&m_graphPositionQueryTimer, &QTimer::timeout, this, &GraphModifier::graphQueryTimeout); |
| connect(m_theSeries, &QSurface3DSeries::selectedPointChanged, this, &GraphModifier::selectedPointChanged); |
| |
| QObject::connect(m_graph, &Q3DSurface::axisXChanged, this, |
| &GraphModifier::handleAxisXChanged); |
| QObject::connect(m_graph, &Q3DSurface::axisYChanged, this, |
| &GraphModifier::handleAxisYChanged); |
| QObject::connect(m_graph, &Q3DSurface::axisZChanged, this, |
| &GraphModifier::handleAxisZChanged); |
| QObject::connect(m_graph, &QAbstract3DGraph::currentFpsChanged, this, |
| &GraphModifier::handleFpsChange); |
| |
| //m_graphPositionQueryTimer.start(100); |
| } |
| |
| GraphModifier::~GraphModifier() |
| { |
| delete m_graph; |
| } |
| |
| void GraphModifier::fillSeries() |
| { |
| float full = m_limitX * m_limitZ; |
| |
| QSurfaceDataArray *dataArray1 = new QSurfaceDataArray; |
| dataArray1->reserve(m_zCount); |
| QSurfaceDataArray *dataArray2 = new QSurfaceDataArray; |
| dataArray2->reserve(m_zCount); |
| QSurfaceDataArray *dataArray3 = new QSurfaceDataArray; |
| dataArray3->reserve(m_zCount); |
| QSurfaceDataArray *dataArray4 = new QSurfaceDataArray; |
| dataArray4->reserve(m_zCount); |
| |
| |
| for (int i = 0; i < m_zCount; i++) { |
| QSurfaceDataRow *newRow[4]; |
| float zAdjust = 0.0f; |
| if (i == 2) |
| zAdjust = 0.7f; |
| |
| for (int s = 0; s < 4; s++) { |
| newRow[s] = new QSurfaceDataRow(m_xCount); |
| float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[s] + zAdjust; |
| for (int j = 0; j < m_xCount; j++) { |
| float xAdjust = 0.0f; |
| if (j == 4) |
| xAdjust = 0.7f; |
| float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[s] + xAdjust; |
| float angle = (z * x) / full * 1.57f; |
| float y = (qSin(angle * float(qPow(1.3f, s))) + 1.1f * s) * 3.0f - 5.0f + xAdjust + zAdjust; |
| (*newRow[s])[j].setPosition(QVector3D(x, y, z)); |
| } |
| } |
| *dataArray1 << newRow[0]; |
| *dataArray2 << newRow[1]; |
| *dataArray3 << newRow[2]; |
| *dataArray4 << newRow[3]; |
| } |
| |
| m_multiseries[0]->dataProxy()->resetArray(dataArray1); |
| m_multiseries[1]->dataProxy()->resetArray(dataArray2); |
| m_multiseries[2]->dataProxy()->resetArray(dataArray3); |
| m_multiseries[3]->dataProxy()->resetArray(dataArray4); |
| } |
| |
| void GraphModifier::toggleSeries1(bool enabled) |
| { |
| qDebug() << __FUNCTION__ << " enabled = " << enabled; |
| |
| if (enabled) { |
| m_graph->addSeries(m_multiseries[0]); |
| } else { |
| m_graph->removeSeries(m_multiseries[0]); |
| } |
| } |
| |
| void GraphModifier::toggleSeries2(bool enabled) |
| { |
| qDebug() << __FUNCTION__ << " enabled = " << enabled; |
| |
| if (enabled) { |
| m_graph->addSeries(m_multiseries[1]); |
| } else { |
| m_graph->removeSeries(m_multiseries[1]); |
| } |
| } |
| |
| void GraphModifier::toggleSeries3(bool enabled) |
| { |
| qDebug() << __FUNCTION__ << " enabled = " << enabled; |
| |
| if (enabled) { |
| m_graph->addSeries(m_multiseries[2]); |
| } else { |
| m_graph->removeSeries(m_multiseries[2]); |
| } |
| } |
| |
| void GraphModifier::toggleSeries4(bool enabled) |
| { |
| qDebug() << __FUNCTION__ << " enabled = " << enabled; |
| |
| if (enabled) { |
| m_graph->addSeries(m_multiseries[3]); |
| } else { |
| m_graph->removeSeries(m_multiseries[3]); |
| } |
| } |
| |
| void GraphModifier::toggleSmooth(bool enabled) |
| { |
| qDebug() << "GraphModifier::toggleSmooth " << enabled; |
| m_theSeries->setFlatShadingEnabled(enabled); |
| #ifdef MULTI_SERIES |
| m_multiseries[0]->setFlatShadingEnabled(enabled); |
| #endif |
| } |
| |
| void GraphModifier::toggleSurfaceGrid(bool enable) |
| { |
| qDebug() << "GraphModifier::toggleSurfaceGrid" << enable; |
| if (enable) |
| m_drawMode |= QSurface3DSeries::DrawWireframe; |
| else |
| m_drawMode &= ~QSurface3DSeries::DrawWireframe; |
| |
| m_theSeries->setDrawMode(m_drawMode); |
| #ifdef MULTI_SERIES |
| m_multiseries[0]->setDrawMode(m_drawMode); |
| #endif |
| } |
| |
| void GraphModifier::toggleSurface(bool enable) |
| { |
| qDebug() << "GraphModifier::toggleSurface" << enable; |
| if (enable) |
| m_drawMode |= QSurface3DSeries::DrawSurface; |
| else |
| m_drawMode &= ~QSurface3DSeries::DrawSurface; |
| |
| m_theSeries->setDrawMode(m_drawMode); |
| #ifdef MULTI_SERIES |
| m_multiseries[0]->setDrawMode(m_drawMode); |
| #endif |
| } |
| |
| void GraphModifier::toggleSeriesVisible(bool enable) |
| { |
| m_theSeries->setVisible(enable); |
| #ifdef MULTI_SERIES |
| m_multiseries[0]->setVisible(enable); |
| #endif |
| } |
| |
| void GraphModifier::toggleSmoothS2(bool enabled) |
| { |
| qDebug() << __FUNCTION__ << enabled; |
| m_multiseries[1]->setFlatShadingEnabled(enabled); |
| } |
| |
| void GraphModifier::toggleSurfaceGridS2(bool enable) |
| { |
| qDebug() << __FUNCTION__ << enable; |
| if (enable) |
| m_drawMode2 |= QSurface3DSeries::DrawWireframe; |
| else |
| m_drawMode2 &= ~QSurface3DSeries::DrawWireframe; |
| |
| m_multiseries[1]->setDrawMode(m_drawMode2); |
| } |
| |
| void GraphModifier::toggleSurfaceS2(bool enable) |
| { |
| qDebug() << __FUNCTION__ << enable; |
| if (enable) |
| m_drawMode2 |= QSurface3DSeries::DrawSurface; |
| else |
| m_drawMode2 &= ~QSurface3DSeries::DrawSurface; |
| |
| m_multiseries[1]->setDrawMode(m_drawMode2); |
| } |
| |
| void GraphModifier::toggleSeries2Visible(bool enable) |
| { |
| qDebug() << __FUNCTION__ << enable; |
| m_multiseries[1]->setVisible(enable); |
| } |
| |
| void GraphModifier::toggleSmoothS3(bool enabled) |
| { |
| qDebug() << __FUNCTION__ << enabled; |
| m_multiseries[2]->setFlatShadingEnabled(enabled); |
| } |
| |
| void GraphModifier::toggleSurfaceGridS3(bool enable) |
| { |
| qDebug() << __FUNCTION__ << enable; |
| if (enable) |
| m_drawMode3 |= QSurface3DSeries::DrawWireframe; |
| else |
| m_drawMode3 &= ~QSurface3DSeries::DrawWireframe; |
| |
| m_multiseries[2]->setDrawMode(m_drawMode3); |
| } |
| |
| void GraphModifier::toggleSurfaceS3(bool enable) |
| { |
| qDebug() << __FUNCTION__ << enable; |
| if (enable) |
| m_drawMode3 |= QSurface3DSeries::DrawSurface; |
| else |
| m_drawMode3 &= ~QSurface3DSeries::DrawSurface; |
| |
| m_multiseries[2]->setDrawMode(m_drawMode3); |
| } |
| |
| void GraphModifier::toggleSeries3Visible(bool enable) |
| { |
| qDebug() << __FUNCTION__ << enable; |
| m_multiseries[2]->setVisible(enable); |
| } |
| |
| void GraphModifier::toggleSmoothS4(bool enabled) |
| { |
| qDebug() << __FUNCTION__ << enabled; |
| m_multiseries[3]->setFlatShadingEnabled(enabled); |
| } |
| |
| void GraphModifier::toggleSurfaceGridS4(bool enable) |
| { |
| qDebug() << __FUNCTION__ << enable; |
| if (enable) |
| m_drawMode4 |= QSurface3DSeries::DrawWireframe; |
| else |
| m_drawMode4 &= ~QSurface3DSeries::DrawWireframe; |
| |
| m_multiseries[3]->setDrawMode(m_drawMode4); |
| } |
| |
| void GraphModifier::toggleSurfaceS4(bool enable) |
| { |
| qDebug() << __FUNCTION__ << enable; |
| if (enable) |
| m_drawMode4 |= QSurface3DSeries::DrawSurface; |
| else |
| m_drawMode4 &= ~QSurface3DSeries::DrawSurface; |
| |
| m_multiseries[3]->setDrawMode(m_drawMode4); |
| } |
| |
| void GraphModifier::toggleSeries4Visible(bool enable) |
| { |
| qDebug() << __FUNCTION__ << enable; |
| m_multiseries[3]->setVisible(enable); |
| } |
| |
| void GraphModifier::toggleSqrtSin(bool enable) |
| { |
| if (enable) { |
| qDebug() << "Create Sqrt&Sin surface, (" << m_xCount << ", " << m_zCount << ")"; |
| |
| float minX = -10.0f; |
| float maxX = 10.0f; |
| float minZ = -10.0f; |
| float maxZ = 10.0f; |
| float stepX = (maxX - minX) / float(m_xCount - 1); |
| float stepZ = (maxZ - minZ) / float(m_zCount - 1); |
| |
| QSurfaceDataArray *dataArray = new QSurfaceDataArray; |
| dataArray->reserve(m_zCount); |
| for (float i = 0; i < m_zCount; i++) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| // Keep values within range bounds, since just adding step can cause minor drift due |
| // to the rounding errors. |
| float z = qMin(maxZ, (i * stepZ + minZ)); |
| for (float j = 0; j < m_xCount; j++) { |
| float x = qMin(maxX, (j * stepX + minX)); |
| float R = qSqrt(x * x + z * z) + 0.01f; |
| float y = (qSin(R) / R + 0.24f) * 1.61f + 1.0f; |
| (*newRow)[j].setPosition(QVector3D(x, y, z)); |
| } |
| *dataArray << newRow; |
| } |
| |
| m_graph->axisY()->setRange(1.0, 3.0); |
| m_graph->axisX()->setLabelFormat("%.2f"); |
| m_graph->axisZ()->setLabelFormat("%.2f"); |
| |
| m_theSeries->setName("Sqrt & Sin"); |
| |
| resetArrayAndSliders(dataArray, minZ, maxZ, minX, maxX); |
| |
| m_activeSample = GraphModifier::SqrtSin; |
| } else { |
| qDebug() << "Remove surface"; |
| } |
| } |
| |
| void GraphModifier::togglePlane(bool enable) |
| { |
| qDebug() << "GraphModifier::togglePlane " << enable; |
| |
| if (enable) { |
| m_planeArray = new QSurfaceDataArray; |
| |
| #ifdef JITTER_PLANE |
| m_timer.start(0); |
| #endif |
| m_graph->axisY()->setRange(0.0, 1.0); |
| m_graph->axisX()->setLabelFormat("%.2f"); |
| m_graph->axisZ()->setLabelFormat("%.2f"); |
| |
| m_planeArray->reserve(m_zCount); |
| float minX = -10.0f; |
| float maxX = 20.0f; |
| float minZ = -10.0f; |
| float maxZ = 10.0f; |
| float stepX = (maxX - minX) / float(m_xCount - 1); |
| float stepZ = (maxZ - minZ) / float(m_zCount - 1); |
| #ifdef WONKY_PLANE |
| float halfZ = m_zCount / 2; |
| float wonkyFactor = 0.01f; |
| float maxStepX = 0.0f; |
| float add = 0.0f; |
| for (float i = 0; i < m_zCount; i++) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| if (i < halfZ) { |
| stepX += wonkyFactor; |
| maxStepX = stepX; |
| } else { |
| stepX -= wonkyFactor; |
| } |
| add = 0.0f; |
| for (float j = 0; j < m_xCount; j++) { |
| (*newRow)[j].setPosition(QVector3D(j * stepX + minX, -0.04f, |
| i * stepZ + minZ + add)); |
| add += 0.5f; |
| |
| } |
| *m_planeArray << newRow; |
| } |
| |
| m_theSeries->setName("Wonky Plane"); |
| |
| resetArrayAndSliders(m_planeArray, minZ, maxZ + add, minX, m_xCount * maxStepX + minX); |
| #else |
| for (float i = 0; i < m_zCount; i++) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| // Keep values within range bounds, since just adding step can cause minor drift due |
| // to the rounding errors. |
| float zVal; |
| if (i == (m_zCount - 1)) |
| zVal = maxZ; |
| else |
| zVal = i * stepZ + minZ; |
| |
| float j = 0; |
| for (; j < m_xCount - 1; j++) |
| (*newRow)[j].setPosition(QVector3D(j * stepX + minX, -0.04f, zVal)); |
| (*newRow)[j].setPosition(QVector3D(maxX, -0.04f, zVal)); |
| |
| *m_planeArray << newRow; |
| } |
| |
| m_theSeries->setName("Plane"); |
| |
| resetArrayAndSliders(m_planeArray, minZ, maxZ, minX, maxX); |
| #endif |
| |
| m_activeSample = GraphModifier::Plane; |
| } |
| #ifdef JITTER_PLANE |
| else { |
| m_timer.stop(); |
| } |
| #endif |
| } |
| |
| void GraphModifier::setHeightMapData(bool enable) |
| { |
| if (enable) { |
| // Do the height map the hard way. |
| // Easier alternative would be to use the QHeightMapSurfaceDataProxy. |
| QImage image(":/maps/map"); |
| |
| QSurfaceDataArray *dataArray = new QSurfaceDataArray; |
| uchar *bits = image.bits(); |
| |
| int p = image.width() * 4 * (image.height() - 1); |
| dataArray->reserve(image.height()); |
| float minX = 34.0; |
| float maxX = 40.0; |
| float minZ = 18.0; |
| float maxZ = 24.0; |
| float xMul = (maxX - minX) / float(image.width() - 1); |
| float zMul = (maxZ - minZ) / float(image.height() - 1); |
| for (int i = 0; i < image.height(); i++, p -= image.width() * 4) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(image.width()); |
| for (int j = 0; j < image.width(); j++) { |
| (*newRow)[j].setPosition(QVector3D((float(j) * xMul) + minX, |
| (float(bits[p + (j * 4)]) + 1.0f) / 1.0f, |
| (float(i) * zMul) + minZ)); |
| } |
| *dataArray << newRow; |
| } |
| |
| m_graph->axisY()->setAutoAdjustRange(true); |
| m_graph->axisX()->setLabelFormat("%.1f N"); |
| m_graph->axisZ()->setLabelFormat("%.1f E"); |
| |
| m_theSeries->setName("Height Map"); |
| |
| resetArrayAndSliders(dataArray, minZ, maxZ, minX, maxX); |
| |
| m_activeSample = GraphModifier::Map; |
| } |
| } |
| |
| void GraphModifier::toggleGridSliderLock(bool enable) |
| { |
| m_gridSlidersLocked = enable; |
| if (m_gridSlidersLocked) { |
| m_gridSliderZ->setEnabled(false); |
| m_gridSliderZ->setValue(m_gridSliderX->value()); |
| } else { |
| m_gridSliderZ->setEnabled(true); |
| } |
| } |
| |
| void GraphModifier::adjustXCount(int count) |
| { |
| m_xCount = count; |
| if (m_gridSlidersLocked) |
| m_gridSliderZ->setValue(count); |
| |
| updateSamples(); |
| |
| qDebug() << "X count =" << count; |
| } |
| |
| void GraphModifier::adjustZCount(int count) |
| { |
| m_zCount = count; |
| |
| updateSamples(); |
| |
| qDebug() << "Z count =" << count; |
| } |
| |
| void GraphModifier::adjustXRange(int range) |
| { |
| m_rangeX = range; |
| m_graph->axisX()->setRange(m_minX, m_minX + m_rangeX); |
| |
| qDebug() << "X Range =" << range; |
| } |
| |
| void GraphModifier::adjustYRange(int range) |
| { |
| m_rangeY = range; |
| m_graph->axisY()->setRange(m_minY, m_minY + m_rangeY); |
| |
| qDebug() << "Y Range =" << range; |
| } |
| |
| void GraphModifier::adjustZRange(int range) |
| { |
| m_rangeZ = range; |
| m_graph->axisZ()->setRange(m_minZ, m_minZ + m_rangeZ); |
| |
| qDebug() << "Z Range =" << range; |
| } |
| |
| void GraphModifier::adjustXMin(int min) |
| { |
| m_minX = min; |
| m_graph->axisX()->setRange(m_minX, m_minX + m_rangeX); |
| |
| qDebug() << "X Minimum =" << min; |
| } |
| |
| void GraphModifier::adjustYMin(int min) |
| { |
| m_minY = min; |
| m_graph->axisY()->setRange(m_minY, m_minY + m_rangeY); |
| |
| qDebug() << "Y Minimum =" << min; |
| } |
| |
| void GraphModifier::adjustZMin(int min) |
| { |
| m_minZ = min; |
| m_graph->axisZ()->setRange(m_minZ, m_minZ + m_rangeZ); |
| |
| qDebug() << "Z Minimum =" << min; |
| } |
| |
| void GraphModifier::gradientPressed() |
| { |
| static Q3DTheme::ColorStyle colorStyle = Q3DTheme::ColorStyleUniform; |
| |
| if (colorStyle == Q3DTheme::ColorStyleRangeGradient) { |
| colorStyle = Q3DTheme::ColorStyleObjectGradient; |
| qDebug() << "Color style: ColorStyleObjectGradient"; |
| } else if (colorStyle == Q3DTheme::ColorStyleObjectGradient) { |
| colorStyle = Q3DTheme::ColorStyleUniform; |
| qDebug() << "Color style: ColorStyleUniform"; |
| } else { |
| colorStyle = Q3DTheme::ColorStyleRangeGradient; |
| qDebug() << "Color style: ColorStyleRangeGradient"; |
| } |
| |
| QLinearGradient gradient; |
| gradient.setColorAt(0.0, Qt::black); |
| gradient.setColorAt(0.33, Qt::blue); |
| gradient.setColorAt(0.67, Qt::red); |
| gradient.setColorAt(1.0, Qt::yellow); |
| |
| QList<QLinearGradient> gradients; |
| gradients << gradient; |
| m_graph->activeTheme()->setBaseGradients(gradients); |
| m_graph->activeTheme()->setColorStyle(colorStyle); |
| |
| } |
| |
| void GraphModifier::changeFont(const QFont &font) |
| { |
| QFont newFont = font; |
| newFont.setPointSizeF(m_fontSize); |
| m_graph->activeTheme()->setFont(newFont); |
| } |
| |
| void GraphModifier::changeStyle() |
| { |
| m_graph->activeTheme()->setLabelBackgroundEnabled(!m_graph->activeTheme()->isLabelBackgroundEnabled()); |
| } |
| |
| void GraphModifier::selectButtonClicked() |
| { |
| QSurfaceDataProxy *proxy = m_theSeries->dataProxy(); |
| int row = QRandomGenerator::global()->bounded(proxy->rowCount()); |
| int col = QRandomGenerator::global()->bounded(proxy->columnCount()); |
| |
| m_theSeries->setSelectedPoint(QPoint(row, col)); |
| } |
| |
| void GraphModifier::selectedPointChanged(const QPoint &point) |
| { |
| QString labelText = QStringLiteral("Selected row: %1, column: %2").arg(point.x()).arg(point.y()); |
| m_selectionInfoLabel->setText(labelText); |
| } |
| |
| void GraphModifier::changeTheme(int theme) |
| { |
| m_graph->activeTheme()->setType(Q3DTheme::Theme(theme)); |
| } |
| |
| |
| void GraphModifier::flipViews() |
| { |
| m_graph->scene()->setSecondarySubviewOnTop(!m_graph->scene()->isSecondarySubviewOnTop()); |
| } |
| |
| void GraphModifier::timeout() |
| { |
| int rows = m_planeArray->size(); |
| int columns = m_planeArray->at(0)->size(); |
| |
| // Induce minor random jitter to the existing plane array |
| for (int i = 0; i < rows; i++) { |
| for (int j = 0; j < columns; j++) { |
| (*m_planeArray->at(i))[j].setX(m_planeArray->at(i)->at(j).x() |
| * ((float((QRandomGenerator::global()->bounded(10)) + 5.0f) / 10000.0f) + 0.999f)); |
| (*m_planeArray->at(i))[j].setY(m_planeArray->at(i)->at(j).y() |
| * ((float((QRandomGenerator::global()->bounded(10)) + 5.0f) / 1000.0f) + 0.99f) + 0.0001f); |
| (*m_planeArray->at(i))[j].setZ(m_planeArray->at(i)->at(j).z() |
| * ((float((QRandomGenerator::global()->bounded(10)) + 5.0f) / 10000.0f) + 0.999f)); |
| } |
| } |
| |
| // Reset same array to make it redraw |
| m_theSeries->dataProxy()->resetArray(m_planeArray); |
| } |
| |
| void GraphModifier::graphQueryTimeout() |
| { |
| #ifndef QT_NO_CURSOR |
| m_graph->scene()->setGraphPositionQuery(m_parentWidget->mapFromGlobal(QCursor::pos())); |
| qDebug() << "pos: " << (m_parentWidget->mapFromGlobal(QCursor::pos())); |
| #else |
| m_graph->scene()->setGraphPositionQuery(QPoint(100, 100)); |
| #endif |
| } |
| |
| void GraphModifier::handleAxisXChanged(QValue3DAxis *axis) |
| { |
| qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisX()); |
| } |
| |
| void GraphModifier::handleAxisYChanged(QValue3DAxis *axis) |
| { |
| qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisY()); |
| } |
| |
| void GraphModifier::handleAxisZChanged(QValue3DAxis *axis) |
| { |
| qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisZ()); |
| } |
| |
| void GraphModifier::handleFpsChange(qreal fps) |
| { |
| qDebug() << "FPS:" << fps; |
| } |
| |
| void GraphModifier::changeLabelRotation(int rotation) |
| { |
| m_graph->axisX()->setLabelAutoRotation(float(rotation)); |
| m_graph->axisY()->setLabelAutoRotation(float(rotation)); |
| m_graph->axisZ()->setLabelAutoRotation(float(rotation)); |
| } |
| |
| void GraphModifier::toggleAxisTitleVisibility(bool enabled) |
| { |
| m_graph->axisX()->setTitleVisible(enabled); |
| m_graph->axisY()->setTitleVisible(enabled); |
| m_graph->axisZ()->setTitleVisible(enabled); |
| } |
| |
| void GraphModifier::toggleAxisTitleFixed(bool enabled) |
| { |
| m_graph->axisX()->setTitleFixed(enabled); |
| m_graph->axisY()->setTitleFixed(enabled); |
| m_graph->axisZ()->setTitleFixed(enabled); |
| } |
| |
| void GraphModifier::toggleXAscending(bool enabled) |
| { |
| m_ascendingX = enabled; |
| |
| // Flip data array contents if necessary |
| foreach (QSurface3DSeries *series, m_graph->seriesList()) { |
| QSurfaceDataArray *array = const_cast<QSurfaceDataArray *>(series->dataProxy()->array()); |
| const int rowCount = array->size(); |
| const int columnCount = array->at(0)->size(); |
| const bool dataAscending = array->at(0)->at(0).x() < array->at(0)->at(columnCount - 1).x(); |
| if (dataAscending != enabled) { |
| // Create new array of equal size |
| QSurfaceDataArray *newArray = new QSurfaceDataArray; |
| newArray->reserve(rowCount); |
| for (int i = 0; i < rowCount; i++) |
| newArray->append(new QSurfaceDataRow(columnCount)); |
| |
| // Flip each row |
| for (int i = 0; i < rowCount; i++) { |
| QSurfaceDataRow *oldRow = array->at(i); |
| QSurfaceDataRow *newRow = newArray->at(i); |
| for (int j = 0; j < columnCount; j++) |
| (*newRow)[j] = oldRow->at(columnCount - 1 - j); |
| } |
| |
| series->dataProxy()->resetArray(newArray); |
| } |
| } |
| } |
| |
| void GraphModifier::toggleZAscending(bool enabled) |
| { |
| m_ascendingZ = enabled; |
| |
| // Flip data array contents if necessary |
| foreach (QSurface3DSeries *series, m_graph->seriesList()) { |
| QSurfaceDataArray *array = const_cast<QSurfaceDataArray *>(series->dataProxy()->array()); |
| const int rowCount = array->size(); |
| const int columnCount = array->at(0)->size(); |
| const bool dataAscending = array->at(0)->at(0).z() < array->at(rowCount - 1)->at(0).z(); |
| if (dataAscending != enabled) { |
| // Create new array of equal size |
| QSurfaceDataArray *newArray = new QSurfaceDataArray; |
| newArray->reserve(rowCount); |
| for (int i = 0; i < rowCount; i++) |
| newArray->append(new QSurfaceDataRow(columnCount)); |
| |
| // Flip each column |
| for (int i = 0; i < rowCount; i++) { |
| QSurfaceDataRow *oldRow = array->at(rowCount - 1 - i); |
| QSurfaceDataRow *newRow = newArray->at(i); |
| for (int j = 0; j < columnCount; j++) |
| (*newRow)[j] = oldRow->at(j); |
| } |
| |
| series->dataProxy()->resetArray(newArray); |
| } |
| } |
| } |
| |
| void GraphModifier::togglePolar(bool enabled) |
| { |
| m_graph->setPolar(enabled); |
| } |
| |
| void GraphModifier::setCameraTargetX(int value) |
| { |
| // Value is (-100, 100), normalize |
| m_cameraTarget.setX(float(value) / 100.0f); |
| m_graph->scene()->activeCamera()->setTarget(m_cameraTarget); |
| qDebug() << "m_cameraTarget:" << m_cameraTarget; |
| } |
| |
| void GraphModifier::setCameraTargetY(int value) |
| { |
| // Value is (-100, 100), normalize |
| m_cameraTarget.setY(float(value) / 100.0f); |
| m_graph->scene()->activeCamera()->setTarget(m_cameraTarget); |
| qDebug() << "m_cameraTarget:" << m_cameraTarget; |
| } |
| |
| void GraphModifier::setCameraTargetZ(int value) |
| { |
| // Value is (-100, 100), normalize |
| m_cameraTarget.setZ(float(value) / 100.0f); |
| m_graph->scene()->activeCamera()->setTarget(m_cameraTarget); |
| 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); |
| m_axisMinSliderZ->setValue(minZ); |
| m_axisRangeSliderX->setValue(maxX - minX); |
| m_axisRangeSliderZ->setValue(maxZ - minZ); |
| |
| m_theSeries->dataProxy()->resetArray(array); |
| } |
| |
| void GraphModifier::changeShadowQuality(int quality) |
| { |
| QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality); |
| m_graph->setShadowQuality(sq); |
| } |
| |
| void GraphModifier::changeSelectionMode(int mode) |
| { |
| QComboBox *comboBox = qobject_cast<QComboBox *>(sender()); |
| if (comboBox) { |
| int flags = comboBox->itemData(mode).toInt(); |
| m_graph->setSelectionMode(QAbstract3DGraph::SelectionFlags(flags)); |
| } |
| } |
| |
| void GraphModifier::changeRow() |
| { |
| if (m_activeSample == GraphModifier::SqrtSin) { |
| qDebug() << "Generating new values to a row at random pos"; |
| float minX = -10.0f; |
| float maxX = 10.0f; |
| float minZ = -10.0f; |
| float maxZ = 10.0f; |
| float stepX = (maxX - minX) / float(m_xCount - 1); |
| float stepZ = (maxZ - minZ) / float(m_zCount - 1); |
| float i = float(QRandomGenerator::global()->bounded(m_zCount)); |
| |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = qMin(maxZ, (i * stepZ + minZ)); |
| for (float j = 0; j < m_xCount; j++) { |
| float x = qMin(maxX, (j * stepX + minX)); |
| float R = qSqrt(x * x + z * z) + 0.01f; |
| float y = (qSin(R) / R + 0.24f) * 1.61f + 1.2f; |
| (*newRow)[j].setPosition(QVector3D(x, y, z)); |
| } |
| |
| m_theSeries->dataProxy()->setRow(int(i), newRow); |
| } else { |
| #ifdef MULTI_SERIES |
| static int changeRowSeries = 0; |
| qDebug() << "Generating new values to a row at random pos for series " << changeRowSeries; |
| |
| int row = QRandomGenerator::global()->bounded(m_zCount); |
| QSurfaceDataRow *newRow = createMultiRow(row, changeRowSeries, true); |
| if (m_ascendingZ) |
| m_multiseries[changeRowSeries]->dataProxy()->setRow(row, newRow); |
| else |
| m_multiseries[changeRowSeries]->dataProxy()->setRow((m_zCount - 1) - row, newRow); |
| |
| changeRowSeries++; |
| if (changeRowSeries > 3) |
| changeRowSeries = 0; |
| #else |
| qDebug() << "Change row function active only for SqrtSin"; |
| #endif |
| } |
| } |
| |
| QSurfaceDataRow *GraphModifier::createMultiRow(int row, int series, bool change) |
| { |
| int full = m_limitX * m_limitZ; |
| float i = float(row); |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[series]; |
| if (m_ascendingX) { |
| for (int j = 0; j < m_xCount; j++) { |
| float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[series]; |
| float angle = (z * x) / float(full) * 1.57f; |
| float y = qSin(angle * float(qPow(1.3f, series))) + 0.2f * float(change) + 1.1f *series; |
| (*newRow)[j].setPosition(QVector3D(x, y, z)); |
| } |
| } else { |
| for (int j = m_xCount - 1; j >= 0 ; j--) { |
| float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[series]; |
| float angle = (z * x) / float(full) * 1.57f; |
| float y = qSin(angle * float(qPow(1.3f, series))) + 0.2f * float(change) + 1.1f *series; |
| (*newRow)[(m_xCount - 1) - j].setPosition(QVector3D(x, y, z)); |
| } |
| } |
| |
| return newRow; |
| } |
| |
| void GraphModifier::populateRisingSeries(QSurface3DSeries *series, int rows, int columns, |
| float minValue, float maxValue, bool ascendingX, |
| bool ascendingZ) |
| { |
| QSurfaceDataArray *dataArray = new QSurfaceDataArray; |
| dataArray->reserve(rows); |
| float range = maxValue - minValue; |
| int arraySize = rows * columns; |
| for (int i = 0; i < rows; i++) { |
| QSurfaceDataRow *dataRow = new QSurfaceDataRow(columns); |
| for (int j = 0; j < columns; j++) { |
| float xValue = ascendingX ? float(j) : float(columns - j - 1); |
| float yValue = minValue + (range * i * j / arraySize); |
| float zValue = ascendingZ ? float(i) : float(rows - i - 1); |
| (*dataRow)[j].setPosition(QVector3D(xValue, yValue, zValue)); |
| } |
| dataArray->append(dataRow); |
| } |
| series->dataProxy()->resetArray(dataArray); |
| |
| } |
| |
| void GraphModifier::changeRows() |
| { |
| if (m_activeSample == GraphModifier::SqrtSin) { |
| qDebug() << "Generating new values to 3 rows from random pos"; |
| |
| float minX = -10.0f; |
| float maxX = 10.0f; |
| float minZ = -10.0f; |
| float maxZ = 10.0f; |
| float stepX = (maxX - minX) / float(m_xCount - 1); |
| float stepZ = (maxZ - minZ) / float(m_zCount - 1); |
| float start = float(QRandomGenerator::global()->bounded(m_zCount - 3)); |
| |
| QSurfaceDataArray dataArray; |
| |
| for (float i = start; i < (start + 3.0f); i++) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = qMin(maxZ, (i * stepZ + minZ)); |
| for (float j = 0; j < m_xCount; j++) { |
| float x = qMin(maxX, (j * stepX + minX)); |
| float R = qSqrt(x * x + z * z) + 0.01f; |
| float y = (qSin(R) / R + 0.24f) * 1.61f + 1.2f; |
| (*newRow)[j].setPosition(QVector3D(x, y, z)); |
| } |
| dataArray.append(newRow); |
| } |
| |
| m_theSeries->dataProxy()->setRows(int(start), dataArray); |
| } else { |
| #ifdef MULTI_SERIES |
| static int changeRowSeries = 0; |
| qDebug() << "Generating new values for 3 rows at random pos for series " << changeRowSeries; |
| |
| int row = QRandomGenerator::global()->bounded(m_zCount - 3); |
| QSurfaceDataArray dataArray; |
| for (int i = 0; i < 3; i++) { |
| QSurfaceDataRow *newRow = createMultiRow(row + i, changeRowSeries, true); |
| dataArray.append(newRow); |
| } |
| m_multiseries[changeRowSeries]->dataProxy()->setRows(row, dataArray); |
| |
| changeRowSeries++; |
| if (changeRowSeries > 3) |
| changeRowSeries = 0; |
| #else |
| qDebug() << "Change row function active only for SqrtSin"; |
| #endif |
| } |
| } |
| |
| void GraphModifier::changeItem() |
| { |
| if (m_activeSample == GraphModifier::SqrtSin) { |
| qDebug() << "Generating new values for an item at random pos"; |
| float minX = -10.0f; |
| float maxX = 10.0f; |
| float minZ = -10.0f; |
| float maxZ = 10.0f; |
| float stepX = (maxX - minX) / float(m_xCount - 1); |
| float stepZ = (maxZ - minZ) / float(m_zCount - 1); |
| float i = float(QRandomGenerator::global()->bounded(m_zCount)); |
| float j = float(QRandomGenerator::global()->bounded(m_xCount)); |
| |
| float x = qMin(maxX, (j * stepX + minX)); |
| float z = qMin(maxZ, (i * stepZ + minZ)); |
| float R = qSqrt(x * x + z * z) + 0.01f; |
| float y = (qSin(R) / R + 0.24f) * 1.61f + 1.2f; |
| QSurfaceDataItem newItem(QVector3D(x, y, z)); |
| |
| m_theSeries->dataProxy()->setItem(int(i), int(j), newItem); |
| } else { |
| #ifdef MULTI_SERIES |
| static int changeItemSeries = 0; |
| int full = m_limitX * m_limitZ; |
| float i = float(QRandomGenerator::global()->bounded(m_zCount)); |
| float j = float(QRandomGenerator::global()->bounded(m_xCount)); |
| float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[changeItemSeries]; |
| float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[changeItemSeries]; |
| float angle = (z * x) / float(full) * 1.57f; |
| float y = qSin(angle * float(qPow(1.3f, changeItemSeries))) + 0.2f + 1.1f *changeItemSeries; |
| QSurfaceDataItem newItem(QVector3D(x, y, z)); |
| |
| if (m_ascendingZ && m_ascendingX) |
| m_multiseries[changeItemSeries]->dataProxy()->setItem(int(i), int(j), newItem); |
| else if (!m_ascendingZ && m_ascendingX) |
| m_multiseries[changeItemSeries]->dataProxy()->setItem(m_zCount - 1 - int(i), int(j), newItem); |
| else if (m_ascendingZ && !m_ascendingX) |
| m_multiseries[changeItemSeries]->dataProxy()->setItem(int(i), m_xCount - 1 - int(j), newItem); |
| else |
| m_multiseries[changeItemSeries]->dataProxy()->setItem(m_zCount - 1 - int(i), m_xCount - 1 - int(j), newItem); |
| //m_multiseries[changeItemSeries]->setSelectedPoint(QPoint(i, j)); |
| changeItemSeries++; |
| if (changeItemSeries > 3) |
| changeItemSeries = 0; |
| #else |
| qDebug() << "Change item function active only for SqrtSin"; |
| #endif |
| } |
| } |
| |
| void GraphModifier::changeMultipleRows() |
| { |
| for (int i = 0; i < 30; i++) |
| changeRow(); |
| } |
| |
| void GraphModifier::changeMultipleItem() |
| { |
| for (int i = 0; i < 30; i++) |
| changeItem(); |
| } |
| |
| void GraphModifier::addRow() |
| { |
| if (m_activeSample == GraphModifier::SqrtSin) { |
| qDebug() << "Adding a new row"; |
| |
| float minX = -10.0f; |
| float maxX = 10.0f; |
| float minZ = -10.0f; |
| float maxZ = 10.0f; |
| float stepX = (maxX - minX) / float(m_xCount - 1); |
| float stepZ = (maxZ - minZ) / float(m_zCount - 1); |
| |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = float(m_addRowCounter) * stepZ + minZ; |
| for (float j = 0; j < m_xCount; j++) { |
| float x = qMin(maxX, (j * stepX + minX)); |
| float R = qSqrt(x * x + z * z) + 0.01f; |
| float y = (qSin(R) / R + 0.24f) * 1.61f + 1.0f; |
| (*newRow)[j].setPosition(QVector3D(x, y, z)); |
| } |
| m_addRowCounter++; |
| |
| m_theSeries->dataProxy()->addRow(newRow); |
| } else { |
| #ifdef MULTI_SERIES |
| qDebug() << "Adding a row into series 3"; |
| int full = m_limitX * m_limitZ; |
| int series = 2; |
| |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = float(m_addRowCounter) - m_limitZ + 0.5f + m_multiSampleOffsetZ[series]; |
| for (int j = 0; j < m_xCount; j++) { |
| float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[series]; |
| float angle = float(z * x) / float(full) * 1.57f; |
| (*newRow)[j].setPosition(QVector3D(x, qSin(angle *float(qPow(1.3f, series))) + 1.1f * series, z)); |
| } |
| m_addRowCounter++; |
| |
| m_multiseries[series]->dataProxy()->addRow(newRow); |
| #else |
| qDebug() << "Add row function active only for SqrtSin"; |
| #endif |
| } |
| } |
| |
| void GraphModifier::addRows() |
| { |
| if (m_activeSample == GraphModifier::SqrtSin) { |
| qDebug() << "Adding few new row"; |
| |
| float minX = -10.0f; |
| float maxX = 10.0f; |
| float minZ = -10.0f; |
| float maxZ = 10.0f; |
| float stepX = (maxX - minX) / float(m_xCount - 1); |
| float stepZ = (maxZ - minZ) / float(m_zCount - 1); |
| |
| QSurfaceDataArray dataArray; |
| |
| for (int i = 0; i < 3; i++) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = m_addRowCounter * stepZ + minZ; |
| for (float j = 0; j < m_xCount; j++) { |
| float x = qMin(maxX, (j * stepX + minX)); |
| float R = qSqrt(x * x + z * z) + 0.01f; |
| float y = (qSin(R) / R + 0.24f) * 1.61f + 1.0f; |
| (*newRow)[j].setPosition(QVector3D(x, y, z)); |
| } |
| dataArray.append(newRow); |
| m_addRowCounter++; |
| } |
| |
| m_theSeries->dataProxy()->addRows(dataArray); |
| } else { |
| #ifdef MULTI_SERIES |
| qDebug() << "Adding 3 rows into series 3"; |
| int changedSeries = 2; |
| |
| QSurfaceDataArray dataArray; |
| for (int i = 0; i < 3; i++) { |
| QSurfaceDataRow *newRow = createMultiRow(m_addRowCounter, changedSeries, false); |
| dataArray.append(newRow); |
| m_addRowCounter++; |
| } |
| |
| m_multiseries[changedSeries]->dataProxy()->addRows(dataArray); |
| #else |
| qDebug() << "Add rows function active only for SqrtSin"; |
| #endif |
| } |
| } |
| |
| void GraphModifier::insertRow() |
| { |
| if (m_activeSample == GraphModifier::SqrtSin) { |
| qDebug() << "Inserting a row"; |
| float minX = -10.0f; |
| float maxX = 10.0f; |
| float minZ = -10.0f; |
| float maxZ = 10.0f; |
| float stepX = (maxX - minX) / float(m_xCount - 1); |
| float stepZ = (maxZ - minZ) / float(m_zCount - 1); |
| |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = qMin(maxZ, (float(m_insertTestZPos) * stepZ + minZ + (stepZ / 2.0f))); |
| for (float j = 0; j < m_xCount; j++) { |
| float x = qMin(maxX, (j * stepX + minX)); |
| float R = qSqrt(x * x + z * z) + 0.01f; |
| float y = (qSin(R) / R + 0.24f) * 1.61f + 1.3f; |
| (*newRow)[j].setPosition(QVector3D(x, y, z)); |
| } |
| m_insertTestZPos++; |
| |
| m_theSeries->dataProxy()->insertRow(m_insertTestIndexPos, newRow); |
| m_insertTestIndexPos += 2; |
| } else { |
| #ifdef MULTI_SERIES |
| qDebug() << "Inserting a row into series 3"; |
| int full = m_limitX * m_limitZ; |
| int changedSeries = 2; |
| |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = float(m_insertTestZPos) - m_limitZ + m_multiSampleOffsetZ[changedSeries]; |
| for (int j = 0; j < m_xCount; j++) { |
| float x = float(j) - m_limitX + m_multiSampleOffsetX[changedSeries]; |
| float angle = (z * x) / float(full) * 1.57f; |
| (*newRow)[j].setPosition(QVector3D(x + 0.5f, |
| qSin(angle * float(qPow(1.3f, changedSeries))) + 1.2f * changedSeries, |
| z + 1.0f)); |
| } |
| |
| m_insertTestZPos++; |
| |
| m_multiseries[2]->dataProxy()->insertRow(m_insertTestIndexPos, newRow); |
| m_insertTestIndexPos += 2; |
| #else |
| qDebug() << "Insert row function active only for SqrtSin"; |
| #endif |
| } |
| } |
| |
| void GraphModifier::insertRows() |
| { |
| if (m_activeSample == GraphModifier::SqrtSin) { |
| qDebug() << "Inserting 3 rows"; |
| float minX = -10.0f; |
| float maxX = 10.0f; |
| float minZ = -10.0f; |
| float maxZ = 10.0f; |
| float stepX = (maxX - minX) / float(m_xCount - 1); |
| float stepZ = (maxZ - minZ) / float(m_zCount - 1); |
| |
| QSurfaceDataArray dataArray; |
| for (int i = 0; i < 3; i++) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = qMin(maxZ, (float(m_insertTestZPos) * stepZ + minZ + i * (stepZ / 4.0f))); |
| for (float j = 0; j < m_xCount; j++) { |
| float x = qMin(maxX, (j * stepX + minX)); |
| float R = qSqrt(x * x + z * z) + 0.01f; |
| float y = (qSin(R) / R + 0.24f) * 1.61f + 1.3f; |
| (*newRow)[j].setPosition(QVector3D(x, y, z)); |
| } |
| dataArray.append(newRow); |
| } |
| m_insertTestZPos++; |
| |
| m_theSeries->dataProxy()->insertRows(m_insertTestIndexPos, dataArray); |
| m_insertTestIndexPos += 4; |
| } else { |
| #ifdef MULTI_SERIES |
| qDebug() << "Inserting 3 rows into series 3"; |
| int full = m_limitX * m_limitZ; |
| int changedSeries = 2; |
| |
| QSurfaceDataArray dataArray; |
| float zAdd = 0.25f; |
| for (int i = 0; i < 3; i++) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); |
| float z = float(m_insertTestZPos) - m_limitZ + 0.5f + zAdd + m_multiSampleOffsetZ[changedSeries]; |
| for (int j = 0; j < m_xCount; j++) { |
| float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[changedSeries]; |
| float angle = (z * x) / float(full) * 1.57f; |
| float y = qSin(angle * float(qPow(1.3f, changedSeries))) + + 1.2f * changedSeries; |
| (*newRow)[j].setPosition(QVector3D(x, y, z)); |
| } |
| zAdd += 0.25f; |
| dataArray.append(newRow); |
| } |
| |
| m_insertTestZPos++; |
| |
| m_multiseries[2]->dataProxy()->insertRows(m_insertTestIndexPos, dataArray); |
| m_insertTestIndexPos += 4; |
| #else |
| qDebug() << "Insert rows function active only for SqrtSin"; |
| #endif |
| } |
| } |
| |
| void GraphModifier::removeRow() |
| { |
| qDebug() << "Remove an arbitrary row"; |
| if (m_zCount < 1) |
| return; |
| |
| int row = QRandomGenerator::global()->bounded(m_zCount); |
| |
| #ifdef MULTI_SERIES |
| int series = QRandomGenerator::global()->bounded(4); |
| m_multiseries[series]->dataProxy()->removeRows(row, 1); |
| #else |
| m_theSeries->dataProxy()->removeRows(row, 1); |
| #endif |
| m_zCount--; |
| } |
| |
| void GraphModifier::resetArray() |
| { |
| qDebug() << "Reset series data array"; |
| int rows = 10; |
| int columns = 10; |
| float randFactor = float(QRandomGenerator::global()->bounded(100)) / 100.0f; |
| QSurfaceDataArray *planeArray = new QSurfaceDataArray; |
| planeArray->reserve(rows); |
| |
| for (int i = 0; i < rows; i++) { |
| planeArray->append(new QSurfaceDataRow); |
| (*planeArray)[i]->resize(columns); |
| for (int j = 0; j < columns; j++) { |
| (*planeArray->at(i))[j].setX(float(j) * randFactor); |
| (*planeArray->at(i))[j].setY(float(i - j) * randFactor); |
| (*planeArray->at(i))[j].setZ(float(i)); |
| } |
| } |
| |
| #ifdef MULTI_SERIES |
| int series = QRandomGenerator::global()->bounded(4); |
| m_multiseries[series]->dataProxy()->resetArray(planeArray); |
| #else |
| m_theSeries->dataProxy()->resetArray(planeArray); |
| #endif |
| } |
| |
| void GraphModifier::resetArrayEmpty() |
| { |
| QSurfaceDataArray *emptyArray = new QSurfaceDataArray; |
| #ifdef MULTI_SERIES |
| int series = QRandomGenerator::global()->bounded(4); |
| m_multiseries[series]->dataProxy()->resetArray(emptyArray); |
| #else |
| m_theSeries->dataProxy()->resetArray(emptyArray); |
| #endif |
| } |
| |
| void GraphModifier::massiveDataTest() |
| { |
| static int testPhase = 0; |
| static const int cacheSize = 1000; |
| const int columns = 200; |
| const int rows = 200000; |
| const int visibleRows = 200; |
| const float yRangeMin = 0.0f; |
| const float yRangeMax = 1.0f; |
| const float yRangeMargin = 0.05f; |
| static QTimer *massiveTestTimer = 0; |
| static QSurface3DSeries *series = new QSurface3DSeries; |
| |
| // To speed up massive array creation, we generate a smaller cache array |
| // and copy rows from that to our main array |
| if (!m_massiveTestCacheArray.size()) { |
| m_massiveTestCacheArray.reserve(cacheSize); |
| float minY = yRangeMin + yRangeMargin; |
| float maxY = yRangeMax - yRangeMargin; |
| float rowBase = minY; |
| float direction = 1.0f; |
| for (int i = 0; i < cacheSize; i++) { |
| m_massiveTestCacheArray.append(new QSurfaceDataRow); |
| m_massiveTestCacheArray[i]->resize(columns); |
| rowBase += direction * (float(QRandomGenerator::global()->bounded(3)) / 100.0f); |
| if (rowBase > maxY) { |
| rowBase = maxY; |
| direction = -1.0f; |
| } else if (rowBase < minY) { |
| rowBase = minY; |
| direction = 1.0f; |
| } |
| for (int j = 0; j < columns; j++) { |
| float randFactor = float(QRandomGenerator::global()->bounded(100)) / (100 / yRangeMargin); |
| (*m_massiveTestCacheArray.at(i))[j].setX(float(j)); |
| (*m_massiveTestCacheArray.at(i))[j].setY(rowBase + randFactor); |
| // Z value is irrelevant, we replace it anyway when we take row to use |
| } |
| } |
| massiveTestTimer = new QTimer; |
| } |
| |
| switch (testPhase) { |
| case 0: { |
| qDebug() << __FUNCTION__ << testPhase << ": Setting the graph up..."; |
| QValue3DAxis *xAxis = new QValue3DAxis(); |
| QValue3DAxis *yAxis = new QValue3DAxis(); |
| QValue3DAxis *zAxis = new QValue3DAxis(); |
| xAxis->setRange(0.0f, float(columns)); |
| yAxis->setRange(yRangeMin, yRangeMax); |
| zAxis->setRange(0.0f, float(visibleRows)); |
| xAxis->setSegmentCount(1); |
| yAxis->setSegmentCount(1); |
| zAxis->setSegmentCount(1); |
| m_graph->setMeasureFps(true); |
| m_graph->setAxisX(xAxis); |
| m_graph->setAxisY(yAxis); |
| m_graph->setAxisZ(zAxis); |
| m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetRight); |
| m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualityNone); |
| foreach (QAbstract3DSeries *series, m_graph->seriesList()) |
| m_graph->removeSeries(static_cast<QSurface3DSeries *>(series)); |
| |
| qDebug() << __FUNCTION__ << testPhase << ": Creating massive array..." |
| << rows << "x" << columns; |
| // Reset to zero first to avoid having memory allocated for two massive arrays at the same |
| // time on the second and subsequent runs. |
| series->dataProxy()->resetArray(0); |
| QSurfaceDataArray *massiveArray = new QSurfaceDataArray; |
| massiveArray->reserve(rows); |
| |
| for (int i = 0; i < rows; i++) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(*m_massiveTestCacheArray.at(i % cacheSize)); |
| for (int j = 0; j < columns; j++) |
| (*newRow)[j].setZ(float(i)); |
| massiveArray->append(newRow); |
| } |
| qDebug() << __FUNCTION__ << testPhase << ": Massive array creation finished!"; |
| |
| series->dataProxy()->resetArray(massiveArray); |
| m_graph->addSeries(series); |
| break; |
| } |
| case 1: { |
| qDebug() << __FUNCTION__ << testPhase << ": Scroll"; |
| QObject::disconnect(massiveTestTimer, 0, this, 0); |
| QObject::connect(massiveTestTimer, &QTimer::timeout, this, |
| &GraphModifier::massiveTestScroll); |
| massiveTestTimer->start(16); |
| break; |
| } |
| case 2: { |
| qDebug() << __FUNCTION__ << testPhase << ": Append and scroll"; |
| massiveTestTimer->stop(); |
| QObject::disconnect(massiveTestTimer, 0, this, 0); |
| QObject::connect(massiveTestTimer, &QTimer::timeout, this, |
| &GraphModifier::massiveTestAppendAndScroll); |
| m_graph->axisZ()->setRange(rows - visibleRows, rows); |
| massiveTestTimer->start(16); |
| break; |
| } |
| default: |
| QObject::disconnect(massiveTestTimer, 0, this, 0); |
| massiveTestTimer->stop(); |
| qDebug() << __FUNCTION__ << testPhase << ": Resetting the test"; |
| testPhase = -1; |
| } |
| testPhase++; |
| } |
| |
| void GraphModifier::massiveTestScroll() |
| { |
| const int scrollAmount = 20; |
| int maxRows = m_graph->seriesList().at(0)->dataProxy()->rowCount(); |
| int min = m_graph->axisZ()->min() + scrollAmount; |
| int max = m_graph->axisZ()->max() + scrollAmount; |
| if (max >= maxRows) { |
| max = max - min; |
| min = 0; |
| } |
| m_graph->axisZ()->setRange(min, max); |
| } |
| |
| void GraphModifier::massiveTestAppendAndScroll() |
| { |
| const int addedRows = 50; |
| int maxRows = m_graph->seriesList().at(0)->dataProxy()->rowCount(); |
| int columns = m_graph->seriesList().at(0)->dataProxy()->columnCount(); |
| |
| QSurfaceDataArray appendArray; |
| appendArray.reserve(addedRows); |
| for (int i = 0; i < addedRows; i++) { |
| QSurfaceDataRow *newRow = new QSurfaceDataRow(*m_massiveTestCacheArray.at((i + maxRows) % 1000)); |
| for (int j = 0; j < columns; j++) |
| (*newRow)[j].setZ(float(maxRows + i)); |
| appendArray.append(newRow); |
| } |
| m_graph->seriesList().at(0)->dataProxy()->addRows(appendArray); |
| int min = m_graph->axisZ()->min() + addedRows; |
| int max = m_graph->axisZ()->max() + addedRows; |
| m_graph->axisZ()->setRange(min, max); |
| } |
| |
| void GraphModifier::testAxisReverse() |
| { |
| static int counter = 0; |
| const int rowCount = 16; |
| const int colCount = 16; |
| static QSurface3DSeries *series0 = 0; |
| static QSurface3DSeries *series1 = 0; |
| |
| switch (counter) { |
| case 0: { |
| qDebug() << __FUNCTION__ << counter << "Setup test"; |
| foreach (QSurface3DSeries *series, m_graph->seriesList()) |
| m_graph->removeSeries(series); |
| foreach (QValue3DAxis *axis, m_graph->axes()) |
| m_graph->releaseAxis(axis); |
| delete series0; |
| delete series1; |
| series0 = new QSurface3DSeries; |
| series1 = new QSurface3DSeries; |
| populateRisingSeries(series0, rowCount, colCount, 0.0f, 50.0f, true, true); |
| populateRisingSeries(series1, rowCount, colCount, -20.0f, 30.0f, true, true); |
| m_graph->axisX()->setRange(0.0f, 10.0f); |
| m_graph->axisY()->setRange(-20.0f, 50.0f); |
| m_graph->axisZ()->setRange(5.0f, 15.0f); |
| m_graph->addSeries(series0); |
| m_graph->addSeries(series1); |
| } |
| break; |
| case 1: { |
| qDebug() << __FUNCTION__ << counter << "Reverse X axis"; |
| m_graph->axisX()->setReversed(true); |
| } |
| break; |
| case 2: { |
| qDebug() << __FUNCTION__ << counter << "Reverse Y axis"; |
| m_graph->axisY()->setReversed(true); |
| } |
| break; |
| case 3: { |
| qDebug() << __FUNCTION__ << counter << "Reverse Z axis"; |
| m_graph->axisZ()->setReversed(true); |
| } |
| break; |
| case 4: { |
| qDebug() << __FUNCTION__ << counter << "Return all axes to normal"; |
| m_graph->axisX()->setReversed(false); |
| m_graph->axisY()->setReversed(false); |
| m_graph->axisZ()->setReversed(false); |
| } |
| break; |
| case 5: { |
| qDebug() << __FUNCTION__ << counter << "Reverse all axes"; |
| m_graph->axisX()->setReversed(true); |
| m_graph->axisY()->setReversed(true); |
| m_graph->axisZ()->setReversed(true); |
| } |
| break; |
| default: |
| qDebug() << __FUNCTION__ << "Resetting test"; |
| counter = -1; |
| } |
| counter++; |
| } |
| |
| void GraphModifier::testDataOrdering() |
| { |
| static int counter = 0; |
| const int rowCount = 20; |
| const int colCount = 20; |
| static QSurface3DSeries *series0 = 0; |
| static QSurface3DSeries *series1 = 0; |
| const float series0min = 0.0f; |
| const float series0max = 50.0f; |
| const float series1min = -20.0f; |
| const float series1max = 30.0f; |
| |
| switch (counter) { |
| case 0: { |
| qDebug() << __FUNCTION__ << counter << "Setup test - both ascending"; |
| foreach (QSurface3DSeries *series, m_graph->seriesList()) |
| m_graph->removeSeries(series); |
| foreach (QValue3DAxis *axis, m_graph->axes()) |
| m_graph->releaseAxis(axis); |
| delete series0; |
| delete series1; |
| series0 = new QSurface3DSeries; |
| series1 = new QSurface3DSeries; |
| populateRisingSeries(series0, rowCount, colCount, series0min, series0max, true, true); |
| populateRisingSeries(series1, rowCount, colCount, series1min, series1max, true, true); |
| m_graph->axisX()->setRange(5.0f, 15.0f); |
| m_graph->axisY()->setRange(-20.0f, 50.0f); |
| m_graph->axisZ()->setRange(5.0f, 15.0f); |
| m_graph->addSeries(series0); |
| m_graph->addSeries(series1); |
| } |
| break; |
| case 1: { |
| qDebug() << __FUNCTION__ << counter << "Ascending X, descending Z"; |
| populateRisingSeries(series0, rowCount, colCount, series0min, series0max, true, false); |
| populateRisingSeries(series1, rowCount, colCount, series1min, series1max, true, false); |
| } |
| break; |
| case 2: { |
| qDebug() << __FUNCTION__ << counter << "Descending X, ascending Z"; |
| populateRisingSeries(series0, rowCount, colCount, series0min, series0max, false, true); |
| populateRisingSeries(series1, rowCount, colCount, series1min, series1max, false, true); |
| } |
| break; |
| case 3: { |
| qDebug() << __FUNCTION__ << counter << "Both descending"; |
| populateRisingSeries(series0, rowCount, colCount, series0min, series0max, false, false); |
| populateRisingSeries(series1, rowCount, colCount, series1min, series1max, false, false); |
| } |
| break; |
| default: |
| qDebug() << __FUNCTION__ << "Resetting test"; |
| counter = -1; |
| } |
| counter++; |
| } |
| |
| void GraphModifier::changeMesh() |
| { |
| static int model = 0; |
| switch (model) { |
| case 0: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCylinder); |
| m_graph->seriesList().at(0)->setMeshSmooth(false); |
| break; |
| case 1: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCylinder); |
| m_graph->seriesList().at(0)->setMeshSmooth(true); |
| break; |
| case 2: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCone); |
| m_graph->seriesList().at(0)->setMeshSmooth(false); |
| break; |
| case 3: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshCone); |
| m_graph->seriesList().at(0)->setMeshSmooth(true); |
| break; |
| case 4: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBar); |
| m_graph->seriesList().at(0)->setMeshSmooth(false); |
| break; |
| case 5: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBar); |
| m_graph->seriesList().at(0)->setMeshSmooth(true); |
| break; |
| case 6: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshPyramid); |
| m_graph->seriesList().at(0)->setMeshSmooth(false); |
| break; |
| case 7: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshPyramid); |
| m_graph->seriesList().at(0)->setMeshSmooth(true); |
| break; |
| case 8: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBevelBar); |
| m_graph->seriesList().at(0)->setMeshSmooth(false); |
| break; |
| case 9: |
| m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::MeshBevelBar); |
| m_graph->seriesList().at(0)->setMeshSmooth(true); |
| break; |
| } |
| model++; |
| if (model > 9) |
| model = 0; |
| } |
| |
| void GraphModifier::updateSamples() |
| { |
| switch (m_activeSample) { |
| case SqrtSin: |
| toggleSqrtSin(true); |
| break; |
| |
| case Plane: |
| togglePlane(true); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| void GraphModifier::setAspectRatio(int ratio) |
| { |
| qreal aspectRatio = qreal(ratio) / 10.0; |
| m_graph->setAspectRatio(aspectRatio); |
| } |
| |
| void GraphModifier::setHorizontalAspectRatio(int ratio) |
| { |
| qreal aspectRatio = qreal(ratio) / 100.0; |
| m_graph->setHorizontalAspectRatio(aspectRatio); |
| } |
| |
| void GraphModifier::setSurfaceTexture(bool enabled) |
| { |
| if (enabled) |
| m_multiseries[3]->setTexture(QImage(":/maps/mapimage")); |
| else |
| m_multiseries[3]->setTexture(QImage()); |
| } |