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#define NOMINMAX
31
32#include "data.h"
33#include <QtDataVisualization/QValue3DAxis>
34#include <QtDataVisualization/Q3DCamera>
35#include <QtDataVisualization/QBar3DSeries>
36#include <QtDataVisualization/QScatter3DSeries>
37#include <QtDataVisualization/QSurface3DSeries>
38#include <QtDataVisualization/Q3DTheme>
39#include <QScrollBar>
40#include <QSize>
41#include <QImage>
42
43using namespace QtDataVisualization;
44
45Data::Data(Q3DSurface *surface, Q3DScatter *scatter, Q3DBars *bars,
46 QTextEdit *statusArea, QWidget *widget) :
47 m_surface(surface),
48 m_scatter(scatter),
49 m_bars(bars),
50 m_statusArea(statusArea),
51 m_widget(widget),
52 m_resize(true),
53 m_resolution(QSize(300, 300)),
54 m_resolutionLevel(0),
55 m_mode(Surface),
56 m_scatterDataArray(0),
57 m_barDataArray(0),
58 m_started(false)
59{
60 // Initialize surface
61 m_surface->activeTheme()->setType(Q3DTheme::ThemeIsabelle);
62 QLinearGradient gradient;
63 gradient.setColorAt(pos: 0.0, color: Qt::black);
64 gradient.setColorAt(pos: 0.33, color: Qt::blue);
65 gradient.setColorAt(pos: 0.67, color: Qt::red);
66 gradient.setColorAt(pos: 1.0, color: Qt::yellow);
67 m_surface->setSelectionMode(QAbstract3DGraph::SelectionNone);
68 m_surface->activeTheme()->setGridEnabled(false);
69 m_surface->activeTheme()->setBackgroundEnabled(false);
70 m_surface->scene()->activeCamera()->setCameraPosition(horizontal: 0.0, vertical: 90.0, zoom: 150.0);
71 QSurface3DSeries *series1 = new QSurface3DSeries(new QHeightMapSurfaceDataProxy());
72 series1->setFlatShadingEnabled(true);
73 series1->setDrawMode(QSurface3DSeries::DrawSurface);
74 series1->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
75 series1->setBaseGradient(gradient);
76 m_surface->addSeries(series: series1);
77
78 // Initialize scatter
79 m_scatter->activeTheme()->setType(Q3DTheme::ThemeStoneMoss);
80 m_scatter->setSelectionMode(QAbstract3DGraph::SelectionNone);
81 m_scatter->activeTheme()->setGridEnabled(false);
82 m_scatter->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftLow);
83 m_scatter->scene()->activeCamera()->setCameraPosition(horizontal: 0.0, vertical: 85.0, zoom: 150.0);
84 QScatter3DSeries *series2 = new QScatter3DSeries;
85 series2->setMesh(QAbstract3DSeries::MeshPoint);
86 m_scatter->addSeries(series: series2);
87
88 // Initialize bars
89 m_bars->activeTheme()->setType(Q3DTheme::ThemeQt);
90 m_bars->setSelectionMode(QAbstract3DGraph::SelectionItemAndRow | QAbstract3DGraph::SelectionSlice);
91 m_bars->activeTheme()->setGridEnabled(false);
92 m_bars->setShadowQuality(QAbstract3DGraph::ShadowQualityLow);
93 m_bars->setBarSpacing(QSizeF(0.0, 0.0));
94 m_bars->scene()->activeCamera()->setCameraPosition(horizontal: 0.0, vertical: 75.0, zoom: 150.0);
95 QBar3DSeries *series3 = new QBar3DSeries;
96 series3->setMesh(QAbstract3DSeries::MeshBar);
97 m_bars->addSeries(series: series3);
98
99 // Hide scroll bar
100 m_statusArea->verticalScrollBar()->setVisible(false);
101}
102
103Data::~Data()
104{
105 delete m_bars;
106 delete m_surface;
107 delete m_scatter;
108 delete m_widget;
109 delete m_scatterDataArray; // only portion of this array is set to graph
110}
111
112void Data::updateData()
113{
114 if (!m_started) {
115 m_statusArea->append(QStringLiteral("<i>We are stopped. The changes will take effect once started.</i>"));
116 return;
117 }
118 QImage depthMap = QImage(":/australia.png");
119 if (m_resize) // Resize for better performance
120 depthMap = depthMap.scaled(s: m_resolution);
121 if (m_mode != Surface)
122 setData(depthMap);
123 else
124 static_cast<QHeightMapSurfaceDataProxy *>(m_surface->seriesList().at(i: 0)->dataProxy())->setHeightMap(
125 depthMap);
126}
127
128void Data::clearData()
129{
130 m_bars->seriesList().at(i: 0)->dataProxy()->resetArray(newArray: 0);
131 m_scatter->seriesList().at(i: 0)->dataProxy()->resetArray(newArray: 0);
132 m_surface->seriesList().at(i: 0)->dataProxy()->resetArray(newArray: 0);
133}
134
135void Data::setResolution(int selection)
136{
137 m_resolutionLevel = selection;
138 switch (selection) {
139 case 0: {
140 m_resize = true;
141 m_resolution = QSize(300, 300);
142 break;
143 }
144 case 1: {
145 m_resize = true;
146 m_resolution = QSize(600, 600);
147 break;
148 }
149 case 2: {
150 m_resize = true;
151 m_resolution = QSize(800, 800);
152 break;
153 }
154 case 3: {
155 m_resize = false;
156 m_resolution = QSize(1020, 1020); // image size
157 break;
158 }
159 };
160 if (m_mode == Scatter) {
161 m_resize = true;
162 m_resolution /= 3;
163 delete m_scatterDataArray;
164 m_scatterDataArray = new QScatterDataArray;
165 m_scatterDataArray->resize(asize: m_resolution.width() * m_resolution.height());
166 } else if (m_mode == Bars) {
167 m_resize = true;
168 m_resolution /= 6;
169 m_barDataArray = new QBarDataArray;
170 m_barDataArray->reserve(alloc: m_resolution.height());
171 for (int i = 0; i < m_resolution.height(); i++) {
172 QBarDataRow *newProxyRow = new QBarDataRow(m_resolution.width());
173 m_barDataArray->append(t: newProxyRow);
174 }
175 }
176
177 m_statusArea->append(text: QString(QStringLiteral("<b>Resolution:</b> %1 x %2")).arg(
178 a: m_resolution.width()).arg(a: m_resolution.height()));
179
180 updateData();
181}
182
183void Data::scrollDown()
184{
185 QScrollBar *scrollbar = m_statusArea->verticalScrollBar();
186 scrollbar->setValue(scrollbar->maximum());
187}
188
189void Data::useGradientOne()
190{
191 m_surface->activeTheme()->setType(Q3DTheme::ThemeIsabelle);
192 QLinearGradient gradient;
193 gradient.setColorAt(pos: 0.0, color: Qt::black);
194 gradient.setColorAt(pos: 0.33, color: Qt::blue);
195 gradient.setColorAt(pos: 0.67, color: Qt::red);
196 gradient.setColorAt(pos: 1.0, color: Qt::yellow);
197 m_surface->seriesList().at(i: 0)->setBaseGradient(gradient);
198 m_surface->seriesList().at(i: 0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
199 m_statusArea->append(QStringLiteral("<b>Colors:</b> Thermal image imitation"));
200}
201
202void Data::useGradientTwo()
203{
204 m_surface->activeTheme()->setType(Q3DTheme::ThemeQt);
205 QLinearGradient gradient;
206 gradient.setColorAt(pos: 0.0, color: Qt::white);
207 gradient.setColorAt(pos: 0.8, color: Qt::red);
208 gradient.setColorAt(pos: 1.0, color: Qt::green);
209 m_surface->seriesList().at(i: 0)->setBaseGradient(gradient);
210 m_surface->seriesList().at(i: 0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
211 m_statusArea->append(QStringLiteral("<b>Colors:</b> Highlight foreground"));
212}
213
214void Data::setData(const QImage &image)
215{
216 QImage heightImage = image;
217
218 uchar *bits = heightImage.bits();
219
220 int imageHeight = heightImage.height();
221 int imageWidth = heightImage.width();
222 int bitCount = imageWidth * 4 * (imageHeight - 1);
223 int widthBits = imageWidth * 4;
224
225 if (m_mode == Scatter) {
226 QScatterDataItem *ptrToDataArray = &m_scatterDataArray->first();
227
228 int limitsX = imageWidth / 2;
229 int limitsZ = imageHeight / 2;
230 float height = 0;
231 int count = 0;
232
233 for (int i = -limitsZ; i < limitsZ; i++, bitCount -= widthBits) {
234 for (int j = -limitsX; j < limitsX; j++) {
235 height = float(bits[bitCount + ((j + limitsX) * 4)]) - 128.0;
236 if (height > -128) {
237 ptrToDataArray->setPosition(QVector3D(float(j), height, float(i)));
238 ptrToDataArray++;
239 count++;
240 }
241 }
242 }
243
244 QScatterDataArray *dataArray = new QScatterDataArray(m_scatterDataArray->mid(pos: 0, len: count));
245 m_scatter->seriesList().at(i: 0)->dataProxy()->resetArray(newArray: dataArray);
246 } else {
247 QBarDataArray *dataArray = m_barDataArray;
248 for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) {
249 QBarDataRow &newRow = *dataArray->at(i);
250 for (int j = 0; j < imageWidth; j++)
251 newRow[j] = float(bits[bitCount + (j * 4)]);
252 }
253
254 m_bars->seriesList().at(i: 0)->dataProxy()->resetArray(newArray: dataArray);
255 }
256}
257
258void Data::changeMode(int mode)
259{
260 m_mode = VisualizationMode(mode);
261 switch (m_mode) {
262 case Surface: {
263 m_statusArea->append(QStringLiteral("<b>Visualization Type:</b> Surface"));
264 break;
265 }
266 case Scatter: {
267 m_statusArea->append(QStringLiteral("<b>Visualization Type:</b> Scatter"));
268 break;
269 }
270 default: {
271 m_statusArea->append(QStringLiteral("<b>Visualization Type:</b> Bars"));
272 break;
273 }
274 }
275 // Reset resolution after mode change
276 setResolution(m_resolutionLevel);
277}
278
279void Data::start()
280{
281 m_started = true;
282 // Reset resolution before starting (otherwise restart will crash due to empty data)
283 setResolution(m_resolutionLevel);
284 updateData();
285 m_statusArea->append(QStringLiteral("<b>Started<\b>"));
286}
287
288void Data::stop()
289{
290 m_started = false;
291 clearData();
292 m_statusArea->append(QStringLiteral("<b>Stopped<\b>"));
293}
294
295ContainerChanger::ContainerChanger(QWidget *surface, QWidget *scatter, QWidget *bars,
296 QWidget *buttonOne, QWidget *buttonTwo)
297 : m_surface(surface),
298 m_scatter(scatter),
299 m_bars(bars),
300 m_button1(buttonOne),
301 m_button2(buttonTwo)
302{
303}
304
305ContainerChanger::~ContainerChanger()
306{
307}
308
309void ContainerChanger::changeContainer(int container)
310{
311 switch (container) {
312 case 0: {
313 m_scatter->setVisible(false);
314 m_bars->setVisible(false);
315 m_surface->setVisible(true);
316 m_button1->setEnabled(true);
317 m_button2->setEnabled(true);
318 break;
319 }
320 case 1: {
321 m_surface->setVisible(false);
322 m_bars->setVisible(false);
323 m_scatter->setVisible(true);
324 m_button1->setEnabled(false);
325 m_button2->setEnabled(false);
326 break;
327 }
328 case 2: {
329 m_surface->setVisible(false);
330 m_scatter->setVisible(false);
331 m_bars->setVisible(true);
332 m_button1->setEnabled(false);
333 m_button2->setEnabled(false);
334 break;
335 }
336 }
337}
338

source code of qtdatavis3d/tests/manual/multigraphs/data.cpp