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 "surfacegraph.h" |
31 | |
32 | #include <QtDataVisualization/QValue3DAxis> |
33 | #include <QtDataVisualization/Q3DTheme> |
34 | #include <QtGui/QImage> |
35 | #include <QtCore/qmath.h> |
36 | |
37 | using namespace QtDataVisualization; |
38 | |
39 | const int sampleCountX = 50; |
40 | const int sampleCountZ = 50; |
41 | const int heightMapGridStepX = 6; |
42 | const int heightMapGridStepZ = 6; |
43 | const float sampleMin = -8.0f; |
44 | const float sampleMax = 8.0f; |
45 | |
46 | SurfaceGraph::SurfaceGraph(Q3DSurface *surface) |
47 | : m_graph(surface) |
48 | { |
49 | m_graph->setAxisX(new QValue3DAxis); |
50 | m_graph->setAxisY(new QValue3DAxis); |
51 | m_graph->setAxisZ(new QValue3DAxis); |
52 | |
53 | //! [0] |
54 | m_sqrtSinProxy = new QSurfaceDataProxy(); |
55 | m_sqrtSinSeries = new QSurface3DSeries(m_sqrtSinProxy); |
56 | //! [0] |
57 | fillSqrtSinProxy(); |
58 | |
59 | //! [2] |
60 | QImage heightMapImage(":/maps/mountain" ); |
61 | m_heightMapProxy = new QHeightMapSurfaceDataProxy(heightMapImage); |
62 | m_heightMapSeries = new QSurface3DSeries(m_heightMapProxy); |
63 | m_heightMapSeries->setItemLabelFormat(QStringLiteral("(@xLabel, @zLabel): @yLabel" )); |
64 | m_heightMapProxy->setValueRanges(minX: 34.0f, maxX: 40.0f, minZ: 18.0f, maxZ: 24.0f); |
65 | //! [2] |
66 | m_heightMapWidth = heightMapImage.width(); |
67 | m_heightMapHeight = heightMapImage.height(); |
68 | } |
69 | |
70 | SurfaceGraph::~SurfaceGraph() |
71 | { |
72 | delete m_graph; |
73 | } |
74 | |
75 | //! [1] |
76 | void SurfaceGraph::fillSqrtSinProxy() |
77 | { |
78 | float stepX = (sampleMax - sampleMin) / float(sampleCountX - 1); |
79 | float stepZ = (sampleMax - sampleMin) / float(sampleCountZ - 1); |
80 | |
81 | QSurfaceDataArray *dataArray = new QSurfaceDataArray; |
82 | dataArray->reserve(alloc: sampleCountZ); |
83 | for (int i = 0 ; i < sampleCountZ ; i++) { |
84 | QSurfaceDataRow *newRow = new QSurfaceDataRow(sampleCountX); |
85 | // Keep values within range bounds, since just adding step can cause minor drift due |
86 | // to the rounding errors. |
87 | float z = qMin(a: sampleMax, b: (i * stepZ + sampleMin)); |
88 | int index = 0; |
89 | for (int j = 0; j < sampleCountX; j++) { |
90 | float x = qMin(a: sampleMax, b: (j * stepX + sampleMin)); |
91 | float R = qSqrt(v: z * z + x * x) + 0.01f; |
92 | float y = (qSin(v: R) / R + 0.24f) * 1.61f; |
93 | (*newRow)[index++].setPosition(QVector3D(x, y, z)); |
94 | } |
95 | *dataArray << newRow; |
96 | } |
97 | |
98 | m_sqrtSinProxy->resetArray(newArray: dataArray); |
99 | } |
100 | //! [1] |
101 | |
102 | void SurfaceGraph::enableSqrtSinModel(bool enable) |
103 | { |
104 | if (enable) { |
105 | //! [3] |
106 | m_sqrtSinSeries->setDrawMode(QSurface3DSeries::DrawSurfaceAndWireframe); |
107 | m_sqrtSinSeries->setFlatShadingEnabled(true); |
108 | |
109 | m_graph->axisX()->setLabelFormat("%.2f" ); |
110 | m_graph->axisZ()->setLabelFormat("%.2f" ); |
111 | m_graph->axisX()->setRange(min: sampleMin, max: sampleMax); |
112 | m_graph->axisY()->setRange(min: 0.0f, max: 2.0f); |
113 | m_graph->axisZ()->setRange(min: sampleMin, max: sampleMax); |
114 | m_graph->axisX()->setLabelAutoRotation(30); |
115 | m_graph->axisY()->setLabelAutoRotation(90); |
116 | m_graph->axisZ()->setLabelAutoRotation(30); |
117 | |
118 | m_graph->removeSeries(series: m_heightMapSeries); |
119 | m_graph->addSeries(series: m_sqrtSinSeries); |
120 | //! [3] |
121 | |
122 | //! [8] |
123 | // Reset range sliders for Sqrt&Sin |
124 | m_rangeMinX = sampleMin; |
125 | m_rangeMinZ = sampleMin; |
126 | m_stepX = (sampleMax - sampleMin) / float(sampleCountX - 1); |
127 | m_stepZ = (sampleMax - sampleMin) / float(sampleCountZ - 1); |
128 | m_axisMinSliderX->setMaximum(sampleCountX - 2); |
129 | m_axisMinSliderX->setValue(0); |
130 | m_axisMaxSliderX->setMaximum(sampleCountX - 1); |
131 | m_axisMaxSliderX->setValue(sampleCountX - 1); |
132 | m_axisMinSliderZ->setMaximum(sampleCountZ - 2); |
133 | m_axisMinSliderZ->setValue(0); |
134 | m_axisMaxSliderZ->setMaximum(sampleCountZ - 1); |
135 | m_axisMaxSliderZ->setValue(sampleCountZ - 1); |
136 | //! [8] |
137 | } |
138 | } |
139 | |
140 | void SurfaceGraph::enableHeightMapModel(bool enable) |
141 | { |
142 | if (enable) { |
143 | //! [4] |
144 | m_heightMapSeries->setDrawMode(QSurface3DSeries::DrawSurface); |
145 | m_heightMapSeries->setFlatShadingEnabled(false); |
146 | |
147 | m_graph->axisX()->setLabelFormat("%.1f N" ); |
148 | m_graph->axisZ()->setLabelFormat("%.1f E" ); |
149 | m_graph->axisX()->setRange(min: 34.0f, max: 40.0f); |
150 | m_graph->axisY()->setAutoAdjustRange(true); |
151 | m_graph->axisZ()->setRange(min: 18.0f, max: 24.0f); |
152 | |
153 | m_graph->axisX()->setTitle(QStringLiteral("Latitude" )); |
154 | m_graph->axisY()->setTitle(QStringLiteral("Height" )); |
155 | m_graph->axisZ()->setTitle(QStringLiteral("Longitude" )); |
156 | |
157 | m_graph->removeSeries(series: m_sqrtSinSeries); |
158 | m_graph->addSeries(series: m_heightMapSeries); |
159 | //! [4] |
160 | |
161 | // Reset range sliders for height map |
162 | int mapGridCountX = m_heightMapWidth / heightMapGridStepX; |
163 | int mapGridCountZ = m_heightMapHeight / heightMapGridStepZ; |
164 | m_rangeMinX = 34.0f; |
165 | m_rangeMinZ = 18.0f; |
166 | m_stepX = 6.0f / float(mapGridCountX - 1); |
167 | m_stepZ = 6.0f / float(mapGridCountZ - 1); |
168 | m_axisMinSliderX->setMaximum(mapGridCountX - 2); |
169 | m_axisMinSliderX->setValue(0); |
170 | m_axisMaxSliderX->setMaximum(mapGridCountX - 1); |
171 | m_axisMaxSliderX->setValue(mapGridCountX - 1); |
172 | m_axisMinSliderZ->setMaximum(mapGridCountZ - 2); |
173 | m_axisMinSliderZ->setValue(0); |
174 | m_axisMaxSliderZ->setMaximum(mapGridCountZ - 1); |
175 | m_axisMaxSliderZ->setValue(mapGridCountZ - 1); |
176 | } |
177 | } |
178 | |
179 | void SurfaceGraph::adjustXMin(int min) |
180 | { |
181 | float minX = m_stepX * float(min) + m_rangeMinX; |
182 | |
183 | int max = m_axisMaxSliderX->value(); |
184 | if (min >= max) { |
185 | max = min + 1; |
186 | m_axisMaxSliderX->setValue(max); |
187 | } |
188 | float maxX = m_stepX * max + m_rangeMinX; |
189 | |
190 | setAxisXRange(min: minX, max: maxX); |
191 | } |
192 | |
193 | void SurfaceGraph::adjustXMax(int max) |
194 | { |
195 | float maxX = m_stepX * float(max) + m_rangeMinX; |
196 | |
197 | int min = m_axisMinSliderX->value(); |
198 | if (max <= min) { |
199 | min = max - 1; |
200 | m_axisMinSliderX->setValue(min); |
201 | } |
202 | float minX = m_stepX * min + m_rangeMinX; |
203 | |
204 | setAxisXRange(min: minX, max: maxX); |
205 | } |
206 | |
207 | void SurfaceGraph::adjustZMin(int min) |
208 | { |
209 | float minZ = m_stepZ * float(min) + m_rangeMinZ; |
210 | |
211 | int max = m_axisMaxSliderZ->value(); |
212 | if (min >= max) { |
213 | max = min + 1; |
214 | m_axisMaxSliderZ->setValue(max); |
215 | } |
216 | float maxZ = m_stepZ * max + m_rangeMinZ; |
217 | |
218 | setAxisZRange(min: minZ, max: maxZ); |
219 | } |
220 | |
221 | void SurfaceGraph::adjustZMax(int max) |
222 | { |
223 | float maxX = m_stepZ * float(max) + m_rangeMinZ; |
224 | |
225 | int min = m_axisMinSliderZ->value(); |
226 | if (max <= min) { |
227 | min = max - 1; |
228 | m_axisMinSliderZ->setValue(min); |
229 | } |
230 | float minX = m_stepZ * min + m_rangeMinZ; |
231 | |
232 | setAxisZRange(min: minX, max: maxX); |
233 | } |
234 | |
235 | //! [5] |
236 | void SurfaceGraph::setAxisXRange(float min, float max) |
237 | { |
238 | m_graph->axisX()->setRange(min, max); |
239 | } |
240 | |
241 | void SurfaceGraph::setAxisZRange(float min, float max) |
242 | { |
243 | m_graph->axisZ()->setRange(min, max); |
244 | } |
245 | //! [5] |
246 | |
247 | //! [6] |
248 | void SurfaceGraph::changeTheme(int theme) |
249 | { |
250 | m_graph->activeTheme()->setType(Q3DTheme::Theme(theme)); |
251 | } |
252 | //! [6] |
253 | |
254 | void SurfaceGraph::setBlackToYellowGradient() |
255 | { |
256 | //! [7] |
257 | QLinearGradient gr; |
258 | gr.setColorAt(pos: 0.0, color: Qt::black); |
259 | gr.setColorAt(pos: 0.33, color: Qt::blue); |
260 | gr.setColorAt(pos: 0.67, color: Qt::red); |
261 | gr.setColorAt(pos: 1.0, color: Qt::yellow); |
262 | |
263 | m_graph->seriesList().at(i: 0)->setBaseGradient(gr); |
264 | m_graph->seriesList().at(i: 0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient); |
265 | //! [7] |
266 | } |
267 | |
268 | void SurfaceGraph::setGreenToRedGradient() |
269 | { |
270 | QLinearGradient gr; |
271 | gr.setColorAt(pos: 0.0, color: Qt::darkGreen); |
272 | gr.setColorAt(pos: 0.5, color: Qt::yellow); |
273 | gr.setColorAt(pos: 0.8, color: Qt::red); |
274 | gr.setColorAt(pos: 1.0, color: Qt::darkRed); |
275 | |
276 | m_graph->seriesList().at(i: 0)->setBaseGradient(gr); |
277 | m_graph->seriesList().at(i: 0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient); |
278 | } |
279 | |
280 | |