1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "q3dscatter.h"
5#include "qquickgraphsscatter_p.h"
6
7QT_BEGIN_NAMESPACE
8
9/*!
10 * \class Q3DScatter
11 * \inmodule QtGraphs
12 * \brief The Q3DScatter class provides methods for rendering 3D scatter graphs.
13 *
14 * This class enables developers to render scatter graphs in 3D and to view them by rotating the scene
15 * freely. Rotation is done by holding down the right mouse button and moving the mouse. Zooming
16 * is done by mouse wheel. Selection, if enabled, is done by left mouse button. The scene can be
17 * reset to default camera view by clicking mouse wheel. In touch devices rotation is done
18 * by tap-and-move, selection by tap-and-hold and zoom by pinch.
19 *
20 * If no axes are set explicitly to Q3DScatter, temporary default axes with no labels are created.
21 * These default axes can be modified via axis accessors, but as soon any axis is set explicitly
22 * for the orientation, the default axis for that orientation is destroyed.
23 *
24 * Q3DScatter supports more than one series visible at the same time.
25 *
26 * \section1 How to construct a minimal Q3DScatter graph
27 *
28 * First, construct Q3DScatter. Since we are running the graph as top level window
29 * in this example, we need to clear the \c Qt::FramelessWindowHint flag, which gets set by
30 * default:
31 *
32 * \snippet doc_src_q3dscatter_construction.cpp 0
33 *
34 * Now Q3DScatter is ready to receive data to be rendered. Add one series of 3 QVector3D items:
35 *
36 * \snippet doc_src_q3dscatter_construction.cpp 1
37 *
38 * Finally you will need to set it visible:
39 *
40 * \snippet doc_src_q3dscatter_construction.cpp 2
41 *
42 * The complete code needed to create and display this graph is:
43 *
44 * \snippet doc_src_q3dscatter_construction.cpp 3
45 *
46 * And this is what those few lines of code produce:
47 *
48 * \image q3dscatter-minimal.png
49 *
50 * The scene can be rotated, zoomed into, and an item can be selected to view its position,
51 * but no other interaction is included in this minimal code example.
52 * You can learn more by familiarizing yourself with the examples provided, like
53 * the \l{Simple Scatter Graph}.
54 *
55 * \sa Q3DBars, Q3DSurface, {Qt Graphs C++ Classes}
56 */
57
58/*!
59 * Constructs a new 3D scatter graph.
60 */
61Q3DScatter::Q3DScatter() : QAbstract3DGraph()
62{
63 QQmlComponent *component = new QQmlComponent(engine(), this);
64 component->setData("import QtQuick; import QtGraphs; Scatter3D { anchors.fill: parent; }", baseUrl: QUrl());
65 m_graphsItem.reset(other: qobject_cast<QQuickGraphsScatter *>(object: component->create()));
66 setContent(url: component->url(), component, item: m_graphsItem.data());
67
68 QObject::connect(sender: m_graphsItem.data(), signal: &QQuickGraphsItem::selectedElementChanged,
69 context: this, slot: &QAbstract3DGraph::selectedElementChanged);
70}
71
72/*!
73 * Destroys the 3D scatter graph.
74 */
75Q3DScatter::~Q3DScatter()
76{
77}
78
79/*!
80 * Adds the \a series to the graph. A graph can contain multiple series, but has only one set of
81 * axes. If the newly added series has specified a selected item, it will be highlighted and
82 * any existing selection will be cleared. Only one added series can have an active selection.
83 *
84 * \sa QAbstract3DGraph::hasSeries()
85 */
86void Q3DScatter::addSeries(QScatter3DSeries *series)
87{
88 dptr()->addSeries(series);
89}
90
91/*!
92 * Removes the \a series from the graph.
93 *
94 * \sa QAbstract3DGraph::hasSeries()
95 */
96void Q3DScatter::removeSeries(QScatter3DSeries *series)
97{
98 dptr()->removeSeries(series);
99}
100
101/*!
102 * Returns the list of series added to this graph.
103 *
104 * \sa QAbstract3DGraph::hasSeries()
105 */
106QList<QScatter3DSeries *> Q3DScatter::seriesList() const
107{
108 return dptrc()->m_scatterController->scatterSeriesList();
109}
110
111/*!
112 * \property Q3DScatter::axisX
113 *
114 * \brief The active x-axis.
115 *
116 * Sets \a axis as the active x-axis. Implicitly calls addAxis() to transfer the
117 * ownership of the axis to this graph.
118 *
119 * If \a axis is null, a temporary default axis with no labels and an automatically adjusting
120 * range is created.
121 * This temporary axis is destroyed if another axis is set explicitly to the
122 * same orientation.
123 *
124 * \sa addAxis(), releaseAxis()
125 */
126void Q3DScatter::setAxisX(QValue3DAxis *axis)
127{
128 dptr()->setAxisX(axis);
129}
130
131QValue3DAxis *Q3DScatter::axisX() const
132{
133 return static_cast<QValue3DAxis *>(dptrc()->axisX());
134}
135
136/*!
137 * \property Q3DScatter::axisY
138 *
139 * \brief The active y-axis.
140 *
141 * Sets \a axis as the active y-axis. Implicitly calls addAxis() to transfer the
142 * ownership of the axis to this graph.
143 *
144 * If \a axis is null, a temporary default axis with no labels and an automatically adjusting
145 * range is created.
146 * This temporary axis is destroyed if another axis is set explicitly to the
147 * same orientation.
148 *
149 * \sa addAxis(), releaseAxis()
150 */
151void Q3DScatter::setAxisY(QValue3DAxis *axis)
152{
153 dptr()->setAxisY(axis);
154}
155
156QValue3DAxis *Q3DScatter::axisY() const
157{
158 return static_cast<QValue3DAxis *>(dptrc()->axisY());
159}
160
161/*!
162 * \property Q3DScatter::axisZ
163 *
164 * \brief The active z-axis.
165 *
166 * Sets \a axis as the active z-axis. Implicitly calls addAxis() to transfer the
167 * ownership of the axis to this graph.
168 *
169 * If \a axis is null, a temporary default axis with no labels and an automatically adjusting
170 * range is created.
171 * This temporary axis is destroyed if another axis is set explicitly to the
172 * same orientation.
173 *
174 * \sa addAxis(), releaseAxis()
175 */
176void Q3DScatter::setAxisZ(QValue3DAxis *axis)
177{
178 dptr()->setAxisZ(axis);
179}
180
181QValue3DAxis *Q3DScatter::axisZ() const
182{
183 return static_cast<QValue3DAxis *>(dptrc()->axisZ());
184}
185
186/*!
187 * \property Q3DScatter::selectedSeries
188 *
189 * \brief The selected series or null.
190 */
191QScatter3DSeries *Q3DScatter::selectedSeries() const
192{
193 return dptrc()->selectedSeries();
194}
195
196/*!
197 * Adds \a axis to the graph. The axes added via addAxis are not yet taken to use,
198 * addAxis is simply used to give the ownership of the \a axis to the graph.
199 * The \a axis must not be null or added to another graph.
200 *
201 * \sa releaseAxis(), setAxisX(), setAxisY(), setAxisZ()
202 */
203void Q3DScatter::addAxis(QValue3DAxis *axis)
204{
205 dptr()->m_scatterController->addAxis(axis);
206}
207
208/*!
209 * Releases the ownership of the \a axis back to the caller, if it is added to this graph.
210 * If the released \a axis is in use, a new default axis will be created and set active.
211 *
212 * If the default axis is released and added back later, it behaves as any other axis would.
213 *
214 * \sa addAxis(), setAxisX(), setAxisY(), setAxisZ()
215 */
216void Q3DScatter::releaseAxis(QValue3DAxis *axis)
217{
218 dptr()->m_scatterController->releaseAxis(axis);
219}
220
221/*!
222 * Returns the list of all added axes.
223 *
224 * \sa addAxis()
225 */
226QList<QValue3DAxis *> Q3DScatter::axes() const
227{
228 QList<QAbstract3DAxis *> abstractAxes = dptrc()->m_scatterController->axes();
229 QList<QValue3DAxis *> retList;
230 for (QAbstract3DAxis *axis : abstractAxes)
231 retList.append(t: static_cast<QValue3DAxis *>(axis));
232
233 return retList;
234}
235
236/*!
237 * \internal
238 */
239QQuickGraphsScatter *Q3DScatter::dptr()
240{
241 return static_cast<QQuickGraphsScatter *>(m_graphsItem.data());
242}
243
244/*!
245 * \internal
246 */
247const QQuickGraphsScatter *Q3DScatter::dptrc() const
248{
249 return static_cast<const QQuickGraphsScatter *>(m_graphsItem.data());
250}
251
252QT_END_NAMESPACE
253
254

source code of qtgraphs/src/graphs/engine/q3dscatter.cpp