1 /*
2  * DQt - D bindings for the Qt Toolkit
3  *
4  * GNU Lesser General Public License Usage
5  * This file may be used under the terms of the GNU Lesser
6  * General Public License version 3 as published by the Free Software
7  * Foundation and appearing in the file LICENSE.LGPL3 included in the
8  * packaging of this file. Please review the following information to
9  * ensure the GNU Lesser General Public License version 3 requirements
10  * will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
11  */
12 module qt.gui.vector3d;
13 extern(C++):
14 
15 import qt.config;
16 import qt.helpers;
17 version(QT_NO_VECTOR2D){}else
18 version(QT_NO_VECTOR3D){}else
19     import qt.gui.vector2d;
20 version(QT_NO_VECTOR3D){}else
21 version(QT_NO_VECTOR4D){}else
22     import qt.gui.vector4d;
23 version(QT_NO_VECTOR3D){}else
24 {
25     import qt.core.metatype;
26     import qt.core.namespace;
27     import qt.core.point;
28     import qt.core.rect;
29     import qt.core.typeinfo;
30     import qt.core.variant;
31 }
32 
33 version(QT_NO_VECTOR3D)
34 {
35 extern(C++, class) struct QVector3D;
36 }
37 version(QT_NO_VECTOR3D){}else
38 {
39 
40 /// Binding for C++ class [QVector3D](https://doc.qt.io/qt-6/qvector3d.html).
41 @Q_PRIMITIVE_TYPE extern(C++, class) struct QVector3D
42 {
43 public:
44     /+pragma(inline, true) this()/+ noexcept+/
45     {
46         this.v = [0.0f, 0.0f, 0.0f];
47     }+/
48     /+ explicit +/this(/+ Qt:: +/qt.core.namespace.Initialization)/+ noexcept+/ {}
49     this(float xpos, float ypos, float zpos)/+ noexcept+/
50     {
51         this.v = [xpos, ypos, zpos];
52     }
53 
54     /+ explicit +/pragma(inline, true) this(QPoint point)/+ noexcept+/
55     {
56         this.v = [float(point.x()), float(point.y()), 0.0f];
57     }
58     /+ explicit +/pragma(inline, true) this(QPointF point)/+ noexcept+/
59     {
60         this.v = [float(point.x()), float(point.y()), 0.0f];
61     }
62 /+ #ifndef QT_NO_VECTOR2D +/
63     version(QT_NO_VECTOR2D){}else
64     {
65         /+ /+ explicit +/pragma(inline, true) this(QVector2D vector)/+ noexcept+/
66         {
67             this.v = [vector[0], vector[1], 0.0f];
68         }
69         pragma(inline, true) this(QVector2D vector, float zpos)/+ noexcept+/
70         {
71             this.v = [vector[0], vector[1], zpos];
72         } +/
73     }
74 /+ #endif
75 #ifndef QT_NO_VECTOR4D +/
76     version(QT_NO_VECTOR4D){}else
77     {
78         /+ /+ explicit +/pragma(inline, true) this(QVector4D vector)/+ noexcept+/
79         {
80             this.v = [vector[0], vector[1], vector[2]];
81         } +/
82     }
83 /+ #endif +/
84 
85     pragma(inline, true) bool isNull() const/+ noexcept+/
86     {
87         import qt.core.global;
88 
89         return qIsNull(v[0]) && qIsNull(v[1]) && qIsNull(v[2]);
90     }
91 
92     pragma(inline, true) float x() const/+ noexcept+/ { return v[0]; }
93     pragma(inline, true) float y() const/+ noexcept+/ { return v[1]; }
94     pragma(inline, true) float z() const/+ noexcept+/ { return v[2]; }
95 
96     pragma(inline, true) void setX(float aX)/+ noexcept+/ { v[0] = aX; }
97     pragma(inline, true) void setY(float aY)/+ noexcept+/ { v[1] = aY; }
98     pragma(inline, true) void setZ(float aZ)/+ noexcept+/ { v[2] = aZ; }
99 
100     /+pragma(inline, true) ref float operator [](int i)
101     {
102         import qt.core.global;
103 
104         (mixin(Q_ASSERT(q{uint(i) < 3u})));
105         return v[i];
106     }+/
107     /+pragma(inline, true) float operator [](int i) const
108     {
109         import qt.core.global;
110 
111         (mixin(Q_ASSERT(q{uint(i) < 3u})));
112         return v[i];
113     }+/
114 
115     /+ /+ [[nodiscard]] +/ pragma(inline, true) float length() const/+ noexcept+/
116     {
117         return qHypot(v[0], v[1], v[2]);
118     }
119     /+ [[nodiscard]] +/ pragma(inline, true) float lengthSquared() const/+ noexcept+/
120     {
121         return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
122     }
123 
124     /+ [[nodiscard]] +/ pragma(inline, true) QVector3D normalized() const/+ noexcept+/
125     {
126         import qt.core.global;
127 
128         const(float) len = length();
129         return qFuzzyIsNull(len - 1.0f) ? this : qFuzzyIsNull(len) ? QVector3D()
130             : QVector3D(v[0] / len, v[1] / len, v[2] / len);
131     }
132     pragma(inline, true) void normalize()/+ noexcept+/
133     {
134         import qt.core.global;
135 
136         const(float) len = length();
137         if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
138             return;
139 
140         v[0] /= len;
141         v[1] /= len;
142         v[2] /= len;
143     } +/
144 
145     /+pragma(inline, true) ref QVector3D operator +=(QVector3D vector)/+ noexcept+/
146     {
147         v[0] += vector.v[0];
148         v[1] += vector.v[1];
149         v[2] += vector.v[2];
150         return this;
151     }+/
152     /+pragma(inline, true) ref QVector3D operator -=(QVector3D vector)/+ noexcept+/
153     {
154         v[0] -= vector.v[0];
155         v[1] -= vector.v[1];
156         v[2] -= vector.v[2];
157         return this;
158     }+/
159     /+pragma(inline, true) ref QVector3D operator *=(float factor)/+ noexcept+/
160     {
161         v[0] *= factor;
162         v[1] *= factor;
163         v[2] *= factor;
164         return this;
165     }+/
166     /+pragma(inline, true) ref QVector3D operator *=(QVector3D vector)/+ noexcept+/
167     {
168         v[0] *= vector.v[0];
169         v[1] *= vector.v[1];
170         v[2] *= vector.v[2];
171         return this;
172     }+/
173     /+pragma(inline, true) ref QVector3D operator /=(float divisor)
174     {
175         import qt.core.global;
176 
177         (mixin(Q_ASSERT(q{divisor < 0 || divisor > 0})));
178         v[0] /= divisor;
179         v[1] /= divisor;
180         v[2] /= divisor;
181         return this;
182     }+/
183     /+pragma(inline, true) ref QVector3D operator /=(QVector3D vector)
184     {
185         import qt.core.global;
186 
187         (mixin(Q_ASSERT(q{vector.v[0] > 0 || vector.v[0] < 0})));
188         (mixin(Q_ASSERT(q{vector.v[1] > 0 || vector.v[1] < 0})));
189         (mixin(Q_ASSERT(q{vector.v[2] > 0 || vector.v[2] < 0})));
190         v[0] /= vector.v[0];
191         v[1] /= vector.v[1];
192         v[2] /= vector.v[2];
193         return this;
194     }+/
195 
196     /+ [[nodiscard]] +/ pragma(inline, true) static float dotProduct(QVector3D v1, QVector3D v2)/+ noexcept+/
197     {
198         return v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1] + v1.v[2] * v2.v[2];
199     }
200     /+ [[nodiscard]] +/ pragma(inline, true) static QVector3D crossProduct(QVector3D v1, QVector3D v2)/+ noexcept+/
201     {
202         return QVector3D(v1.v[1] * v2.v[2] - v1.v[2] * v2.v[1],
203                          v1.v[2] * v2.v[0] - v1.v[0] * v2.v[2],
204                          v1.v[0] * v2.v[1] - v1.v[1] * v2.v[0]);
205     }
206 
207     /+ /+ [[nodiscard]] +/ pragma(inline, true) static QVector3D normal(QVector3D v1, QVector3D v2)/+ noexcept+/
208     {
209         return crossProduct(v1, v2).normalized();
210     }
211     /+ [[nodiscard]] +/ pragma(inline, true) static QVector3D normal(QVector3D v1, QVector3D v2, QVector3D v3)/+ noexcept+/
212     {
213         return crossProduct((v2 - v1), (v3 - v1)).normalized();
214     } +/
215 
216     /+ Q_GUI_EXPORT +/ QVector3D project(ref const(QMatrix4x4) modelView, ref const(QMatrix4x4) projection, ref const(QRect) viewport) const;
217     /+ Q_GUI_EXPORT +/ QVector3D unproject(ref const(QMatrix4x4) modelView, ref const(QMatrix4x4) projection, ref const(QRect) viewport) const;
218 
219 /+ QT_WARNING_PUSH
220 QT_WARNING_DISABLE_FLOAT_COMPARE +/
221     /+ constexpr friend inline bool operator==(QVector3D v1, QVector3D v2) noexcept
222     {
223         return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2];
224     } +/
225 
226     /+ constexpr friend inline bool operator!=(QVector3D v1, QVector3D v2) noexcept
227     {
228         return v1.v[0] != v2.v[0] || v1.v[1] != v2.v[1] || v1.v[2] != v2.v[2];
229     } +/
230 /+ QT_WARNING_POP +/
231     /+ pragma(inline, true) float distanceToPoint(QVector3D point) const/+ noexcept+/
232     {
233         return (this - point).length();
234     }
235     pragma(inline, true) float distanceToPlane(QVector3D plane, QVector3D normal) const/+ noexcept+/
236     {
237         return dotProduct(this - plane, normal);
238     }
239     pragma(inline, true) float distanceToPlane(QVector3D plane1, QVector3D plane2, QVector3D plane3) const/+ noexcept+/
240     {
241         QVector3D n = normal(plane2 - plane1, plane3 - plane1);
242         return dotProduct(this - plane1, n);
243     }
244     pragma(inline, true) float distanceToLine(QVector3D point, QVector3D direction) const/+ noexcept+/
245     {
246         if (direction.isNull())
247             return (this - point).length();
248         QVector3D p = cast(QVector3D)(point + dotProduct(this - point, direction) * direction);
249         return (this - p).length();
250     } +/
251 
252 
253     /+ constexpr friend inline QVector3D operator+(QVector3D v1, QVector3D v2) noexcept
254     {
255         return QVector3D(v1.v[0] + v2.v[0], v1.v[1] + v2.v[1], v1.v[2] + v2.v[2]);
256     } +/
257 
258     /+ constexpr friend inline QVector3D operator-(QVector3D v1, QVector3D v2) noexcept
259     {
260         return QVector3D(v1.v[0] - v2.v[0], v1.v[1] - v2.v[1], v1.v[2] - v2.v[2]);
261     } +/
262 
263     /+ constexpr friend inline QVector3D operator*(float factor, QVector3D vector) noexcept
264     {
265         return QVector3D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor);
266     } +/
267 
268     /+ constexpr friend inline QVector3D operator*(QVector3D vector, float factor) noexcept
269     {
270         return QVector3D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor);
271     } +/
272 
273     /+ constexpr friend inline QVector3D operator*(QVector3D v1, QVector3D v2) noexcept
274     {
275         return QVector3D(v1.v[0] * v2.v[0], v1.v[1] * v2.v[1], v1.v[2] * v2.v[2]);
276     } +/
277 
278     /+ constexpr friend inline QVector3D operator-(QVector3D vector) noexcept
279     {
280         return QVector3D(-vector.v[0], -vector.v[1], -vector.v[2]);
281     } +/
282 
283     /+ constexpr friend inline QVector3D operator/(QVector3D vector, float divisor)
284     {
285         Q_ASSERT(divisor < 0 || divisor > 0);
286         return QVector3D(vector.v[0] / divisor, vector.v[1] / divisor, vector.v[2] / divisor);
287     } +/
288 
289     /+ constexpr friend inline QVector3D operator/(QVector3D vector, QVector3D divisor)
290     {
291         Q_ASSERT(divisor.v[0] > 0 || divisor.v[0] < 0);
292         Q_ASSERT(divisor.v[1] > 0 || divisor.v[1] < 0);
293         Q_ASSERT(divisor.v[2] > 0 || divisor.v[2] < 0);
294         return QVector3D(vector.v[0] / divisor.v[0], vector.v[1] / divisor.v[1],
295                          vector.v[2] / divisor.v[2]);
296     } +/
297 
298     /+ friend Q_GUI_EXPORT bool qFuzzyCompare(QVector3D v1, QVector3D v2) noexcept; +/
299 
300 /+ #ifndef QT_NO_VECTOR2D +/
301     version(QT_NO_VECTOR2D){}else
302     {
303         pragma(inline, true) QVector2D toVector2D() const/+ noexcept+/
304         {
305             return QVector2D(v[0], v[1]);
306         }
307     }
308 /+ #endif
309 #ifndef QT_NO_VECTOR4D +/
310     version(QT_NO_VECTOR4D){}else
311     {
312         pragma(inline, true) QVector4D toVector4D() const/+ noexcept+/
313         {
314             return QVector4D(v[0], v[1], v[2], 0.0f);
315         }
316     }
317 /+ #endif +/
318 
319     pragma(inline, true) QPoint toPoint() const/+ noexcept+/
320     {
321         import qt.core.global;
322 
323         return QPoint(qRound(v[0]), qRound(v[1]));
324     }
325     pragma(inline, true) QPointF toPointF() const/+ noexcept+/
326     {
327         import qt.core.global;
328 
329         return QPointF(qreal(v[0]), qreal(v[1]));
330     }
331 
332     /+/+ Q_GUI_EXPORT +/ auto opCast(T : QVariant)() const;+/
333 
334 private:
335     float[3] v = [0.0f, 0.0f, 0.0f];
336 
337     /+ friend class QVector2D; +/
338     /+ friend class QVector4D; +/
339     static if(!defined!"QT_NO_MATRIX4X4")
340     {
341         /+ friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix); +/
342         /+ friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector); +/
343     }
344 
345     /+ template <std::size_t I,
346               typename V,
347               std::enable_if_t<(I < 3), bool> = true,
348               std::enable_if_t<std::is_same_v<std::decay_t<V>, QVector3D>, bool> = true> +/
349     /+ friend constexpr decltype(auto) get(V &&vec) noexcept
350     {
351         static if (I == 0)
352             return (std::forward<V>(vec).v[0]);
353         else static if (I == 1)
354             return (std::forward<V>(vec).v[1]);
355         else static if (I == 2)
356             return (std::forward<V>(vec).v[2]);
357     } +/
358     mixin(CREATE_CONVENIENCE_WRAPPERS);
359 }
360 }
361