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 "scatterdatamodifier.h"
31#include <QtDataVisualization/qscatterdataproxy.h>
32#include <QtDataVisualization/qvalue3daxis.h>
33#include <QtDataVisualization/q3dscene.h>
34#include <QtDataVisualization/q3dcamera.h>
35#include <QtDataVisualization/qscatter3dseries.h>
36#include <QtDataVisualization/q3dtheme.h>
37#include <qmath.h>
38#include <QComboBox>
39
40using namespace QtDataVisualization;
41
42const int numberOfCols = 8;
43const int numberOfRows = 8;
44const float limit = 8.0f;
45#define HEDGEHOG
46
47ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter)
48 : m_graph(scatter),
49 m_fontSize(40.0f),
50 m_style(QAbstract3DSeries::MeshUserDefined),
51 m_smooth(true)
52{
53 m_graph->activeTheme()->setType(Q3DTheme::ThemeEbony);
54 QFont font = m_graph->activeTheme()->font();
55 font.setPointSize(m_fontSize);
56 m_graph->activeTheme()->setFont(font);
57 m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftLow);
58 m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
59
60 m_graph->setAxisX(new QValue3DAxis);
61 m_graph->setAxisY(new QValue3DAxis);
62 m_graph->setAxisZ(new QValue3DAxis);
63
64 QScatterDataProxy *proxy = new QScatterDataProxy;
65 QScatter3DSeries *series = new QScatter3DSeries(proxy);
66 series->setItemLabelFormat("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel");
67 m_graph->addSeries(series);
68
69 QObject::connect(sender: &m_rotationTimer, signal: &QTimer::timeout, receiver: this,
70 slot: &ScatterDataModifier::triggerRotation);
71
72 addData();
73}
74
75ScatterDataModifier::~ScatterDataModifier()
76{
77 delete m_graph;
78}
79
80void ScatterDataModifier::addData()
81{
82 // Configure the axes according to the data
83 m_graph->axisX()->setTitle("X");
84 m_graph->axisY()->setTitle("Y");
85 m_graph->axisZ()->setTitle("Z");
86 m_graph->axisX()->setRange(min: -limit, max: limit);
87 m_graph->axisY()->setRange(min: -1.0f, max: 1.0f);
88 m_graph->axisZ()->setRange(min: -limit, max: limit);
89
90 QScatterDataArray *dataArray = new QScatterDataArray;
91 dataArray->resize(asize: numberOfCols * numberOfRows);
92 QScatterDataItem *ptrToDataArray = &dataArray->first();
93
94 float angleStep = 360.0f / float(numberOfCols);
95 float latAngleStep = 100.0f / float(numberOfRows);
96
97 for (float i = 0; i < numberOfRows; i++) {
98 float latAngle = float(i) * latAngleStep + 40.0f;
99 float radius = qSin(v: qDegreesToRadians(degrees: latAngle)) * limit;
100 float y = qCos(v: qDegreesToRadians(degrees: latAngle)) * 1.0f;
101#ifdef HEDGEHOG
102 float angleZ = qRadiansToDegrees(radians: qAtan(v: (y * limit / 2.0f) / radius));
103 QQuaternion rotationZ = QQuaternion::fromAxisAndAngle(axis: QVector3D(0.0f, 0.0f, 1.0f), angle: angleZ - 90.0f);
104#endif
105 for (float j = 0; j < numberOfCols; j++) {
106 float angle = float(j) * angleStep;
107 float x = qCos(v: qDegreesToRadians(degrees: angle)) * radius;
108 float z = qSin(v: qDegreesToRadians(degrees: angle)) * radius;
109
110 float angleY = qRadiansToDegrees(radians: qAtan(v: z / x));
111 if (x < 0)
112 angleY = 180.0f + angleY;
113 if (x > 0 && z < 0)
114 angleY = 360.0f + angleY;
115#ifdef HEDGEHOG
116 QQuaternion rotationY = QQuaternion::fromAxisAndAngle(axis: QVector3D(0.0f, 1.0f, 0.0f), angle: angleY);
117 QQuaternion rotation = rotationY * rotationZ;
118#else
119 QQuaternion rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0f, 1.0f, 0.0f), angleY) *
120 QQuaternion::fromAxisAndAngle(QVector3D(1.0f, 0.0f, 0.0f), -90.0f);
121#endif
122
123 ptrToDataArray->setPosition(QVector3D(x, y, z));
124 ptrToDataArray->setRotation(rotation);
125 ptrToDataArray++;
126 }
127 }
128
129 m_graph->seriesList().at(i: 0)->dataProxy()->resetArray(newArray: dataArray);
130}
131
132void ScatterDataModifier::enableOptimization(int enabled)
133{
134 if (enabled)
135 m_graph->setOptimizationHints(QAbstract3DGraph::OptimizationStatic);
136 else
137 m_graph->setOptimizationHints(QAbstract3DGraph::OptimizationDefault);
138}
139
140void ScatterDataModifier::changeStyle(int style)
141{
142 QComboBox *comboBox = qobject_cast<QComboBox *>(object: sender());
143 if (comboBox) {
144 m_style = QAbstract3DSeries::Mesh(comboBox->itemData(index: style).toInt());
145 if (m_graph->seriesList().size())
146 m_graph->seriesList().at(i: 0)->setMesh(m_style);
147 }
148}
149
150void ScatterDataModifier::changeTheme(int theme)
151{
152 Q3DTheme *currentTheme = m_graph->activeTheme();
153 currentTheme->setType(Q3DTheme::Theme(theme));
154 emit backgroundEnabledChanged(enabled: currentTheme->isBackgroundEnabled());
155 emit gridEnabledChanged(enabled: currentTheme->isGridEnabled());
156 emit fontChanged(font: currentTheme->font());
157}
158
159void ScatterDataModifier::changePresetCamera()
160{
161 static int preset = Q3DCamera::CameraPresetFrontLow;
162
163 m_graph->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset);
164
165 if (++preset > Q3DCamera::CameraPresetDirectlyBelow)
166 preset = Q3DCamera::CameraPresetFrontLow;
167}
168
169void ScatterDataModifier::changeLabelStyle()
170{
171 m_graph->activeTheme()->setLabelBackgroundEnabled(!m_graph->activeTheme()->isLabelBackgroundEnabled());
172}
173
174void ScatterDataModifier::changeFont(const QFont &font)
175{
176 QFont newFont = font;
177 newFont.setPointSizeF(m_fontSize);
178 m_graph->activeTheme()->setFont(newFont);
179}
180
181void ScatterDataModifier::shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality sq)
182{
183 int quality = int(sq);
184 emit shadowQualityChanged(quality); // connected to a checkbox in main.cpp
185}
186
187void ScatterDataModifier::triggerRotation()
188{
189 if (m_graph->seriesList().size()) {
190 int selectedIndex = m_graph->seriesList().at(i: 0)->selectedItem();
191 if (selectedIndex != QScatter3DSeries::invalidSelectionIndex()) {
192 static float itemAngle = 0.0f;
193 QScatterDataItem item(*(m_graph->seriesList().at(i: 0)->dataProxy()->itemAt(index: selectedIndex)));
194 QQuaternion itemRotation = QQuaternion::fromAxisAndAngle(x: 0.0f, y: 0.0f, z: 1.0f, angle: itemAngle++);
195 item.setRotation(itemRotation);
196 m_graph->seriesList().at(i: 0)->dataProxy()->setItem(index: selectedIndex, item);
197 } else {
198 static float seriesAngle = 0.0f;
199 QQuaternion rotation = QQuaternion::fromAxisAndAngle(x: 1.0f, y: 1.0f, z: 1.0f, angle: seriesAngle++);
200 m_graph->seriesList().at(i: 0)->setMeshRotation(rotation);
201 }
202 }
203}
204
205void ScatterDataModifier::changeShadowQuality(int quality)
206{
207 QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality);
208 m_graph->setShadowQuality(sq);
209}
210
211void ScatterDataModifier::setBackgroundEnabled(int enabled)
212{
213 m_graph->activeTheme()->setBackgroundEnabled((bool)enabled);
214}
215
216void ScatterDataModifier::setGridEnabled(int enabled)
217{
218 m_graph->activeTheme()->setGridEnabled((bool)enabled);
219}
220
221void ScatterDataModifier::toggleRotation()
222{
223 if (m_rotationTimer.isActive())
224 m_rotationTimer.stop();
225 else
226 m_rotationTimer.start(msec: 20);
227}
228

source code of qtdatavis3d/tests/manual/directional/scatterdatamodifier.cpp