| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the Qt Data Visualization module of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:GPL$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU | 
| 19 | ** General Public License version 3 or (at your option) any later version | 
| 20 | ** approved by the KDE Free Qt Foundation. The licenses are as published by | 
| 21 | ** the Free Software Foundation and appearing in the file LICENSE.GPL3 | 
| 22 | ** included in the packaging of this file. Please review the following | 
| 23 | ** information to ensure the GNU General Public License requirements will | 
| 24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 25 | ** | 
| 26 | ** $QT_END_LICENSE$ | 
| 27 | ** | 
| 28 | ****************************************************************************/ | 
| 29 |  | 
| 30 | #include "graphmodifier.h" | 
| 31 | #include <QtDataVisualization/QValue3DAxis> | 
| 32 | #include <QtDataVisualization/QSurfaceDataProxy> | 
| 33 | #include <QtDataVisualization/QSurface3DSeries> | 
| 34 | #include <QtDataVisualization/Q3DTheme> | 
| 35 | #include <QtDataVisualization/Q3DInputHandler> | 
| 36 |  | 
| 37 | #include <qmath.h> | 
| 38 | #include <qrandom.h> | 
| 39 | #include <QLinearGradient> | 
| 40 | #include <QDebug> | 
| 41 | #include <QComboBox> | 
| 42 | #ifndef QT_NO_CURSOR | 
| 43 | #include <QtGui/QCursor> | 
| 44 | #endif | 
| 45 | using namespace QtDataVisualization; | 
| 46 |  | 
| 47 | //#define JITTER_PLANE | 
| 48 | //#define WONKY_PLANE | 
| 49 |  | 
| 50 | GraphModifier::GraphModifier(Q3DSurface *graph, QWidget *parentWidget) | 
| 51 |     : m_graph(graph), | 
| 52 |       m_series1(new QSurface3DSeries), | 
| 53 |       m_series2(new QSurface3DSeries), | 
| 54 |       m_series3(new QSurface3DSeries), | 
| 55 |       m_series4(new QSurface3DSeries), | 
| 56 |       m_gridSliderX(0), | 
| 57 |       m_gridSliderZ(0), | 
| 58 |       m_axisRangeSliderX(0), | 
| 59 |       m_axisRangeSliderZ(0), | 
| 60 |       m_axisMinSliderX(0), | 
| 61 |       m_axisMinSliderZ(0), | 
| 62 |       m_xCount(24), | 
| 63 |       m_zCount(24), | 
| 64 |       m_activeSample(0), | 
| 65 |       m_fontSize(40), | 
| 66 |       m_rangeX(34.0), | 
| 67 |       m_rangeY(16.0), | 
| 68 |       m_rangeZ(34.0), | 
| 69 |       m_minX(-17.0), | 
| 70 |       m_minY(-8.0), | 
| 71 |       m_minZ(-17.0), | 
| 72 |       m_addRowCounter(m_zCount), | 
| 73 |       m_insertTestZPos(0), | 
| 74 |       m_insertTestIndexPos(1), | 
| 75 |       m_planeArray(0), | 
| 76 |       m_theSeries(new QSurface3DSeries), | 
| 77 |       m_drawMode(QSurface3DSeries::DrawSurfaceAndWireframe), | 
| 78 |       m_drawMode2(QSurface3DSeries::DrawSurfaceAndWireframe), | 
| 79 |       m_drawMode3(QSurface3DSeries::DrawSurfaceAndWireframe), | 
| 80 |       m_drawMode4(QSurface3DSeries::DrawSurfaceAndWireframe), | 
| 81 |       m_offset(4.0f), | 
| 82 |       m_parentWidget(parentWidget), | 
| 83 |       m_ascendingX(true), | 
| 84 |       m_ascendingZ(true) | 
| 85 | { | 
| 86 |     m_graph->setAxisX(new QValue3DAxis); | 
| 87 |     m_graph->axisX()->setTitle("X-Axis" ); | 
| 88 |     m_graph->setAxisY(new QValue3DAxis); | 
| 89 |     m_graph->axisY()->setTitle("Value Axis" ); | 
| 90 |     m_graph->setAxisZ(new QValue3DAxis); | 
| 91 |     m_graph->axisZ()->setTitle("Z-Axis" ); | 
| 92 | #ifdef MULTI_SERIES | 
| 93 |     m_limitX = float(m_xCount) / 2.0f; | 
| 94 |     m_limitZ = float(m_zCount) / 2.0f; | 
| 95 |     // Series 1 | 
| 96 |     m_multiSampleOffsetX[0] = -m_offset; | 
| 97 |     m_multiSampleOffsetZ[0] = -m_offset; | 
| 98 |     // Series 2 | 
| 99 |     m_multiSampleOffsetX[1] = -m_offset; | 
| 100 |     m_multiSampleOffsetZ[1] = m_offset; | 
| 101 |     // Series 3 | 
| 102 |     m_multiSampleOffsetX[2] = m_offset; | 
| 103 |     m_multiSampleOffsetZ[2] = -m_offset; | 
| 104 |     // Series 4 | 
| 105 |     m_multiSampleOffsetX[3] = m_offset; | 
| 106 |     m_multiSampleOffsetZ[3] = m_offset; | 
| 107 |  | 
| 108 | //    m_graph->axisX()->setRange(-m_limitX - m_offset, m_limitX + m_offset); | 
| 109 | //    m_graph->axisY()->setRange(-1.0f, 4.5f); | 
| 110 | //    m_graph->axisZ()->setRange(-m_limitZ - m_offset, m_limitZ + m_offset); | 
| 111 | #else | 
| 112 |     m_graph->addSeries(m_theSeries); | 
| 113 | #endif | 
| 114 |     m_graph->axisX()->setRange(min: m_minX, max: m_minX + m_rangeX); | 
| 115 |     m_graph->axisY()->setRange(min: m_minY, max: m_minY + m_rangeY); | 
| 116 |     m_graph->axisZ()->setRange(min: m_minZ, max: m_minZ + m_rangeZ); | 
| 117 |  | 
| 118 |     static_cast<Q3DInputHandler *>(m_graph->activeInputHandler())->setZoomAtTargetEnabled(true); | 
| 119 |  | 
| 120 |     for (int i = 0; i < 4; i++) { | 
| 121 |         m_multiseries[i] = new QSurface3DSeries; | 
| 122 |         m_multiseries[i]->setName(QStringLiteral("Series %1" ).arg(a: i+1)); | 
| 123 |         m_multiseries[i]->setItemLabelFormat(QStringLiteral("@seriesName: (@xLabel, @zLabel): @yLabel" )); | 
| 124 |     } | 
| 125 |  | 
| 126 |     fillSeries(); | 
| 127 |     changeStyle(); | 
| 128 |  | 
| 129 |     m_theSeries->setItemLabelFormat(QStringLiteral("@seriesName: (@xLabel, @zLabel): @yLabel" )); | 
| 130 |  | 
| 131 |     connect(sender: &m_timer, signal: &QTimer::timeout, receiver: this, slot: &GraphModifier::timeout); | 
| 132 |     connect(sender: &m_graphPositionQueryTimer, signal: &QTimer::timeout, receiver: this, slot: &GraphModifier::graphQueryTimeout); | 
| 133 |     connect(sender: m_theSeries, signal: &QSurface3DSeries::selectedPointChanged, receiver: this, slot: &GraphModifier::selectedPointChanged); | 
| 134 |  | 
| 135 |     QObject::connect(sender: m_graph, signal: &Q3DSurface::axisXChanged, receiver: this, | 
| 136 |                      slot: &GraphModifier::handleAxisXChanged); | 
| 137 |     QObject::connect(sender: m_graph, signal: &Q3DSurface::axisYChanged, receiver: this, | 
| 138 |                      slot: &GraphModifier::handleAxisYChanged); | 
| 139 |     QObject::connect(sender: m_graph, signal: &Q3DSurface::axisZChanged, receiver: this, | 
| 140 |                      slot: &GraphModifier::handleAxisZChanged); | 
| 141 |     QObject::connect(sender: m_graph, signal: &QAbstract3DGraph::currentFpsChanged, receiver: this, | 
| 142 |                      slot: &GraphModifier::handleFpsChange); | 
| 143 |  | 
| 144 |     //m_graphPositionQueryTimer.start(100); | 
| 145 | } | 
| 146 |  | 
| 147 | GraphModifier::~GraphModifier() | 
| 148 | { | 
| 149 |     delete m_graph; | 
| 150 | } | 
| 151 |  | 
| 152 | void GraphModifier::fillSeries() | 
| 153 | { | 
| 154 |     float full = m_limitX * m_limitZ; | 
| 155 |  | 
| 156 |     QSurfaceDataArray *dataArray1 = new QSurfaceDataArray; | 
| 157 |     dataArray1->reserve(alloc: m_zCount); | 
| 158 |     QSurfaceDataArray *dataArray2 = new QSurfaceDataArray; | 
| 159 |     dataArray2->reserve(alloc: m_zCount); | 
| 160 |     QSurfaceDataArray *dataArray3 = new QSurfaceDataArray; | 
| 161 |     dataArray3->reserve(alloc: m_zCount); | 
| 162 |     QSurfaceDataArray *dataArray4 = new QSurfaceDataArray; | 
| 163 |     dataArray4->reserve(alloc: m_zCount); | 
| 164 |  | 
| 165 |  | 
| 166 |     for (int i = 0; i < m_zCount; i++) { | 
| 167 |         QSurfaceDataRow *newRow[4]; | 
| 168 |         float zAdjust = 0.0f; | 
| 169 |         if (i == 2) | 
| 170 |             zAdjust = 0.7f; | 
| 171 |  | 
| 172 |         for (int s = 0; s < 4; s++) { | 
| 173 |             newRow[s] = new QSurfaceDataRow(m_xCount); | 
| 174 |             float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[s] + zAdjust; | 
| 175 |             for (int j = 0; j < m_xCount; j++) { | 
| 176 |                 float xAdjust = 0.0f; | 
| 177 |                 if (j == 4) | 
| 178 |                     xAdjust = 0.7f; | 
| 179 |                 float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[s] + xAdjust; | 
| 180 |                 float angle = (z * x) / full * 1.57f; | 
| 181 |                 float y = (qSin(v: angle * float(qPow(x: 1.3f, y: s))) + 1.1f * s) * 3.0f - 5.0f + xAdjust + zAdjust; | 
| 182 |                 (*newRow[s])[j].setPosition(QVector3D(x, y, z)); | 
| 183 |             } | 
| 184 |         } | 
| 185 |         *dataArray1 << newRow[0]; | 
| 186 |         *dataArray2 << newRow[1]; | 
| 187 |         *dataArray3 << newRow[2]; | 
| 188 |         *dataArray4 << newRow[3]; | 
| 189 |     } | 
| 190 |  | 
| 191 |     m_multiseries[0]->dataProxy()->resetArray(newArray: dataArray1); | 
| 192 |     m_multiseries[1]->dataProxy()->resetArray(newArray: dataArray2); | 
| 193 |     m_multiseries[2]->dataProxy()->resetArray(newArray: dataArray3); | 
| 194 |     m_multiseries[3]->dataProxy()->resetArray(newArray: dataArray4); | 
| 195 | } | 
| 196 |  | 
| 197 | void GraphModifier::toggleSeries1(bool enabled) | 
| 198 | { | 
| 199 |     qDebug() << __FUNCTION__ << " enabled = "  << enabled; | 
| 200 |  | 
| 201 |     if (enabled) { | 
| 202 |         m_graph->addSeries(series: m_multiseries[0]); | 
| 203 |     } else { | 
| 204 |         m_graph->removeSeries(series: m_multiseries[0]); | 
| 205 |     } | 
| 206 | } | 
| 207 |  | 
| 208 | void GraphModifier::toggleSeries2(bool enabled) | 
| 209 | { | 
| 210 |     qDebug() << __FUNCTION__ << " enabled = "  << enabled; | 
| 211 |  | 
| 212 |     if (enabled) { | 
| 213 |         m_graph->addSeries(series: m_multiseries[1]); | 
| 214 |     } else { | 
| 215 |         m_graph->removeSeries(series: m_multiseries[1]); | 
| 216 |     } | 
| 217 | } | 
| 218 |  | 
| 219 | void GraphModifier::toggleSeries3(bool enabled) | 
| 220 | { | 
| 221 |     qDebug() << __FUNCTION__ << " enabled = "  << enabled; | 
| 222 |  | 
| 223 |     if (enabled) { | 
| 224 |         m_graph->addSeries(series: m_multiseries[2]); | 
| 225 |     } else { | 
| 226 |         m_graph->removeSeries(series: m_multiseries[2]); | 
| 227 |     } | 
| 228 | } | 
| 229 |  | 
| 230 | void GraphModifier::toggleSeries4(bool enabled) | 
| 231 | { | 
| 232 |     qDebug() << __FUNCTION__ << " enabled = "  << enabled; | 
| 233 |  | 
| 234 |     if (enabled) { | 
| 235 |         m_graph->addSeries(series: m_multiseries[3]); | 
| 236 |     } else { | 
| 237 |         m_graph->removeSeries(series: m_multiseries[3]); | 
| 238 |     } | 
| 239 | } | 
| 240 |  | 
| 241 | void GraphModifier::toggleSmooth(bool enabled) | 
| 242 | { | 
| 243 |     qDebug() << "GraphModifier::toggleSmooth "  << enabled; | 
| 244 |     m_theSeries->setFlatShadingEnabled(enabled); | 
| 245 | #ifdef MULTI_SERIES | 
| 246 |     m_multiseries[0]->setFlatShadingEnabled(enabled); | 
| 247 | #endif | 
| 248 | } | 
| 249 |  | 
| 250 | void GraphModifier::toggleSurfaceGrid(bool enable) | 
| 251 | { | 
| 252 |     qDebug() << "GraphModifier::toggleSurfaceGrid"  << enable; | 
| 253 |     if (enable) | 
| 254 |         m_drawMode |= QSurface3DSeries::DrawWireframe; | 
| 255 |     else | 
| 256 |         m_drawMode &= ~QSurface3DSeries::DrawWireframe; | 
| 257 |  | 
| 258 |     m_theSeries->setDrawMode(m_drawMode); | 
| 259 | #ifdef MULTI_SERIES | 
| 260 |     m_multiseries[0]->setDrawMode(m_drawMode); | 
| 261 | #endif | 
| 262 | } | 
| 263 |  | 
| 264 | void GraphModifier::toggleSurface(bool enable) | 
| 265 | { | 
| 266 |     qDebug() << "GraphModifier::toggleSurface"  << enable; | 
| 267 |     if (enable) | 
| 268 |         m_drawMode |= QSurface3DSeries::DrawSurface; | 
| 269 |     else | 
| 270 |         m_drawMode &= ~QSurface3DSeries::DrawSurface; | 
| 271 |  | 
| 272 |     m_theSeries->setDrawMode(m_drawMode); | 
| 273 | #ifdef MULTI_SERIES | 
| 274 |     m_multiseries[0]->setDrawMode(m_drawMode); | 
| 275 | #endif | 
| 276 | } | 
| 277 |  | 
| 278 | void GraphModifier::toggleSeriesVisible(bool enable) | 
| 279 | { | 
| 280 |     m_theSeries->setVisible(enable); | 
| 281 | #ifdef MULTI_SERIES | 
| 282 |     m_multiseries[0]->setVisible(enable); | 
| 283 | #endif | 
| 284 | } | 
| 285 |  | 
| 286 | void GraphModifier::toggleSmoothS2(bool enabled) | 
| 287 | { | 
| 288 |     qDebug() << __FUNCTION__ << enabled; | 
| 289 |     m_multiseries[1]->setFlatShadingEnabled(enabled); | 
| 290 | } | 
| 291 |  | 
| 292 | void GraphModifier::toggleSurfaceGridS2(bool enable) | 
| 293 | { | 
| 294 |     qDebug() << __FUNCTION__ << enable; | 
| 295 |     if (enable) | 
| 296 |         m_drawMode2 |= QSurface3DSeries::DrawWireframe; | 
| 297 |     else | 
| 298 |         m_drawMode2 &= ~QSurface3DSeries::DrawWireframe; | 
| 299 |  | 
| 300 |     m_multiseries[1]->setDrawMode(m_drawMode2); | 
| 301 | } | 
| 302 |  | 
| 303 | void GraphModifier::toggleSurfaceS2(bool enable) | 
| 304 | { | 
| 305 |     qDebug() << __FUNCTION__ << enable; | 
| 306 |     if (enable) | 
| 307 |         m_drawMode2 |= QSurface3DSeries::DrawSurface; | 
| 308 |     else | 
| 309 |         m_drawMode2 &= ~QSurface3DSeries::DrawSurface; | 
| 310 |  | 
| 311 |     m_multiseries[1]->setDrawMode(m_drawMode2); | 
| 312 | } | 
| 313 |  | 
| 314 | void GraphModifier::toggleSeries2Visible(bool enable) | 
| 315 | { | 
| 316 |     qDebug() << __FUNCTION__ << enable; | 
| 317 |     m_multiseries[1]->setVisible(enable); | 
| 318 | } | 
| 319 |  | 
| 320 | void GraphModifier::toggleSmoothS3(bool enabled) | 
| 321 | { | 
| 322 |     qDebug() << __FUNCTION__ << enabled; | 
| 323 |     m_multiseries[2]->setFlatShadingEnabled(enabled); | 
| 324 | } | 
| 325 |  | 
| 326 | void GraphModifier::toggleSurfaceGridS3(bool enable) | 
| 327 | { | 
| 328 |     qDebug() << __FUNCTION__ << enable; | 
| 329 |     if (enable) | 
| 330 |         m_drawMode3 |= QSurface3DSeries::DrawWireframe; | 
| 331 |     else | 
| 332 |         m_drawMode3 &= ~QSurface3DSeries::DrawWireframe; | 
| 333 |  | 
| 334 |     m_multiseries[2]->setDrawMode(m_drawMode3); | 
| 335 | } | 
| 336 |  | 
| 337 | void GraphModifier::toggleSurfaceS3(bool enable) | 
| 338 | { | 
| 339 |     qDebug() << __FUNCTION__ << enable; | 
| 340 |     if (enable) | 
| 341 |         m_drawMode3 |= QSurface3DSeries::DrawSurface; | 
| 342 |     else | 
| 343 |         m_drawMode3 &= ~QSurface3DSeries::DrawSurface; | 
| 344 |  | 
| 345 |     m_multiseries[2]->setDrawMode(m_drawMode3); | 
| 346 | } | 
| 347 |  | 
| 348 | void GraphModifier::toggleSeries3Visible(bool enable) | 
| 349 | { | 
| 350 |     qDebug() << __FUNCTION__ << enable; | 
| 351 |     m_multiseries[2]->setVisible(enable); | 
| 352 | } | 
| 353 |  | 
| 354 | void GraphModifier::toggleSmoothS4(bool enabled) | 
| 355 | { | 
| 356 |     qDebug() << __FUNCTION__ << enabled; | 
| 357 |     m_multiseries[3]->setFlatShadingEnabled(enabled); | 
| 358 | } | 
| 359 |  | 
| 360 | void GraphModifier::toggleSurfaceGridS4(bool enable) | 
| 361 | { | 
| 362 |     qDebug() << __FUNCTION__ << enable; | 
| 363 |     if (enable) | 
| 364 |         m_drawMode4 |= QSurface3DSeries::DrawWireframe; | 
| 365 |     else | 
| 366 |         m_drawMode4 &= ~QSurface3DSeries::DrawWireframe; | 
| 367 |  | 
| 368 |     m_multiseries[3]->setDrawMode(m_drawMode4); | 
| 369 | } | 
| 370 |  | 
| 371 | void GraphModifier::toggleSurfaceS4(bool enable) | 
| 372 | { | 
| 373 |     qDebug() << __FUNCTION__ << enable; | 
| 374 |     if (enable) | 
| 375 |         m_drawMode4 |= QSurface3DSeries::DrawSurface; | 
| 376 |     else | 
| 377 |         m_drawMode4 &= ~QSurface3DSeries::DrawSurface; | 
| 378 |  | 
| 379 |     m_multiseries[3]->setDrawMode(m_drawMode4); | 
| 380 | } | 
| 381 |  | 
| 382 | void GraphModifier::toggleSeries4Visible(bool enable) | 
| 383 | { | 
| 384 |     qDebug() << __FUNCTION__ << enable; | 
| 385 |     m_multiseries[3]->setVisible(enable); | 
| 386 | } | 
| 387 |  | 
| 388 | void GraphModifier::toggleSqrtSin(bool enable) | 
| 389 | { | 
| 390 |     if (enable) { | 
| 391 |         qDebug() << "Create Sqrt&Sin surface, ("  << m_xCount << ", "  << m_zCount << ")" ; | 
| 392 |  | 
| 393 |         float minX = -10.0f; | 
| 394 |         float maxX = 10.0f; | 
| 395 |         float minZ = -10.0f; | 
| 396 |         float maxZ = 10.0f; | 
| 397 |         float stepX = (maxX - minX) / float(m_xCount - 1); | 
| 398 |         float stepZ = (maxZ - minZ) / float(m_zCount - 1); | 
| 399 |  | 
| 400 |         QSurfaceDataArray *dataArray = new QSurfaceDataArray; | 
| 401 |         dataArray->reserve(alloc: m_zCount); | 
| 402 |         for (float i = 0; i < m_zCount; i++) { | 
| 403 |             QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 404 |             // Keep values within range bounds, since just adding step can cause minor drift due | 
| 405 |             // to the rounding errors. | 
| 406 |             float z = qMin(a: maxZ, b: (i * stepZ + minZ)); | 
| 407 |             for (float j = 0; j < m_xCount; j++) { | 
| 408 |                 float x = qMin(a: maxX, b: (j * stepX + minX)); | 
| 409 |                 float R = qSqrt(v: x * x + z * z) + 0.01f; | 
| 410 |                 float y = (qSin(v: R) / R + 0.24f) * 1.61f + 1.0f; | 
| 411 |                 (*newRow)[j].setPosition(QVector3D(x, y, z)); | 
| 412 |             } | 
| 413 |             *dataArray << newRow; | 
| 414 |         } | 
| 415 |  | 
| 416 |         m_graph->axisY()->setRange(min: 1.0, max: 3.0); | 
| 417 |         m_graph->axisX()->setLabelFormat("%.2f" ); | 
| 418 |         m_graph->axisZ()->setLabelFormat("%.2f" ); | 
| 419 |  | 
| 420 |         m_theSeries->setName("Sqrt & Sin" ); | 
| 421 |  | 
| 422 |         resetArrayAndSliders(array: dataArray, minZ, maxZ, minX, maxX); | 
| 423 |  | 
| 424 |         m_activeSample = GraphModifier::SqrtSin; | 
| 425 |     } else { | 
| 426 |         qDebug() << "Remove surface" ; | 
| 427 |     } | 
| 428 | } | 
| 429 |  | 
| 430 | void GraphModifier::togglePlane(bool enable) | 
| 431 | { | 
| 432 |     qDebug() << "GraphModifier::togglePlane "  << enable; | 
| 433 |  | 
| 434 |     if (enable) { | 
| 435 |         m_planeArray = new QSurfaceDataArray; | 
| 436 |  | 
| 437 | #ifdef JITTER_PLANE | 
| 438 |         m_timer.start(0); | 
| 439 | #endif | 
| 440 |         m_graph->axisY()->setRange(min: 0.0, max: 1.0); | 
| 441 |         m_graph->axisX()->setLabelFormat("%.2f" ); | 
| 442 |         m_graph->axisZ()->setLabelFormat("%.2f" ); | 
| 443 |  | 
| 444 |         m_planeArray->reserve(alloc: m_zCount); | 
| 445 |         float minX = -10.0f; | 
| 446 |         float maxX = 20.0f; | 
| 447 |         float minZ = -10.0f; | 
| 448 |         float maxZ = 10.0f; | 
| 449 |         float stepX = (maxX - minX) / float(m_xCount - 1); | 
| 450 |         float stepZ = (maxZ - minZ) / float(m_zCount - 1); | 
| 451 | #ifdef WONKY_PLANE | 
| 452 |         float halfZ = m_zCount / 2; | 
| 453 |         float wonkyFactor = 0.01f; | 
| 454 |         float maxStepX = 0.0f; | 
| 455 |         float add = 0.0f; | 
| 456 |         for (float i = 0; i < m_zCount; i++) { | 
| 457 |             QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 458 |             if (i < halfZ) { | 
| 459 |                 stepX += wonkyFactor; | 
| 460 |                 maxStepX = stepX; | 
| 461 |             } else { | 
| 462 |                 stepX -= wonkyFactor; | 
| 463 |             } | 
| 464 |             add = 0.0f; | 
| 465 |             for (float j = 0; j < m_xCount; j++) { | 
| 466 |                 (*newRow)[j].setPosition(QVector3D(j * stepX + minX, -0.04f, | 
| 467 |                                                    i * stepZ + minZ + add)); | 
| 468 |                 add += 0.5f; | 
| 469 |  | 
| 470 |             } | 
| 471 |             *m_planeArray << newRow; | 
| 472 |         } | 
| 473 |  | 
| 474 |         m_theSeries->setName("Wonky Plane" ); | 
| 475 |  | 
| 476 |         resetArrayAndSliders(m_planeArray, minZ, maxZ + add, minX, m_xCount * maxStepX + minX); | 
| 477 | #else | 
| 478 |         for (float i = 0; i < m_zCount; i++) { | 
| 479 |             QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 480 |             // Keep values within range bounds, since just adding step can cause minor drift due | 
| 481 |             // to the rounding errors. | 
| 482 |             float zVal; | 
| 483 |             if (i == (m_zCount - 1)) | 
| 484 |                 zVal = maxZ; | 
| 485 |             else | 
| 486 |                 zVal = i * stepZ + minZ; | 
| 487 |  | 
| 488 |             float j = 0; | 
| 489 |             for (; j < m_xCount - 1; j++) | 
| 490 |                 (*newRow)[j].setPosition(QVector3D(j * stepX + minX, -0.04f, zVal)); | 
| 491 |             (*newRow)[j].setPosition(QVector3D(maxX, -0.04f, zVal)); | 
| 492 |  | 
| 493 |             *m_planeArray << newRow; | 
| 494 |         } | 
| 495 |  | 
| 496 |         m_theSeries->setName("Plane" ); | 
| 497 |  | 
| 498 |         resetArrayAndSliders(array: m_planeArray, minZ, maxZ, minX, maxX); | 
| 499 | #endif | 
| 500 |  | 
| 501 |         m_activeSample = GraphModifier::Plane; | 
| 502 |     } | 
| 503 | #ifdef JITTER_PLANE | 
| 504 |     else { | 
| 505 |         m_timer.stop(); | 
| 506 |     } | 
| 507 | #endif | 
| 508 | } | 
| 509 |  | 
| 510 | void GraphModifier::setHeightMapData(bool enable) | 
| 511 | { | 
| 512 |     if (enable) { | 
| 513 |         // Do the height map the hard way. | 
| 514 |         // Easier alternative would be to use the QHeightMapSurfaceDataProxy. | 
| 515 |         QImage image(":/maps/map" ); | 
| 516 |  | 
| 517 |         QSurfaceDataArray *dataArray = new QSurfaceDataArray; | 
| 518 |         uchar *bits = image.bits(); | 
| 519 |  | 
| 520 |         int p = image.width() * 4 * (image.height() - 1); | 
| 521 |         dataArray->reserve(alloc: image.height()); | 
| 522 |         float minX = 34.0; | 
| 523 |         float maxX = 40.0; | 
| 524 |         float minZ = 18.0; | 
| 525 |         float maxZ = 24.0; | 
| 526 |         float xMul = (maxX - minX) / float(image.width() - 1); | 
| 527 |         float zMul = (maxZ - minZ) / float(image.height() - 1); | 
| 528 |         for (int i = 0; i < image.height(); i++, p -= image.width() * 4) { | 
| 529 |             QSurfaceDataRow *newRow = new QSurfaceDataRow(image.width()); | 
| 530 |             for (int j = 0; j < image.width(); j++) { | 
| 531 |                 (*newRow)[j].setPosition(QVector3D((float(j) * xMul) + minX, | 
| 532 |                                                    (float(bits[p + (j * 4)]) + 1.0f) / 1.0f, | 
| 533 |                                                    (float(i) * zMul) + minZ)); | 
| 534 |             } | 
| 535 |             *dataArray << newRow; | 
| 536 |         } | 
| 537 |  | 
| 538 |         m_graph->axisY()->setAutoAdjustRange(true); | 
| 539 |         m_graph->axisX()->setLabelFormat("%.1f N" ); | 
| 540 |         m_graph->axisZ()->setLabelFormat("%.1f E" ); | 
| 541 |  | 
| 542 |         m_theSeries->setName("Height Map" ); | 
| 543 |  | 
| 544 |         resetArrayAndSliders(array: dataArray, minZ, maxZ, minX, maxX); | 
| 545 |  | 
| 546 |         m_activeSample = GraphModifier::Map; | 
| 547 |     } | 
| 548 | } | 
| 549 |  | 
| 550 | void GraphModifier::toggleGridSliderLock(bool enable) | 
| 551 | { | 
| 552 |     m_gridSlidersLocked = enable; | 
| 553 |     if (m_gridSlidersLocked) { | 
| 554 |         m_gridSliderZ->setEnabled(false); | 
| 555 |         m_gridSliderZ->setValue(m_gridSliderX->value()); | 
| 556 |     } else { | 
| 557 |         m_gridSliderZ->setEnabled(true); | 
| 558 |     } | 
| 559 | } | 
| 560 |  | 
| 561 | void GraphModifier::adjustXCount(int count) | 
| 562 | { | 
| 563 |     m_xCount = count; | 
| 564 |     if (m_gridSlidersLocked) | 
| 565 |         m_gridSliderZ->setValue(count); | 
| 566 |  | 
| 567 |     updateSamples(); | 
| 568 |  | 
| 569 |     qDebug() << "X count ="  << count; | 
| 570 | } | 
| 571 |  | 
| 572 | void GraphModifier::adjustZCount(int count) | 
| 573 | { | 
| 574 |     m_zCount = count; | 
| 575 |  | 
| 576 |     updateSamples(); | 
| 577 |  | 
| 578 |     qDebug() << "Z count ="  << count; | 
| 579 | } | 
| 580 |  | 
| 581 | void GraphModifier::adjustXRange(int range) | 
| 582 | { | 
| 583 |     m_rangeX = range; | 
| 584 |     m_graph->axisX()->setRange(min: m_minX, max: m_minX + m_rangeX); | 
| 585 |  | 
| 586 |     qDebug() << "X Range ="  << range; | 
| 587 | } | 
| 588 |  | 
| 589 | void GraphModifier::adjustYRange(int range) | 
| 590 | { | 
| 591 |     m_rangeY = range; | 
| 592 |     m_graph->axisY()->setRange(min: m_minY, max: m_minY + m_rangeY); | 
| 593 |  | 
| 594 |     qDebug() << "Y Range ="  << range; | 
| 595 | } | 
| 596 |  | 
| 597 | void GraphModifier::adjustZRange(int range) | 
| 598 | { | 
| 599 |     m_rangeZ = range; | 
| 600 |     m_graph->axisZ()->setRange(min: m_minZ, max: m_minZ + m_rangeZ); | 
| 601 |  | 
| 602 |     qDebug() << "Z Range ="  << range; | 
| 603 | } | 
| 604 |  | 
| 605 | void GraphModifier::adjustXMin(int min) | 
| 606 | { | 
| 607 |     m_minX = min; | 
| 608 |     m_graph->axisX()->setRange(min: m_minX, max: m_minX + m_rangeX); | 
| 609 |  | 
| 610 |     qDebug() << "X Minimum ="  << min; | 
| 611 | } | 
| 612 |  | 
| 613 | void GraphModifier::adjustYMin(int min) | 
| 614 | { | 
| 615 |     m_minY = min; | 
| 616 |     m_graph->axisY()->setRange(min: m_minY, max: m_minY + m_rangeY); | 
| 617 |  | 
| 618 |     qDebug() << "Y Minimum ="  << min; | 
| 619 | } | 
| 620 |  | 
| 621 | void GraphModifier::adjustZMin(int min) | 
| 622 | { | 
| 623 |     m_minZ = min; | 
| 624 |     m_graph->axisZ()->setRange(min: m_minZ, max: m_minZ + m_rangeZ); | 
| 625 |  | 
| 626 |     qDebug() << "Z Minimum ="  << min; | 
| 627 | } | 
| 628 |  | 
| 629 | void GraphModifier::gradientPressed() | 
| 630 | { | 
| 631 |     static Q3DTheme::ColorStyle colorStyle = Q3DTheme::ColorStyleUniform; | 
| 632 |  | 
| 633 |     if (colorStyle == Q3DTheme::ColorStyleRangeGradient) { | 
| 634 |         colorStyle = Q3DTheme::ColorStyleObjectGradient; | 
| 635 |         qDebug() << "Color style: ColorStyleObjectGradient" ; | 
| 636 |     } else if (colorStyle == Q3DTheme::ColorStyleObjectGradient) { | 
| 637 |         colorStyle = Q3DTheme::ColorStyleUniform; | 
| 638 |         qDebug() << "Color style: ColorStyleUniform" ; | 
| 639 |     } else { | 
| 640 |         colorStyle = Q3DTheme::ColorStyleRangeGradient; | 
| 641 |         qDebug() << "Color style: ColorStyleRangeGradient" ; | 
| 642 |     } | 
| 643 |  | 
| 644 |     QLinearGradient gradient; | 
| 645 |     gradient.setColorAt(pos: 0.0, color: Qt::black); | 
| 646 |     gradient.setColorAt(pos: 0.33, color: Qt::blue); | 
| 647 |     gradient.setColorAt(pos: 0.67, color: Qt::red); | 
| 648 |     gradient.setColorAt(pos: 1.0, color: Qt::yellow); | 
| 649 |  | 
| 650 |     QList<QLinearGradient> gradients; | 
| 651 |     gradients << gradient; | 
| 652 |     m_graph->activeTheme()->setBaseGradients(gradients); | 
| 653 |     m_graph->activeTheme()->setColorStyle(colorStyle); | 
| 654 |  | 
| 655 | } | 
| 656 |  | 
| 657 | void GraphModifier::changeFont(const QFont &font) | 
| 658 | { | 
| 659 |     QFont newFont = font; | 
| 660 |     newFont.setPointSizeF(m_fontSize); | 
| 661 |     m_graph->activeTheme()->setFont(newFont); | 
| 662 | } | 
| 663 |  | 
| 664 | void GraphModifier::changeStyle() | 
| 665 | { | 
| 666 |     m_graph->activeTheme()->setLabelBackgroundEnabled(!m_graph->activeTheme()->isLabelBackgroundEnabled()); | 
| 667 | } | 
| 668 |  | 
| 669 | void GraphModifier::selectButtonClicked() | 
| 670 | { | 
| 671 |     QSurfaceDataProxy *proxy = m_theSeries->dataProxy(); | 
| 672 |     int row = QRandomGenerator::global()->bounded(highest: proxy->rowCount()); | 
| 673 |     int col = QRandomGenerator::global()->bounded(highest: proxy->columnCount()); | 
| 674 |  | 
| 675 |     m_theSeries->setSelectedPoint(QPoint(row, col)); | 
| 676 | } | 
| 677 |  | 
| 678 | void GraphModifier::selectedPointChanged(const QPoint &point) | 
| 679 | { | 
| 680 |     QString labelText = QStringLiteral("Selected row: %1, column: %2" ).arg(a: point.x()).arg(a: point.y()); | 
| 681 |     m_selectionInfoLabel->setText(labelText); | 
| 682 | } | 
| 683 |  | 
| 684 | void GraphModifier::changeTheme(int theme) | 
| 685 | { | 
| 686 |     m_graph->activeTheme()->setType(Q3DTheme::Theme(theme)); | 
| 687 | } | 
| 688 |  | 
| 689 |  | 
| 690 | void GraphModifier::flipViews() | 
| 691 | { | 
| 692 |     m_graph->scene()->setSecondarySubviewOnTop(!m_graph->scene()->isSecondarySubviewOnTop()); | 
| 693 | } | 
| 694 |  | 
| 695 | void GraphModifier::timeout() | 
| 696 | { | 
| 697 |     int rows = m_planeArray->size(); | 
| 698 |     int columns = m_planeArray->at(i: 0)->size(); | 
| 699 |  | 
| 700 |     // Induce minor random jitter to the existing plane array | 
| 701 |     for (int i = 0; i < rows; i++) { | 
| 702 |         for (int j = 0; j < columns; j++) { | 
| 703 |             (*m_planeArray->at(i))[j].setX(m_planeArray->at(i)->at(i: j).x() | 
| 704 |                                            * ((float((QRandomGenerator::global()->bounded(highest: 10)) + 5.0f) / 10000.0f) + 0.999f)); | 
| 705 |             (*m_planeArray->at(i))[j].setY(m_planeArray->at(i)->at(i: j).y() | 
| 706 |                                            * ((float((QRandomGenerator::global()->bounded(highest: 10)) + 5.0f) / 1000.0f) + 0.99f) + 0.0001f); | 
| 707 |             (*m_planeArray->at(i))[j].setZ(m_planeArray->at(i)->at(i: j).z() | 
| 708 |                                            * ((float((QRandomGenerator::global()->bounded(highest: 10)) + 5.0f) / 10000.0f) + 0.999f)); | 
| 709 |         } | 
| 710 |     } | 
| 711 |  | 
| 712 |     // Reset same array to make it redraw | 
| 713 |     m_theSeries->dataProxy()->resetArray(newArray: m_planeArray); | 
| 714 | } | 
| 715 |  | 
| 716 | void GraphModifier::graphQueryTimeout() | 
| 717 | { | 
| 718 | #ifndef QT_NO_CURSOR | 
| 719 |     m_graph->scene()->setGraphPositionQuery(m_parentWidget->mapFromGlobal(QCursor::pos())); | 
| 720 |     qDebug() << "pos: "  << (m_parentWidget->mapFromGlobal(QCursor::pos())); | 
| 721 | #else | 
| 722 |     m_graph->scene()->setGraphPositionQuery(QPoint(100, 100)); | 
| 723 | #endif | 
| 724 | } | 
| 725 |  | 
| 726 | void GraphModifier::handleAxisXChanged(QValue3DAxis *axis) | 
| 727 | { | 
| 728 |     qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisX()); | 
| 729 | } | 
| 730 |  | 
| 731 | void GraphModifier::handleAxisYChanged(QValue3DAxis *axis) | 
| 732 | { | 
| 733 |     qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisY()); | 
| 734 | } | 
| 735 |  | 
| 736 | void GraphModifier::handleAxisZChanged(QValue3DAxis *axis) | 
| 737 | { | 
| 738 |     qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisZ()); | 
| 739 | } | 
| 740 |  | 
| 741 | void GraphModifier::handleFpsChange(qreal fps) | 
| 742 | { | 
| 743 |     qDebug() << "FPS:"  << fps; | 
| 744 | } | 
| 745 |  | 
| 746 | void GraphModifier::changeLabelRotation(int rotation) | 
| 747 | { | 
| 748 |     m_graph->axisX()->setLabelAutoRotation(float(rotation)); | 
| 749 |     m_graph->axisY()->setLabelAutoRotation(float(rotation)); | 
| 750 |     m_graph->axisZ()->setLabelAutoRotation(float(rotation)); | 
| 751 | } | 
| 752 |  | 
| 753 | void GraphModifier::toggleAxisTitleVisibility(bool enabled) | 
| 754 | { | 
| 755 |     m_graph->axisX()->setTitleVisible(enabled); | 
| 756 |     m_graph->axisY()->setTitleVisible(enabled); | 
| 757 |     m_graph->axisZ()->setTitleVisible(enabled); | 
| 758 | } | 
| 759 |  | 
| 760 | void GraphModifier::toggleAxisTitleFixed(bool enabled) | 
| 761 | { | 
| 762 |     m_graph->axisX()->setTitleFixed(enabled); | 
| 763 |     m_graph->axisY()->setTitleFixed(enabled); | 
| 764 |     m_graph->axisZ()->setTitleFixed(enabled); | 
| 765 | } | 
| 766 |  | 
| 767 | void GraphModifier::toggleXAscending(bool enabled) | 
| 768 | { | 
| 769 |     m_ascendingX = enabled; | 
| 770 |  | 
| 771 |     // Flip data array contents if necessary | 
| 772 |     foreach (QSurface3DSeries *series, m_graph->seriesList()) { | 
| 773 |         QSurfaceDataArray *array = const_cast<QSurfaceDataArray *>(series->dataProxy()->array()); | 
| 774 |         const int rowCount = array->size(); | 
| 775 |         const int columnCount = array->at(i: 0)->size(); | 
| 776 |         const bool dataAscending = array->at(i: 0)->at(i: 0).x() < array->at(i: 0)->at(i: columnCount - 1).x(); | 
| 777 |         if (dataAscending != enabled) { | 
| 778 |             // Create new array of equal size | 
| 779 |             QSurfaceDataArray *newArray = new QSurfaceDataArray; | 
| 780 |             newArray->reserve(alloc: rowCount); | 
| 781 |             for (int i = 0; i < rowCount; i++) | 
| 782 |                 newArray->append(t: new QSurfaceDataRow(columnCount)); | 
| 783 |  | 
| 784 |             // Flip each row | 
| 785 |             for (int i = 0; i < rowCount; i++) { | 
| 786 |                 QSurfaceDataRow *oldRow = array->at(i); | 
| 787 |                 QSurfaceDataRow *newRow = newArray->at(i); | 
| 788 |                 for (int j = 0; j < columnCount; j++) | 
| 789 |                     (*newRow)[j] = oldRow->at(i: columnCount - 1 - j); | 
| 790 |             } | 
| 791 |  | 
| 792 |             series->dataProxy()->resetArray(newArray); | 
| 793 |         } | 
| 794 |     } | 
| 795 | } | 
| 796 |  | 
| 797 | void GraphModifier::toggleZAscending(bool enabled) | 
| 798 | { | 
| 799 |     m_ascendingZ = enabled; | 
| 800 |  | 
| 801 |     // Flip data array contents if necessary | 
| 802 |     foreach (QSurface3DSeries *series, m_graph->seriesList()) { | 
| 803 |         QSurfaceDataArray *array = const_cast<QSurfaceDataArray *>(series->dataProxy()->array()); | 
| 804 |         const int rowCount = array->size(); | 
| 805 |         const int columnCount = array->at(i: 0)->size(); | 
| 806 |         const bool dataAscending = array->at(i: 0)->at(i: 0).z() < array->at(i: rowCount - 1)->at(i: 0).z(); | 
| 807 |         if (dataAscending != enabled) { | 
| 808 |             // Create new array of equal size | 
| 809 |             QSurfaceDataArray *newArray = new QSurfaceDataArray; | 
| 810 |             newArray->reserve(alloc: rowCount); | 
| 811 |             for (int i = 0; i < rowCount; i++) | 
| 812 |                 newArray->append(t: new QSurfaceDataRow(columnCount)); | 
| 813 |  | 
| 814 |             // Flip each column | 
| 815 |             for (int i = 0; i < rowCount; i++) { | 
| 816 |                 QSurfaceDataRow *oldRow = array->at(i: rowCount - 1 - i); | 
| 817 |                 QSurfaceDataRow *newRow = newArray->at(i); | 
| 818 |                 for (int j = 0; j < columnCount; j++) | 
| 819 |                     (*newRow)[j] = oldRow->at(i: j); | 
| 820 |             } | 
| 821 |  | 
| 822 |             series->dataProxy()->resetArray(newArray); | 
| 823 |         } | 
| 824 |     } | 
| 825 | } | 
| 826 |  | 
| 827 | void GraphModifier::togglePolar(bool enabled) | 
| 828 | { | 
| 829 |     m_graph->setPolar(enabled); | 
| 830 | } | 
| 831 |  | 
| 832 | void GraphModifier::setCameraTargetX(int value) | 
| 833 | { | 
| 834 |     // Value is (-100, 100), normalize | 
| 835 |     m_cameraTarget.setX(float(value) / 100.0f); | 
| 836 |     m_graph->scene()->activeCamera()->setTarget(m_cameraTarget); | 
| 837 |     qDebug() << "m_cameraTarget:"  << m_cameraTarget; | 
| 838 | } | 
| 839 |  | 
| 840 | void GraphModifier::setCameraTargetY(int value) | 
| 841 | { | 
| 842 |     // Value is (-100, 100), normalize | 
| 843 |     m_cameraTarget.setY(float(value) / 100.0f); | 
| 844 |     m_graph->scene()->activeCamera()->setTarget(m_cameraTarget); | 
| 845 |     qDebug() << "m_cameraTarget:"  << m_cameraTarget; | 
| 846 | } | 
| 847 |  | 
| 848 | void GraphModifier::setCameraTargetZ(int value) | 
| 849 | { | 
| 850 |     // Value is (-100, 100), normalize | 
| 851 |     m_cameraTarget.setZ(float(value) / 100.0f); | 
| 852 |     m_graph->scene()->activeCamera()->setTarget(m_cameraTarget); | 
| 853 |     qDebug() << "m_cameraTarget:"  << m_cameraTarget; | 
| 854 | } | 
| 855 |  | 
| 856 | void GraphModifier::setGraphMargin(int value) | 
| 857 | { | 
| 858 |     m_graph->setMargin(qreal(value) / 100.0); | 
| 859 |     qDebug() << "Setting margin:"  << m_graph->margin() << value; | 
| 860 | } | 
| 861 |  | 
| 862 | void GraphModifier::resetArrayAndSliders(QSurfaceDataArray *array, float minZ, float maxZ, float minX, float maxX) | 
| 863 | { | 
| 864 |     m_axisMinSliderX->setValue(minX); | 
| 865 |     m_axisMinSliderZ->setValue(minZ); | 
| 866 |     m_axisRangeSliderX->setValue(maxX - minX); | 
| 867 |     m_axisRangeSliderZ->setValue(maxZ - minZ); | 
| 868 |  | 
| 869 |     m_theSeries->dataProxy()->resetArray(newArray: array); | 
| 870 | } | 
| 871 |  | 
| 872 | void GraphModifier::changeShadowQuality(int quality) | 
| 873 | { | 
| 874 |     QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality); | 
| 875 |     m_graph->setShadowQuality(sq); | 
| 876 | } | 
| 877 |  | 
| 878 | void GraphModifier::changeSelectionMode(int mode) | 
| 879 | { | 
| 880 |     QComboBox *comboBox = qobject_cast<QComboBox *>(object: sender()); | 
| 881 |     if (comboBox) { | 
| 882 |         int flags = comboBox->itemData(index: mode).toInt(); | 
| 883 |         m_graph->setSelectionMode(QAbstract3DGraph::SelectionFlags(flags)); | 
| 884 |     } | 
| 885 | } | 
| 886 |  | 
| 887 | void GraphModifier::changeRow() | 
| 888 | { | 
| 889 |     if (m_activeSample == GraphModifier::SqrtSin) { | 
| 890 |         qDebug() << "Generating new values to a row at random pos" ; | 
| 891 |         float minX = -10.0f; | 
| 892 |         float maxX = 10.0f; | 
| 893 |         float minZ = -10.0f; | 
| 894 |         float maxZ = 10.0f; | 
| 895 |         float stepX = (maxX - minX) / float(m_xCount - 1); | 
| 896 |         float stepZ = (maxZ - minZ) / float(m_zCount - 1); | 
| 897 |         float i = float(QRandomGenerator::global()->bounded(highest: m_zCount)); | 
| 898 |  | 
| 899 |         QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 900 |         float z = qMin(a: maxZ, b: (i * stepZ + minZ)); | 
| 901 |         for (float j = 0; j < m_xCount; j++) { | 
| 902 |             float x = qMin(a: maxX, b: (j * stepX + minX)); | 
| 903 |             float R = qSqrt(v: x * x + z * z) + 0.01f; | 
| 904 |             float y = (qSin(v: R) / R + 0.24f) * 1.61f + 1.2f; | 
| 905 |             (*newRow)[j].setPosition(QVector3D(x, y, z)); | 
| 906 |         } | 
| 907 |  | 
| 908 |         m_theSeries->dataProxy()->setRow(rowIndex: int(i), row: newRow); | 
| 909 |     } else { | 
| 910 | #ifdef MULTI_SERIES | 
| 911 |         static int changeRowSeries = 0; | 
| 912 |         qDebug() << "Generating new values to a row at random pos for series "  << changeRowSeries; | 
| 913 |  | 
| 914 |         int row = QRandomGenerator::global()->bounded(highest: m_zCount); | 
| 915 |         QSurfaceDataRow *newRow = createMultiRow(row, series: changeRowSeries, change: true); | 
| 916 |         if (m_ascendingZ) | 
| 917 |             m_multiseries[changeRowSeries]->dataProxy()->setRow(rowIndex: row, row: newRow); | 
| 918 |         else | 
| 919 |             m_multiseries[changeRowSeries]->dataProxy()->setRow(rowIndex: (m_zCount - 1) - row, row: newRow); | 
| 920 |  | 
| 921 |         changeRowSeries++; | 
| 922 |         if (changeRowSeries > 3) | 
| 923 |             changeRowSeries = 0; | 
| 924 | #else | 
| 925 |         qDebug() << "Change row function active only for SqrtSin" ; | 
| 926 | #endif | 
| 927 |     } | 
| 928 | } | 
| 929 |  | 
| 930 | QSurfaceDataRow *GraphModifier::createMultiRow(int row, int series, bool change) | 
| 931 | { | 
| 932 |     int full = m_limitX * m_limitZ; | 
| 933 |     float i = float(row); | 
| 934 |     QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 935 |     float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[series]; | 
| 936 |     if (m_ascendingX) { | 
| 937 |         for (int j = 0; j < m_xCount; j++) { | 
| 938 |             float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[series]; | 
| 939 |             float angle = (z * x) / float(full) * 1.57f; | 
| 940 |             float y = qSin(v: angle * float(qPow(x: 1.3f, y: series))) + 0.2f * float(change) + 1.1f *series; | 
| 941 |             (*newRow)[j].setPosition(QVector3D(x, y, z)); | 
| 942 |         } | 
| 943 |     } else { | 
| 944 |         for (int j = m_xCount - 1; j >= 0 ; j--) { | 
| 945 |             float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[series]; | 
| 946 |             float angle = (z * x) / float(full) * 1.57f; | 
| 947 |             float y = qSin(v: angle * float(qPow(x: 1.3f, y: series))) + 0.2f * float(change) + 1.1f *series; | 
| 948 |             (*newRow)[(m_xCount - 1) - j].setPosition(QVector3D(x, y, z)); | 
| 949 |         } | 
| 950 |     } | 
| 951 |  | 
| 952 |     return newRow; | 
| 953 | } | 
| 954 |  | 
| 955 | void GraphModifier::populateRisingSeries(QSurface3DSeries *series, int rows, int columns, | 
| 956 |                                          float minValue, float maxValue, bool ascendingX, | 
| 957 |                                          bool ascendingZ) | 
| 958 | { | 
| 959 |     QSurfaceDataArray *dataArray = new QSurfaceDataArray; | 
| 960 |     dataArray->reserve(alloc: rows); | 
| 961 |     float range = maxValue - minValue; | 
| 962 |     int arraySize = rows * columns; | 
| 963 |     for (int i = 0; i < rows; i++) { | 
| 964 |         QSurfaceDataRow *dataRow = new QSurfaceDataRow(columns); | 
| 965 |         for (int j = 0; j < columns; j++) { | 
| 966 |             float xValue = ascendingX ? float(j) : float(columns - j - 1); | 
| 967 |             float yValue = minValue + (range * i * j / arraySize); | 
| 968 |             float zValue = ascendingZ ? float(i) : float(rows - i - 1); | 
| 969 |             (*dataRow)[j].setPosition(QVector3D(xValue, yValue, zValue)); | 
| 970 |         } | 
| 971 |         dataArray->append(t: dataRow); | 
| 972 |     } | 
| 973 |     series->dataProxy()->resetArray(newArray: dataArray); | 
| 974 |  | 
| 975 | } | 
| 976 |  | 
| 977 | void GraphModifier::changeRows() | 
| 978 | { | 
| 979 |     if (m_activeSample == GraphModifier::SqrtSin) { | 
| 980 |         qDebug() << "Generating new values to 3 rows from random pos" ; | 
| 981 |  | 
| 982 |         float minX = -10.0f; | 
| 983 |         float maxX = 10.0f; | 
| 984 |         float minZ = -10.0f; | 
| 985 |         float maxZ = 10.0f; | 
| 986 |         float stepX = (maxX - minX) / float(m_xCount - 1); | 
| 987 |         float stepZ = (maxZ - minZ) / float(m_zCount - 1); | 
| 988 |         float start = float(QRandomGenerator::global()->bounded(highest: m_zCount - 3)); | 
| 989 |  | 
| 990 |         QSurfaceDataArray dataArray; | 
| 991 |  | 
| 992 |         for (float i = start; i < (start + 3.0f); i++) { | 
| 993 |             QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 994 |             float z = qMin(a: maxZ, b: (i * stepZ + minZ)); | 
| 995 |             for (float j = 0; j < m_xCount; j++) { | 
| 996 |                 float x = qMin(a: maxX, b: (j * stepX + minX)); | 
| 997 |                 float R = qSqrt(v: x * x + z * z) + 0.01f; | 
| 998 |                 float y = (qSin(v: R) / R + 0.24f) * 1.61f + 1.2f; | 
| 999 |                 (*newRow)[j].setPosition(QVector3D(x, y, z)); | 
| 1000 |             } | 
| 1001 |             dataArray.append(t: newRow); | 
| 1002 |         } | 
| 1003 |  | 
| 1004 |         m_theSeries->dataProxy()->setRows(rowIndex: int(start), rows: dataArray); | 
| 1005 |     } else { | 
| 1006 | #ifdef MULTI_SERIES | 
| 1007 |         static int changeRowSeries = 0; | 
| 1008 |         qDebug() << "Generating new values for 3 rows at random pos for series "  << changeRowSeries; | 
| 1009 |  | 
| 1010 |         int row = QRandomGenerator::global()->bounded(highest: m_zCount - 3); | 
| 1011 |         QSurfaceDataArray dataArray; | 
| 1012 |         for (int i = 0; i < 3; i++) { | 
| 1013 |             QSurfaceDataRow *newRow = createMultiRow(row: row + i, series: changeRowSeries, change: true); | 
| 1014 |             dataArray.append(t: newRow); | 
| 1015 |         } | 
| 1016 |         m_multiseries[changeRowSeries]->dataProxy()->setRows(rowIndex: row, rows: dataArray); | 
| 1017 |  | 
| 1018 |         changeRowSeries++; | 
| 1019 |         if (changeRowSeries > 3) | 
| 1020 |             changeRowSeries = 0; | 
| 1021 | #else | 
| 1022 |         qDebug() << "Change row function active only for SqrtSin" ; | 
| 1023 | #endif | 
| 1024 |     } | 
| 1025 | } | 
| 1026 |  | 
| 1027 | void GraphModifier::changeItem() | 
| 1028 | { | 
| 1029 |     if (m_activeSample == GraphModifier::SqrtSin) { | 
| 1030 |         qDebug() << "Generating new values for an item at random pos" ; | 
| 1031 |         float minX = -10.0f; | 
| 1032 |         float maxX = 10.0f; | 
| 1033 |         float minZ = -10.0f; | 
| 1034 |         float maxZ = 10.0f; | 
| 1035 |         float stepX = (maxX - minX) / float(m_xCount - 1); | 
| 1036 |         float stepZ = (maxZ - minZ) / float(m_zCount - 1); | 
| 1037 |         float i = float(QRandomGenerator::global()->bounded(highest: m_zCount)); | 
| 1038 |         float j = float(QRandomGenerator::global()->bounded(highest: m_xCount)); | 
| 1039 |  | 
| 1040 |         float x = qMin(a: maxX, b: (j * stepX + minX)); | 
| 1041 |         float z = qMin(a: maxZ, b: (i * stepZ + minZ)); | 
| 1042 |         float R = qSqrt(v: x * x + z * z) + 0.01f; | 
| 1043 |         float y = (qSin(v: R) / R + 0.24f) * 1.61f + 1.2f; | 
| 1044 |         QSurfaceDataItem newItem(QVector3D(x, y, z)); | 
| 1045 |  | 
| 1046 |         m_theSeries->dataProxy()->setItem(rowIndex: int(i), columnIndex: int(j), item: newItem); | 
| 1047 |     } else { | 
| 1048 | #ifdef MULTI_SERIES | 
| 1049 |         static int changeItemSeries = 0; | 
| 1050 |         int full = m_limitX * m_limitZ; | 
| 1051 |         float i = float(QRandomGenerator::global()->bounded(highest: m_zCount)); | 
| 1052 |         float j = float(QRandomGenerator::global()->bounded(highest: m_xCount)); | 
| 1053 |         float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[changeItemSeries]; | 
| 1054 |         float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[changeItemSeries]; | 
| 1055 |         float angle = (z * x) / float(full) * 1.57f; | 
| 1056 |         float y = qSin(v: angle * float(qPow(x: 1.3f, y: changeItemSeries))) + 0.2f + 1.1f *changeItemSeries; | 
| 1057 |         QSurfaceDataItem newItem(QVector3D(x, y, z)); | 
| 1058 |  | 
| 1059 |         if (m_ascendingZ && m_ascendingX) | 
| 1060 |             m_multiseries[changeItemSeries]->dataProxy()->setItem(rowIndex: int(i), columnIndex: int(j), item: newItem); | 
| 1061 |         else if (!m_ascendingZ && m_ascendingX) | 
| 1062 |             m_multiseries[changeItemSeries]->dataProxy()->setItem(rowIndex: m_zCount - 1 - int(i), columnIndex: int(j), item: newItem); | 
| 1063 |         else if (m_ascendingZ && !m_ascendingX) | 
| 1064 |             m_multiseries[changeItemSeries]->dataProxy()->setItem(rowIndex: int(i), columnIndex: m_xCount - 1 - int(j), item: newItem); | 
| 1065 |         else | 
| 1066 |             m_multiseries[changeItemSeries]->dataProxy()->setItem(rowIndex: m_zCount - 1 - int(i), columnIndex: m_xCount - 1 - int(j), item: newItem); | 
| 1067 |         //m_multiseries[changeItemSeries]->setSelectedPoint(QPoint(i, j)); | 
| 1068 |         changeItemSeries++; | 
| 1069 |         if (changeItemSeries > 3) | 
| 1070 |             changeItemSeries = 0; | 
| 1071 | #else | 
| 1072 |         qDebug() << "Change item function active only for SqrtSin" ; | 
| 1073 | #endif | 
| 1074 |     } | 
| 1075 | } | 
| 1076 |  | 
| 1077 | void GraphModifier::changeMultipleRows() | 
| 1078 | { | 
| 1079 |     for (int i = 0; i < 30; i++) | 
| 1080 |         changeRow(); | 
| 1081 | } | 
| 1082 |  | 
| 1083 | void GraphModifier::changeMultipleItem() | 
| 1084 | { | 
| 1085 |     for (int i = 0; i < 30; i++) | 
| 1086 |         changeItem(); | 
| 1087 | } | 
| 1088 |  | 
| 1089 | void GraphModifier::addRow() | 
| 1090 | { | 
| 1091 |     if (m_activeSample == GraphModifier::SqrtSin) { | 
| 1092 |         qDebug() << "Adding a new row" ; | 
| 1093 |  | 
| 1094 |         float minX = -10.0f; | 
| 1095 |         float maxX = 10.0f; | 
| 1096 |         float minZ = -10.0f; | 
| 1097 |         float maxZ = 10.0f; | 
| 1098 |         float stepX = (maxX - minX) / float(m_xCount - 1); | 
| 1099 |         float stepZ = (maxZ - minZ) / float(m_zCount - 1); | 
| 1100 |  | 
| 1101 |         QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 1102 |         float z = float(m_addRowCounter) * stepZ + minZ; | 
| 1103 |         for (float j = 0; j < m_xCount; j++) { | 
| 1104 |             float x = qMin(a: maxX, b: (j * stepX + minX)); | 
| 1105 |             float R = qSqrt(v: x * x + z * z) + 0.01f; | 
| 1106 |             float y = (qSin(v: R) / R + 0.24f) * 1.61f + 1.0f; | 
| 1107 |             (*newRow)[j].setPosition(QVector3D(x, y, z)); | 
| 1108 |         } | 
| 1109 |         m_addRowCounter++; | 
| 1110 |  | 
| 1111 |         m_theSeries->dataProxy()->addRow(row: newRow); | 
| 1112 |     } else { | 
| 1113 | #ifdef MULTI_SERIES | 
| 1114 |         qDebug() << "Adding a row into series 3" ; | 
| 1115 |         int full = m_limitX * m_limitZ; | 
| 1116 |         int series = 2; | 
| 1117 |  | 
| 1118 |         QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 1119 |         float z = float(m_addRowCounter) - m_limitZ + 0.5f + m_multiSampleOffsetZ[series]; | 
| 1120 |         for (int j = 0; j < m_xCount; j++) { | 
| 1121 |             float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[series]; | 
| 1122 |             float angle = float(z * x) / float(full) * 1.57f; | 
| 1123 |             (*newRow)[j].setPosition(QVector3D(x, qSin(v: angle *float(qPow(x: 1.3f, y: series))) + 1.1f * series, z)); | 
| 1124 |         } | 
| 1125 |         m_addRowCounter++; | 
| 1126 |  | 
| 1127 |         m_multiseries[series]->dataProxy()->addRow(row: newRow); | 
| 1128 | #else | 
| 1129 |             qDebug() << "Add row function active only for SqrtSin" ; | 
| 1130 | #endif | 
| 1131 |     } | 
| 1132 | } | 
| 1133 |  | 
| 1134 | void GraphModifier::addRows() | 
| 1135 | { | 
| 1136 |     if (m_activeSample == GraphModifier::SqrtSin) { | 
| 1137 |         qDebug() << "Adding few new row" ; | 
| 1138 |  | 
| 1139 |         float minX = -10.0f; | 
| 1140 |         float maxX = 10.0f; | 
| 1141 |         float minZ = -10.0f; | 
| 1142 |         float maxZ = 10.0f; | 
| 1143 |         float stepX = (maxX - minX) / float(m_xCount - 1); | 
| 1144 |         float stepZ = (maxZ - minZ) / float(m_zCount - 1); | 
| 1145 |  | 
| 1146 |         QSurfaceDataArray dataArray; | 
| 1147 |  | 
| 1148 |         for (int i = 0; i < 3; i++) { | 
| 1149 |             QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 1150 |             float z = m_addRowCounter * stepZ + minZ; | 
| 1151 |             for (float j = 0; j < m_xCount; j++) { | 
| 1152 |                 float x = qMin(a: maxX, b: (j * stepX + minX)); | 
| 1153 |                 float R = qSqrt(v: x * x + z * z) + 0.01f; | 
| 1154 |                 float y = (qSin(v: R) / R + 0.24f) * 1.61f + 1.0f; | 
| 1155 |                 (*newRow)[j].setPosition(QVector3D(x, y, z)); | 
| 1156 |             } | 
| 1157 |             dataArray.append(t: newRow); | 
| 1158 |             m_addRowCounter++; | 
| 1159 |         } | 
| 1160 |  | 
| 1161 |         m_theSeries->dataProxy()->addRows(rows: dataArray); | 
| 1162 |     } else { | 
| 1163 | #ifdef MULTI_SERIES | 
| 1164 |     qDebug() << "Adding 3 rows into series 3" ; | 
| 1165 |     int changedSeries = 2; | 
| 1166 |  | 
| 1167 |     QSurfaceDataArray dataArray; | 
| 1168 |     for (int i = 0; i < 3; i++) { | 
| 1169 |         QSurfaceDataRow *newRow = createMultiRow(row: m_addRowCounter, series: changedSeries, change: false); | 
| 1170 |         dataArray.append(t: newRow); | 
| 1171 |         m_addRowCounter++; | 
| 1172 |     } | 
| 1173 |  | 
| 1174 |     m_multiseries[changedSeries]->dataProxy()->addRows(rows: dataArray); | 
| 1175 | #else | 
| 1176 |         qDebug() << "Add rows function active only for SqrtSin" ; | 
| 1177 | #endif | 
| 1178 |     } | 
| 1179 | } | 
| 1180 |  | 
| 1181 | void GraphModifier::insertRow() | 
| 1182 | { | 
| 1183 |     if (m_activeSample == GraphModifier::SqrtSin) { | 
| 1184 |         qDebug() << "Inserting a row" ; | 
| 1185 |         float minX = -10.0f; | 
| 1186 |         float maxX = 10.0f; | 
| 1187 |         float minZ = -10.0f; | 
| 1188 |         float maxZ = 10.0f; | 
| 1189 |         float stepX = (maxX - minX) / float(m_xCount - 1); | 
| 1190 |         float stepZ = (maxZ - minZ) / float(m_zCount - 1); | 
| 1191 |  | 
| 1192 |         QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 1193 |         float z = qMin(a: maxZ, b: (float(m_insertTestZPos) * stepZ + minZ + (stepZ / 2.0f))); | 
| 1194 |         for (float j = 0; j < m_xCount; j++) { | 
| 1195 |             float x = qMin(a: maxX, b: (j * stepX + minX)); | 
| 1196 |             float R = qSqrt(v: x * x + z * z) + 0.01f; | 
| 1197 |             float y = (qSin(v: R) / R + 0.24f) * 1.61f + 1.3f; | 
| 1198 |             (*newRow)[j].setPosition(QVector3D(x, y, z)); | 
| 1199 |         } | 
| 1200 |         m_insertTestZPos++; | 
| 1201 |  | 
| 1202 |         m_theSeries->dataProxy()->insertRow(rowIndex: m_insertTestIndexPos, row: newRow); | 
| 1203 |         m_insertTestIndexPos += 2; | 
| 1204 |     } else { | 
| 1205 | #ifdef MULTI_SERIES | 
| 1206 |     qDebug() << "Inserting a row into series 3" ; | 
| 1207 |     int full = m_limitX * m_limitZ; | 
| 1208 |     int changedSeries = 2; | 
| 1209 |  | 
| 1210 |     QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 1211 |     float z = float(m_insertTestZPos) - m_limitZ + m_multiSampleOffsetZ[changedSeries]; | 
| 1212 |     for (int j = 0; j < m_xCount; j++) { | 
| 1213 |         float x = float(j) - m_limitX + m_multiSampleOffsetX[changedSeries]; | 
| 1214 |         float angle = (z * x) / float(full) * 1.57f; | 
| 1215 |         (*newRow)[j].setPosition(QVector3D(x + 0.5f, | 
| 1216 |                                            qSin(v: angle * float(qPow(x: 1.3f, y: changedSeries))) + 1.2f * changedSeries, | 
| 1217 |                                            z + 1.0f)); | 
| 1218 |     } | 
| 1219 |  | 
| 1220 |     m_insertTestZPos++; | 
| 1221 |  | 
| 1222 |     m_multiseries[2]->dataProxy()->insertRow(rowIndex: m_insertTestIndexPos, row: newRow); | 
| 1223 |     m_insertTestIndexPos += 2; | 
| 1224 | #else | 
| 1225 |         qDebug() << "Insert row function active only for SqrtSin" ; | 
| 1226 | #endif | 
| 1227 |     } | 
| 1228 | } | 
| 1229 |  | 
| 1230 | void GraphModifier::insertRows() | 
| 1231 | { | 
| 1232 |     if (m_activeSample == GraphModifier::SqrtSin) { | 
| 1233 |         qDebug() << "Inserting 3 rows" ; | 
| 1234 |         float minX = -10.0f; | 
| 1235 |         float maxX = 10.0f; | 
| 1236 |         float minZ = -10.0f; | 
| 1237 |         float maxZ = 10.0f; | 
| 1238 |         float stepX = (maxX - minX) / float(m_xCount - 1); | 
| 1239 |         float stepZ = (maxZ - minZ) / float(m_zCount - 1); | 
| 1240 |  | 
| 1241 |         QSurfaceDataArray dataArray; | 
| 1242 |         for (int i = 0; i < 3; i++) { | 
| 1243 |             QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 1244 |             float z = qMin(a: maxZ, b: (float(m_insertTestZPos) * stepZ + minZ + i * (stepZ / 4.0f))); | 
| 1245 |             for (float j = 0; j < m_xCount; j++) { | 
| 1246 |                 float x = qMin(a: maxX, b: (j * stepX + minX)); | 
| 1247 |                 float R = qSqrt(v: x * x + z * z) + 0.01f; | 
| 1248 |                 float y = (qSin(v: R) / R + 0.24f) * 1.61f + 1.3f; | 
| 1249 |                 (*newRow)[j].setPosition(QVector3D(x, y, z)); | 
| 1250 |             } | 
| 1251 |             dataArray.append(t: newRow); | 
| 1252 |         } | 
| 1253 |         m_insertTestZPos++; | 
| 1254 |  | 
| 1255 |         m_theSeries->dataProxy()->insertRows(rowIndex: m_insertTestIndexPos, rows: dataArray); | 
| 1256 |         m_insertTestIndexPos += 4; | 
| 1257 |     } else { | 
| 1258 | #ifdef MULTI_SERIES | 
| 1259 |     qDebug() << "Inserting 3 rows into series 3" ; | 
| 1260 |     int full = m_limitX * m_limitZ; | 
| 1261 |     int changedSeries = 2; | 
| 1262 |  | 
| 1263 |     QSurfaceDataArray dataArray; | 
| 1264 |     float zAdd = 0.25f; | 
| 1265 |     for (int i = 0; i < 3; i++) { | 
| 1266 |         QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); | 
| 1267 |         float z = float(m_insertTestZPos) - m_limitZ  + 0.5f + zAdd + m_multiSampleOffsetZ[changedSeries]; | 
| 1268 |         for (int j = 0; j < m_xCount; j++) { | 
| 1269 |             float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[changedSeries]; | 
| 1270 |             float angle = (z * x) / float(full) * 1.57f; | 
| 1271 |             float y = qSin(v: angle * float(qPow(x: 1.3f, y: changedSeries))) + + 1.2f * changedSeries; | 
| 1272 |             (*newRow)[j].setPosition(QVector3D(x, y, z)); | 
| 1273 |         } | 
| 1274 |         zAdd += 0.25f; | 
| 1275 |         dataArray.append(t: newRow); | 
| 1276 |     } | 
| 1277 |  | 
| 1278 |     m_insertTestZPos++; | 
| 1279 |  | 
| 1280 |     m_multiseries[2]->dataProxy()->insertRows(rowIndex: m_insertTestIndexPos, rows: dataArray); | 
| 1281 |     m_insertTestIndexPos += 4; | 
| 1282 | #else | 
| 1283 |         qDebug() << "Insert rows function active only for SqrtSin" ; | 
| 1284 | #endif | 
| 1285 |     } | 
| 1286 | } | 
| 1287 |  | 
| 1288 | void GraphModifier::removeRow() | 
| 1289 | { | 
| 1290 |     qDebug() << "Remove an arbitrary row" ; | 
| 1291 |     if (m_zCount < 1) | 
| 1292 |         return; | 
| 1293 |  | 
| 1294 |     int row = QRandomGenerator::global()->bounded(highest: m_zCount); | 
| 1295 |  | 
| 1296 | #ifdef MULTI_SERIES | 
| 1297 |     int series = QRandomGenerator::global()->bounded(highest: 4); | 
| 1298 |     m_multiseries[series]->dataProxy()->removeRows(rowIndex: row, removeCount: 1); | 
| 1299 | #else | 
| 1300 |     m_theSeries->dataProxy()->removeRows(row, 1); | 
| 1301 | #endif | 
| 1302 |     m_zCount--; | 
| 1303 | } | 
| 1304 |  | 
| 1305 | void GraphModifier::resetArray() | 
| 1306 | { | 
| 1307 |     qDebug() << "Reset series data array" ; | 
| 1308 |     int rows = 10; | 
| 1309 |     int columns = 10; | 
| 1310 |     float randFactor = float(QRandomGenerator::global()->bounded(highest: 100)) / 100.0f; | 
| 1311 |     QSurfaceDataArray *planeArray = new QSurfaceDataArray; | 
| 1312 |     planeArray->reserve(alloc: rows); | 
| 1313 |  | 
| 1314 |     for (int i = 0; i < rows; i++) { | 
| 1315 |         planeArray->append(t: new QSurfaceDataRow); | 
| 1316 |         (*planeArray)[i]->resize(asize: columns); | 
| 1317 |         for (int j = 0; j < columns; j++) { | 
| 1318 |             (*planeArray->at(i))[j].setX(float(j) * randFactor); | 
| 1319 |             (*planeArray->at(i))[j].setY(float(i - j) * randFactor); | 
| 1320 |             (*planeArray->at(i))[j].setZ(float(i)); | 
| 1321 |         } | 
| 1322 |     } | 
| 1323 |  | 
| 1324 | #ifdef MULTI_SERIES | 
| 1325 |     int series = QRandomGenerator::global()->bounded(highest: 4); | 
| 1326 |     m_multiseries[series]->dataProxy()->resetArray(newArray: planeArray); | 
| 1327 | #else | 
| 1328 |     m_theSeries->dataProxy()->resetArray(planeArray); | 
| 1329 | #endif | 
| 1330 | } | 
| 1331 |  | 
| 1332 | void GraphModifier::resetArrayEmpty() | 
| 1333 | { | 
| 1334 |     QSurfaceDataArray *emptyArray = new QSurfaceDataArray; | 
| 1335 | #ifdef MULTI_SERIES | 
| 1336 |     int series = QRandomGenerator::global()->bounded(highest: 4); | 
| 1337 |     m_multiseries[series]->dataProxy()->resetArray(newArray: emptyArray); | 
| 1338 | #else | 
| 1339 |     m_theSeries->dataProxy()->resetArray(emptyArray); | 
| 1340 | #endif | 
| 1341 | } | 
| 1342 |  | 
| 1343 | void GraphModifier::massiveDataTest() | 
| 1344 | { | 
| 1345 |     static int testPhase = 0; | 
| 1346 |     static const int cacheSize = 1000; | 
| 1347 |     const int columns = 200; | 
| 1348 |     const int rows = 200000; | 
| 1349 |     const int visibleRows = 200; | 
| 1350 |     const float yRangeMin = 0.0f; | 
| 1351 |     const float yRangeMax = 1.0f; | 
| 1352 |     const float yRangeMargin = 0.05f; | 
| 1353 |     static QTimer *massiveTestTimer = 0; | 
| 1354 |     static QSurface3DSeries *series = new QSurface3DSeries; | 
| 1355 |  | 
| 1356 |     // To speed up massive array creation, we generate a smaller cache array | 
| 1357 |     // and copy rows from that to our main array | 
| 1358 |     if (!m_massiveTestCacheArray.size()) { | 
| 1359 |         m_massiveTestCacheArray.reserve(alloc: cacheSize); | 
| 1360 |         float minY = yRangeMin + yRangeMargin; | 
| 1361 |         float maxY = yRangeMax - yRangeMargin; | 
| 1362 |         float rowBase = minY; | 
| 1363 |         float direction = 1.0f; | 
| 1364 |         for (int i = 0; i < cacheSize; i++) { | 
| 1365 |             m_massiveTestCacheArray.append(t: new QSurfaceDataRow); | 
| 1366 |             m_massiveTestCacheArray[i]->resize(asize: columns); | 
| 1367 |             rowBase += direction * (float(QRandomGenerator::global()->bounded(highest: 3)) / 100.0f); | 
| 1368 |             if (rowBase > maxY) { | 
| 1369 |                 rowBase = maxY; | 
| 1370 |                 direction = -1.0f; | 
| 1371 |             } else if (rowBase < minY) { | 
| 1372 |                 rowBase = minY; | 
| 1373 |                 direction = 1.0f; | 
| 1374 |             } | 
| 1375 |             for (int j = 0; j < columns; j++) { | 
| 1376 |                 float randFactor = float(QRandomGenerator::global()->bounded(highest: 100)) / (100 / yRangeMargin); | 
| 1377 |                 (*m_massiveTestCacheArray.at(i))[j].setX(float(j)); | 
| 1378 |                 (*m_massiveTestCacheArray.at(i))[j].setY(rowBase + randFactor); | 
| 1379 |                 // Z value is irrelevant, we replace it anyway when we take row to use | 
| 1380 |             } | 
| 1381 |         } | 
| 1382 |         massiveTestTimer = new QTimer; | 
| 1383 |     } | 
| 1384 |  | 
| 1385 |     switch (testPhase) { | 
| 1386 |     case 0: { | 
| 1387 |         qDebug() << __FUNCTION__ << testPhase << ": Setting the graph up..." ; | 
| 1388 |         QValue3DAxis *xAxis = new QValue3DAxis(); | 
| 1389 |         QValue3DAxis *yAxis = new QValue3DAxis(); | 
| 1390 |         QValue3DAxis *zAxis = new QValue3DAxis(); | 
| 1391 |         xAxis->setRange(min: 0.0f, max: float(columns)); | 
| 1392 |         yAxis->setRange(min: yRangeMin, max: yRangeMax); | 
| 1393 |         zAxis->setRange(min: 0.0f, max: float(visibleRows)); | 
| 1394 |         xAxis->setSegmentCount(1); | 
| 1395 |         yAxis->setSegmentCount(1); | 
| 1396 |         zAxis->setSegmentCount(1); | 
| 1397 |         m_graph->setMeasureFps(true); | 
| 1398 |         m_graph->setAxisX(xAxis); | 
| 1399 |         m_graph->setAxisY(yAxis); | 
| 1400 |         m_graph->setAxisZ(zAxis); | 
| 1401 |         m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetRight); | 
| 1402 |         m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualityNone); | 
| 1403 |         foreach (QAbstract3DSeries *series, m_graph->seriesList()) | 
| 1404 |             m_graph->removeSeries(series: static_cast<QSurface3DSeries *>(series)); | 
| 1405 |  | 
| 1406 |         qDebug() << __FUNCTION__ << testPhase << ": Creating massive array..."  | 
| 1407 |                  << rows << "x"  << columns; | 
| 1408 |         // Reset to zero first to avoid having memory allocated for two massive arrays at the same | 
| 1409 |         // time on the second and subsequent runs. | 
| 1410 |         series->dataProxy()->resetArray(newArray: 0); | 
| 1411 |         QSurfaceDataArray *massiveArray = new QSurfaceDataArray; | 
| 1412 |         massiveArray->reserve(alloc: rows); | 
| 1413 |  | 
| 1414 |         for (int i = 0; i < rows; i++) { | 
| 1415 |             QSurfaceDataRow *newRow = new QSurfaceDataRow(*m_massiveTestCacheArray.at(i: i % cacheSize)); | 
| 1416 |             for (int j = 0; j < columns; j++) | 
| 1417 |                 (*newRow)[j].setZ(float(i)); | 
| 1418 |             massiveArray->append(t: newRow); | 
| 1419 |         } | 
| 1420 |         qDebug() << __FUNCTION__ << testPhase << ": Massive array creation finished!" ; | 
| 1421 |  | 
| 1422 |         series->dataProxy()->resetArray(newArray: massiveArray); | 
| 1423 |         m_graph->addSeries(series); | 
| 1424 |         break; | 
| 1425 |     } | 
| 1426 |     case 1: { | 
| 1427 |         qDebug() << __FUNCTION__ << testPhase << ": Scroll" ; | 
| 1428 |         QObject::disconnect(sender: massiveTestTimer, signal: 0, receiver: this, member: 0); | 
| 1429 |         QObject::connect(sender: massiveTestTimer, signal: &QTimer::timeout, receiver: this, | 
| 1430 |                          slot: &GraphModifier::massiveTestScroll); | 
| 1431 |         massiveTestTimer->start(msec: 16); | 
| 1432 |         break; | 
| 1433 |     } | 
| 1434 |     case 2: { | 
| 1435 |         qDebug() << __FUNCTION__ << testPhase << ": Append and scroll" ; | 
| 1436 |         massiveTestTimer->stop(); | 
| 1437 |         QObject::disconnect(sender: massiveTestTimer, signal: 0, receiver: this, member: 0); | 
| 1438 |         QObject::connect(sender: massiveTestTimer, signal: &QTimer::timeout, receiver: this, | 
| 1439 |                          slot: &GraphModifier::massiveTestAppendAndScroll); | 
| 1440 |         m_graph->axisZ()->setRange(min: rows - visibleRows, max: rows); | 
| 1441 |         massiveTestTimer->start(msec: 16); | 
| 1442 |         break; | 
| 1443 |     } | 
| 1444 |     default: | 
| 1445 |         QObject::disconnect(sender: massiveTestTimer, signal: 0, receiver: this, member: 0); | 
| 1446 |         massiveTestTimer->stop(); | 
| 1447 |         qDebug() << __FUNCTION__ << testPhase << ": Resetting the test" ; | 
| 1448 |         testPhase = -1; | 
| 1449 |     } | 
| 1450 |     testPhase++; | 
| 1451 | } | 
| 1452 |  | 
| 1453 | void GraphModifier::massiveTestScroll() | 
| 1454 | { | 
| 1455 |     const int scrollAmount = 20; | 
| 1456 |     int maxRows = m_graph->seriesList().at(i: 0)->dataProxy()->rowCount(); | 
| 1457 |     int min = m_graph->axisZ()->min() + scrollAmount; | 
| 1458 |     int max = m_graph->axisZ()->max() + scrollAmount; | 
| 1459 |     if (max >= maxRows) { | 
| 1460 |         max = max - min; | 
| 1461 |         min = 0; | 
| 1462 |     } | 
| 1463 |     m_graph->axisZ()->setRange(min, max); | 
| 1464 | } | 
| 1465 |  | 
| 1466 | void GraphModifier::massiveTestAppendAndScroll() | 
| 1467 | { | 
| 1468 |     const int addedRows = 50; | 
| 1469 |     int maxRows = m_graph->seriesList().at(i: 0)->dataProxy()->rowCount(); | 
| 1470 |     int columns = m_graph->seriesList().at(i: 0)->dataProxy()->columnCount(); | 
| 1471 |  | 
| 1472 |     QSurfaceDataArray appendArray; | 
| 1473 |     appendArray.reserve(alloc: addedRows); | 
| 1474 |     for (int i = 0; i < addedRows; i++) { | 
| 1475 |         QSurfaceDataRow *newRow = new QSurfaceDataRow(*m_massiveTestCacheArray.at(i: (i + maxRows) % 1000)); | 
| 1476 |         for (int j = 0; j < columns; j++) | 
| 1477 |             (*newRow)[j].setZ(float(maxRows + i)); | 
| 1478 |         appendArray.append(t: newRow); | 
| 1479 |     } | 
| 1480 |     m_graph->seriesList().at(i: 0)->dataProxy()->addRows(rows: appendArray); | 
| 1481 |     int min = m_graph->axisZ()->min() + addedRows; | 
| 1482 |     int max = m_graph->axisZ()->max() + addedRows; | 
| 1483 |     m_graph->axisZ()->setRange(min, max); | 
| 1484 | } | 
| 1485 |  | 
| 1486 | void GraphModifier::testAxisReverse() | 
| 1487 | { | 
| 1488 |     static int counter = 0; | 
| 1489 |     const int rowCount = 16; | 
| 1490 |     const int colCount = 16; | 
| 1491 |     static QSurface3DSeries *series0 = 0; | 
| 1492 |     static QSurface3DSeries *series1 = 0; | 
| 1493 |  | 
| 1494 |     switch (counter) { | 
| 1495 |     case 0: { | 
| 1496 |         qDebug() << __FUNCTION__ << counter << "Setup test" ; | 
| 1497 |         foreach (QSurface3DSeries *series, m_graph->seriesList()) | 
| 1498 |             m_graph->removeSeries(series); | 
| 1499 |         foreach (QValue3DAxis *axis, m_graph->axes()) | 
| 1500 |             m_graph->releaseAxis(axis); | 
| 1501 |         delete series0; | 
| 1502 |         delete series1; | 
| 1503 |         series0 = new QSurface3DSeries; | 
| 1504 |         series1 = new QSurface3DSeries; | 
| 1505 |         populateRisingSeries(series: series0, rows: rowCount, columns: colCount, minValue: 0.0f, maxValue: 50.0f, ascendingX: true, ascendingZ: true); | 
| 1506 |         populateRisingSeries(series: series1, rows: rowCount, columns: colCount, minValue: -20.0f, maxValue: 30.0f, ascendingX: true, ascendingZ: true); | 
| 1507 |         m_graph->axisX()->setRange(min: 0.0f, max: 10.0f); | 
| 1508 |         m_graph->axisY()->setRange(min: -20.0f, max: 50.0f); | 
| 1509 |         m_graph->axisZ()->setRange(min: 5.0f, max: 15.0f); | 
| 1510 |         m_graph->addSeries(series: series0); | 
| 1511 |         m_graph->addSeries(series: series1); | 
| 1512 |     } | 
| 1513 |         break; | 
| 1514 |     case 1: { | 
| 1515 |         qDebug() << __FUNCTION__ << counter << "Reverse X axis" ; | 
| 1516 |         m_graph->axisX()->setReversed(true); | 
| 1517 |     } | 
| 1518 |         break; | 
| 1519 |     case 2: { | 
| 1520 |         qDebug() << __FUNCTION__ << counter << "Reverse Y axis" ; | 
| 1521 |         m_graph->axisY()->setReversed(true); | 
| 1522 |     } | 
| 1523 |         break; | 
| 1524 |     case 3: { | 
| 1525 |         qDebug() << __FUNCTION__ << counter << "Reverse Z axis" ; | 
| 1526 |         m_graph->axisZ()->setReversed(true); | 
| 1527 |     } | 
| 1528 |         break; | 
| 1529 |     case 4: { | 
| 1530 |         qDebug() << __FUNCTION__ << counter << "Return all axes to normal" ; | 
| 1531 |         m_graph->axisX()->setReversed(false); | 
| 1532 |         m_graph->axisY()->setReversed(false); | 
| 1533 |         m_graph->axisZ()->setReversed(false); | 
| 1534 |     } | 
| 1535 |         break; | 
| 1536 |     case 5: { | 
| 1537 |         qDebug() << __FUNCTION__ << counter << "Reverse all axes" ; | 
| 1538 |         m_graph->axisX()->setReversed(true); | 
| 1539 |         m_graph->axisY()->setReversed(true); | 
| 1540 |         m_graph->axisZ()->setReversed(true); | 
| 1541 |     } | 
| 1542 |         break; | 
| 1543 |     default: | 
| 1544 |         qDebug() << __FUNCTION__ << "Resetting test" ; | 
| 1545 |         counter = -1; | 
| 1546 |     } | 
| 1547 |     counter++; | 
| 1548 | } | 
| 1549 |  | 
| 1550 | void GraphModifier::testDataOrdering() | 
| 1551 | { | 
| 1552 |     static int counter = 0; | 
| 1553 |     const int rowCount = 20; | 
| 1554 |     const int colCount = 20; | 
| 1555 |     static QSurface3DSeries *series0 = 0; | 
| 1556 |     static QSurface3DSeries *series1 = 0; | 
| 1557 |     const float series0min = 0.0f; | 
| 1558 |     const float series0max = 50.0f; | 
| 1559 |     const float series1min = -20.0f; | 
| 1560 |     const float series1max = 30.0f; | 
| 1561 |  | 
| 1562 |     switch (counter) { | 
| 1563 |     case 0: { | 
| 1564 |         qDebug() << __FUNCTION__ << counter << "Setup test - both ascending" ; | 
| 1565 |         foreach (QSurface3DSeries *series, m_graph->seriesList()) | 
| 1566 |             m_graph->removeSeries(series); | 
| 1567 |         foreach (QValue3DAxis *axis, m_graph->axes()) | 
| 1568 |             m_graph->releaseAxis(axis); | 
| 1569 |         delete series0; | 
| 1570 |         delete series1; | 
| 1571 |         series0 = new QSurface3DSeries; | 
| 1572 |         series1 = new QSurface3DSeries; | 
| 1573 |         populateRisingSeries(series: series0, rows: rowCount, columns: colCount, minValue: series0min, maxValue: series0max, ascendingX: true, ascendingZ: true); | 
| 1574 |         populateRisingSeries(series: series1, rows: rowCount, columns: colCount, minValue: series1min, maxValue: series1max, ascendingX: true, ascendingZ: true); | 
| 1575 |         m_graph->axisX()->setRange(min: 5.0f, max: 15.0f); | 
| 1576 |         m_graph->axisY()->setRange(min: -20.0f, max: 50.0f); | 
| 1577 |         m_graph->axisZ()->setRange(min: 5.0f, max: 15.0f); | 
| 1578 |         m_graph->addSeries(series: series0); | 
| 1579 |         m_graph->addSeries(series: series1); | 
| 1580 |     } | 
| 1581 |         break; | 
| 1582 |     case 1: { | 
| 1583 |         qDebug() << __FUNCTION__ << counter << "Ascending X, descending Z" ; | 
| 1584 |         populateRisingSeries(series: series0, rows: rowCount, columns: colCount, minValue: series0min, maxValue: series0max, ascendingX: true, ascendingZ: false); | 
| 1585 |         populateRisingSeries(series: series1, rows: rowCount, columns: colCount, minValue: series1min, maxValue: series1max, ascendingX: true, ascendingZ: false); | 
| 1586 |     } | 
| 1587 |         break; | 
| 1588 |     case 2: { | 
| 1589 |         qDebug() << __FUNCTION__ << counter << "Descending X, ascending Z" ; | 
| 1590 |         populateRisingSeries(series: series0, rows: rowCount, columns: colCount, minValue: series0min, maxValue: series0max, ascendingX: false, ascendingZ: true); | 
| 1591 |         populateRisingSeries(series: series1, rows: rowCount, columns: colCount, minValue: series1min, maxValue: series1max, ascendingX: false, ascendingZ: true); | 
| 1592 |     } | 
| 1593 |         break; | 
| 1594 |     case 3: { | 
| 1595 |         qDebug() << __FUNCTION__ << counter << "Both descending" ; | 
| 1596 |         populateRisingSeries(series: series0, rows: rowCount, columns: colCount, minValue: series0min, maxValue: series0max, ascendingX: false, ascendingZ: false); | 
| 1597 |         populateRisingSeries(series: series1, rows: rowCount, columns: colCount, minValue: series1min, maxValue: series1max, ascendingX: false, ascendingZ: false); | 
| 1598 |     } | 
| 1599 |         break; | 
| 1600 |     default: | 
| 1601 |         qDebug() << __FUNCTION__ << "Resetting test" ; | 
| 1602 |         counter = -1; | 
| 1603 |     } | 
| 1604 |     counter++; | 
| 1605 | } | 
| 1606 |  | 
| 1607 | void GraphModifier::changeMesh() | 
| 1608 | { | 
| 1609 |     static int model = 0; | 
| 1610 |     switch (model) { | 
| 1611 |     case 0: | 
| 1612 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshCylinder); | 
| 1613 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(false); | 
| 1614 |         break; | 
| 1615 |     case 1: | 
| 1616 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshCylinder); | 
| 1617 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(true); | 
| 1618 |         break; | 
| 1619 |     case 2: | 
| 1620 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshCone); | 
| 1621 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(false); | 
| 1622 |         break; | 
| 1623 |     case 3: | 
| 1624 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshCone); | 
| 1625 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(true); | 
| 1626 |         break; | 
| 1627 |     case 4: | 
| 1628 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshBar); | 
| 1629 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(false); | 
| 1630 |         break; | 
| 1631 |     case 5: | 
| 1632 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshBar); | 
| 1633 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(true); | 
| 1634 |         break; | 
| 1635 |     case 6: | 
| 1636 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshPyramid); | 
| 1637 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(false); | 
| 1638 |         break; | 
| 1639 |     case 7: | 
| 1640 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshPyramid); | 
| 1641 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(true); | 
| 1642 |         break; | 
| 1643 |     case 8: | 
| 1644 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshBevelBar); | 
| 1645 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(false); | 
| 1646 |         break; | 
| 1647 |     case 9: | 
| 1648 |         m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshBevelBar); | 
| 1649 |         m_graph->seriesList().at(i: 0)->setMeshSmooth(true); | 
| 1650 |         break; | 
| 1651 |     } | 
| 1652 |     model++; | 
| 1653 |     if (model > 9) | 
| 1654 |         model = 0; | 
| 1655 | } | 
| 1656 |  | 
| 1657 | void GraphModifier::updateSamples() | 
| 1658 | { | 
| 1659 |     switch (m_activeSample) { | 
| 1660 |     case SqrtSin: | 
| 1661 |         toggleSqrtSin(enable: true); | 
| 1662 |         break; | 
| 1663 |  | 
| 1664 |     case Plane: | 
| 1665 |         togglePlane(enable: true); | 
| 1666 |         break; | 
| 1667 |  | 
| 1668 |     default: | 
| 1669 |         break; | 
| 1670 |     } | 
| 1671 | } | 
| 1672 |  | 
| 1673 | void GraphModifier::setAspectRatio(int ratio) | 
| 1674 | { | 
| 1675 |     qreal aspectRatio = qreal(ratio) / 10.0; | 
| 1676 |     m_graph->setAspectRatio(aspectRatio); | 
| 1677 | } | 
| 1678 |  | 
| 1679 | void GraphModifier::setHorizontalAspectRatio(int ratio) | 
| 1680 | { | 
| 1681 |     qreal aspectRatio = qreal(ratio) / 100.0; | 
| 1682 |     m_graph->setHorizontalAspectRatio(aspectRatio); | 
| 1683 | } | 
| 1684 |  | 
| 1685 | void GraphModifier::setSurfaceTexture(bool enabled) | 
| 1686 | { | 
| 1687 |     if (enabled) | 
| 1688 |         m_multiseries[3]->setTexture(QImage(":/maps/mapimage" )); | 
| 1689 |     else | 
| 1690 |         m_multiseries[3]->setTexture(QImage()); | 
| 1691 | } | 
| 1692 |  |