1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "datasource.h"
#include <QtCore/qmath.h>
#include <QtCore/qrandom.h>
//! [3]
Q_DECLARE_METATYPE(QSurface3DSeries *)
//! [3]
DataSource::DataSource(QObject *parent) :
QObject(parent),
m_index(-1),
m_resetArray(nullptr)
{
//! [4]
qRegisterMetaType<QSurface3DSeries *>();
//! [4]
}
DataSource::~DataSource()
{
clearData();
}
//! [0]
void DataSource::generateData(int cacheCount, int rowCount, int columnCount,
float xMin, float xMax, float yMin, float yMax,
float zMin, float zMax)
{
if (!cacheCount || !rowCount || !columnCount)
return;
clearData();
// Re-create the cache array
m_data.resize(cacheCount);
for (int i(0); i < cacheCount; i++) {
QSurfaceDataArray &array = m_data[i];
array.reserve(rowCount);
for (int j(0); j < rowCount; j++)
array.append(new QSurfaceDataRow(columnCount));
}
float xRange = xMax - xMin;
float yRange = yMax - yMin;
float zRange = zMax - zMin;
int cacheIndexStep = columnCount / cacheCount;
float cacheStep = float(cacheIndexStep) * xRange / float(columnCount);
// Populate caches
for (int i(0); i < cacheCount; i++) {
QSurfaceDataArray &cache = m_data[i];
float cacheXAdjustment = cacheStep * i;
float cacheIndexAdjustment = cacheIndexStep * i;
for (int j(0); j < rowCount; j++) {
QSurfaceDataRow &row = *(cache[j]);
float rowMod = (float(j)) / float(rowCount);
float yRangeMod = yRange * rowMod;
float zRangeMod = zRange * rowMod;
float z = zRangeMod + zMin;
qreal rowColWaveAngleMul = M_PI * M_PI * rowMod;
float rowColWaveMul = yRangeMod * 0.2f;
for (int k(0); k < columnCount; k++) {
float colMod = (float(k)) / float(columnCount);
float xRangeMod = xRange * colMod;
float x = xRangeMod + xMin + cacheXAdjustment;
float colWave = float(qSin((2.0 * M_PI * colMod) - (1.0 / 2.0 * M_PI)) + 1.0);
float y = (colWave * ((float(qSin(rowColWaveAngleMul * colMod) + 1.0))))
* rowColWaveMul
+ QRandomGenerator::global()->bounded(0.15f) * yRangeMod;
int index = k + cacheIndexAdjustment;
if (index >= columnCount) {
// Wrap over
index -= columnCount;
x -= xRange;
}
row[index] = QVector3D(x, y, z);
}
}
}
}
//! [0]
//! [1]
void DataSource::update(QSurface3DSeries *series)
{
if (series && m_data.size()) {
// Each iteration uses data from a different cached array
m_index++;
if (m_index > m_data.count() - 1)
m_index = 0;
QSurfaceDataArray array = m_data.at(m_index);
int newRowCount = array.size();
int newColumnCount = array.at(0)->size();
// If the first time or the dimensions of the cache array have changed,
// reconstruct the reset array
if (!m_resetArray || series->dataProxy()->rowCount() != newRowCount
|| series->dataProxy()->columnCount() != newColumnCount) {
m_resetArray = new QSurfaceDataArray();
m_resetArray->reserve(newRowCount);
for (int i(0); i < newRowCount; i++)
m_resetArray->append(new QSurfaceDataRow(newColumnCount));
}
// Copy items from our cache to the reset array
for (int i(0); i < newRowCount; i++) {
const QSurfaceDataRow &sourceRow = *(array.at(i));
QSurfaceDataRow &row = *(*m_resetArray)[i];
for (int j(0); j < newColumnCount; j++)
row[j].setPosition(sourceRow.at(j).position());
}
// Notify the proxy that data has changed
series->dataProxy()->resetArray(m_resetArray);
}
}
//! [1]
void DataSource::clearData()
{
for (int i(0); i < m_data.size(); i++) {
QSurfaceDataArray &array = m_data[i];
for (int j(0); j < array.size(); j++)
delete array[j];
array.clear();
}
}
|