summaryrefslogtreecommitdiffstats
path: root/examples/datavisualization/qmloscilloscope/datasource.cpp
blob: 83ff0ff9e44744c21d6ca9f7556b0fb34e5a5270 (plain)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com
**
** This file is part of the QtDataVisualization module.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com
**
****************************************************************************/

#include "datasource.h"
#include <qmath.h>

using namespace QtDataVisualization;

Q_DECLARE_METATYPE(QSurface3DSeries *)

DataSource::DataSource(QObject *parent) :
    QObject(parent),
    m_index(-1),
    m_resetArray(0)
{
    qRegisterMetaType<QSurface3DSeries *>();
}

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)
        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
                        + (0.15f * float(rand()) / float(RAND_MAX)) * 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]

//! [2]
QString DataSource::selectionLabel(QSurface3DSeries *series, QValue3DAxis *axisX,
                                   QValue3DAxis *axisY, QValue3DAxis *axisZ)
{
    QString label;

    if (series && series->selectedPoint() != QSurface3DSeries::invalidSelectionPosition()) {
        const QSurfaceDataItem *item = series->dataProxy()->itemAt(series->selectedPoint());
        QString x;
        QString y;
        QString z;
        x.sprintf(axisX->labelFormat().toUtf8().constData(), int(item->x()));
        y.sprintf(axisY->labelFormat().toUtf8().constData(), int(item->y()));
        z.sprintf(axisZ->labelFormat().toUtf8().constData(), int(item->z()));
        label = QStringLiteral("%1, %3: %2").arg(x).arg(y).arg(z);
    } else {
        label = QStringLiteral("No selection");
    }

    return label;
}
//! [2]

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();
    }
}