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
45using namespace QtDataVisualization;
46
47//#define JITTER_PLANE
48//#define WONKY_PLANE
49
50GraphModifier::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
147GraphModifier::~GraphModifier()
148{
149 delete m_graph;
150}
151
152void 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
197void 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
208void 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
219void 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
230void 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
241void 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
250void 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
264void 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
278void GraphModifier::toggleSeriesVisible(bool enable)
279{
280 m_theSeries->setVisible(enable);
281#ifdef MULTI_SERIES
282 m_multiseries[0]->setVisible(enable);
283#endif
284}
285
286void GraphModifier::toggleSmoothS2(bool enabled)
287{
288 qDebug() << __FUNCTION__ << enabled;
289 m_multiseries[1]->setFlatShadingEnabled(enabled);
290}
291
292void 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
303void 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
314void GraphModifier::toggleSeries2Visible(bool enable)
315{
316 qDebug() << __FUNCTION__ << enable;
317 m_multiseries[1]->setVisible(enable);
318}
319
320void GraphModifier::toggleSmoothS3(bool enabled)
321{
322 qDebug() << __FUNCTION__ << enabled;
323 m_multiseries[2]->setFlatShadingEnabled(enabled);
324}
325
326void 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
337void 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
348void GraphModifier::toggleSeries3Visible(bool enable)
349{
350 qDebug() << __FUNCTION__ << enable;
351 m_multiseries[2]->setVisible(enable);
352}
353
354void GraphModifier::toggleSmoothS4(bool enabled)
355{
356 qDebug() << __FUNCTION__ << enabled;
357 m_multiseries[3]->setFlatShadingEnabled(enabled);
358}
359
360void 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
371void 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
382void GraphModifier::toggleSeries4Visible(bool enable)
383{
384 qDebug() << __FUNCTION__ << enable;
385 m_multiseries[3]->setVisible(enable);
386}
387
388void 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
430void 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
510void 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
550void 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
561void 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
572void GraphModifier::adjustZCount(int count)
573{
574 m_zCount = count;
575
576 updateSamples();
577
578 qDebug() << "Z count =" << count;
579}
580
581void 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
589void 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
597void 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
605void 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
613void 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
621void 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
629void 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
657void GraphModifier::changeFont(const QFont &font)
658{
659 QFont newFont = font;
660 newFont.setPointSizeF(m_fontSize);
661 m_graph->activeTheme()->setFont(newFont);
662}
663
664void GraphModifier::changeStyle()
665{
666 m_graph->activeTheme()->setLabelBackgroundEnabled(!m_graph->activeTheme()->isLabelBackgroundEnabled());
667}
668
669void 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
678void 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
684void GraphModifier::changeTheme(int theme)
685{
686 m_graph->activeTheme()->setType(Q3DTheme::Theme(theme));
687}
688
689
690void GraphModifier::flipViews()
691{
692 m_graph->scene()->setSecondarySubviewOnTop(!m_graph->scene()->isSecondarySubviewOnTop());
693}
694
695void 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
716void 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
726void GraphModifier::handleAxisXChanged(QValue3DAxis *axis)
727{
728 qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisX());
729}
730
731void GraphModifier::handleAxisYChanged(QValue3DAxis *axis)
732{
733 qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisY());
734}
735
736void GraphModifier::handleAxisZChanged(QValue3DAxis *axis)
737{
738 qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisZ());
739}
740
741void GraphModifier::handleFpsChange(qreal fps)
742{
743 qDebug() << "FPS:" << fps;
744}
745
746void 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
753void 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
760void 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
767void 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
797void 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
827void GraphModifier::togglePolar(bool enabled)
828{
829 m_graph->setPolar(enabled);
830}
831
832void 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
840void 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
848void 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
856void GraphModifier::setGraphMargin(int value)
857{
858 m_graph->setMargin(qreal(value) / 100.0);
859 qDebug() << "Setting margin:" << m_graph->margin() << value;
860}
861
862void 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
872void GraphModifier::changeShadowQuality(int quality)
873{
874 QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality);
875 m_graph->setShadowQuality(sq);
876}
877
878void 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
887void 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
930QSurfaceDataRow *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
955void 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
977void 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
1027void 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
1077void GraphModifier::changeMultipleRows()
1078{
1079 for (int i = 0; i < 30; i++)
1080 changeRow();
1081}
1082
1083void GraphModifier::changeMultipleItem()
1084{
1085 for (int i = 0; i < 30; i++)
1086 changeItem();
1087}
1088
1089void 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
1134void 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
1181void 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
1230void 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
1288void 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
1305void 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
1332void 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
1343void 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
1453void 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
1466void 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
1486void 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
1550void 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
1607void 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
1657void 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
1673void GraphModifier::setAspectRatio(int ratio)
1674{
1675 qreal aspectRatio = qreal(ratio) / 10.0;
1676 m_graph->setAspectRatio(aspectRatio);
1677}
1678
1679void GraphModifier::setHorizontalAspectRatio(int ratio)
1680{
1681 qreal aspectRatio = qreal(ratio) / 100.0;
1682 m_graph->setHorizontalAspectRatio(aspectRatio);
1683}
1684
1685void 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

source code of qtdatavis3d/tests/manual/surfacetest/graphmodifier.cpp