1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QVECTORND_H
6#define QVECTORND_H
7
8#include <QtGui/qtguiglobal.h>
9#include <QtCore/qpoint.h>
10#include <QtCore/qrect.h>
11#include <QtCore/qmath.h>
12
13#include <QtCore/q20type_traits.h>
14#include <QtCore/q23utility.h>
15
16QT_BEGIN_NAMESPACE
17
18// QT_ENABLE_P0846_SEMANTICS_FOR(get) // from qpoint.h
19
20class QVector2D;
21class QVector3D;
22class QVector4D;
23class QMatrix4x4;
24class QVariant;
25
26/***************************** QVector2D *****************************/
27
28#ifndef QT_NO_VECTOR2D
29
30class QVector2D
31{
32public:
33 constexpr QVector2D() noexcept;
34 explicit QVector2D(Qt::Initialization) noexcept {}
35 constexpr QVector2D(float xpos, float ypos) noexcept;
36 constexpr explicit QVector2D(QPoint point) noexcept;
37 constexpr explicit QVector2D(QPointF point) noexcept;
38#ifndef QT_NO_VECTOR3D
39 constexpr explicit QVector2D(QVector3D vector) noexcept;
40#endif
41#ifndef QT_NO_VECTOR4D
42 constexpr explicit QVector2D(QVector4D vector) noexcept;
43#endif
44
45 constexpr bool isNull() const noexcept;
46
47 constexpr float x() const noexcept;
48 constexpr float y() const noexcept;
49
50 constexpr void setX(float x) noexcept;
51 constexpr void setY(float y) noexcept;
52
53 constexpr float &operator[](int i);
54 constexpr float operator[](int i) const;
55
56 [[nodiscard]] float length() const noexcept;
57 [[nodiscard]] constexpr float lengthSquared() const noexcept;
58
59 [[nodiscard]] QVector2D normalized() const noexcept;
60 void normalize() noexcept;
61
62 [[nodiscard]] float distanceToPoint(QVector2D point) const noexcept;
63 [[nodiscard]] float distanceToLine(QVector2D point, QVector2D direction) const noexcept;
64
65 constexpr QVector2D &operator+=(QVector2D vector) noexcept;
66 constexpr QVector2D &operator-=(QVector2D vector) noexcept;
67 constexpr QVector2D &operator*=(float factor) noexcept;
68 constexpr QVector2D &operator*=(QVector2D vector) noexcept;
69 constexpr QVector2D &operator/=(float divisor);
70 constexpr QVector2D &operator/=(QVector2D vector);
71
72 [[nodiscard]] static constexpr float dotProduct(QVector2D v1, QVector2D v2) noexcept;
73
74QT_WARNING_PUSH
75QT_WARNING_DISABLE_FLOAT_COMPARE
76 constexpr friend inline bool operator==(QVector2D v1, QVector2D v2) noexcept
77 {
78 return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1];
79 }
80
81 constexpr friend inline bool operator!=(QVector2D v1, QVector2D v2) noexcept
82 {
83 return v1.v[0] != v2.v[0] || v1.v[1] != v2.v[1];
84 }
85QT_WARNING_POP
86
87 constexpr friend inline QVector2D operator+(QVector2D v1, QVector2D v2) noexcept
88 {
89 return QVector2D(v1.v[0] + v2.v[0], v1.v[1] + v2.v[1]);
90 }
91
92 constexpr friend inline QVector2D operator-(QVector2D v1, QVector2D v2) noexcept
93 {
94 return QVector2D(v1.v[0] - v2.v[0], v1.v[1] - v2.v[1]);
95 }
96
97 constexpr friend inline QVector2D operator*(float factor, QVector2D vector) noexcept
98 {
99 return QVector2D(vector.v[0] * factor, vector.v[1] * factor);
100 }
101
102 constexpr friend inline QVector2D operator*(QVector2D vector, float factor) noexcept
103 {
104 return QVector2D(vector.v[0] * factor, vector.v[1] * factor);
105 }
106
107 constexpr friend inline QVector2D operator*(QVector2D v1, QVector2D v2) noexcept
108 {
109 return QVector2D(v1.v[0] * v2.v[0], v1.v[1] * v2.v[1]);
110 }
111
112 constexpr friend inline QVector2D operator-(QVector2D vector) noexcept
113 {
114 return QVector2D(-vector.v[0], -vector.v[1]);
115 }
116
117 constexpr friend inline QVector2D operator/(QVector2D vector, float divisor)
118 {
119 Q_ASSERT(divisor < 0 || divisor > 0);
120 return QVector2D(vector.v[0] / divisor, vector.v[1] / divisor);
121 }
122
123 constexpr friend inline QVector2D operator/(QVector2D vector, QVector2D divisor)
124 {
125 Q_ASSERT(divisor.v[0] < 0 || divisor.v[0] > 0);
126 Q_ASSERT(divisor.v[1] < 0 || divisor.v[1] > 0);
127 return QVector2D(vector.v[0] / divisor.v[0], vector.v[1] / divisor.v[1]);
128 }
129
130 friend Q_GUI_EXPORT bool qFuzzyCompare(QVector2D v1, QVector2D v2) noexcept;
131
132#ifndef QT_NO_VECTOR3D
133 constexpr QVector3D toVector3D() const noexcept;
134#endif
135#ifndef QT_NO_VECTOR4D
136 constexpr QVector4D toVector4D() const noexcept;
137#endif
138
139 constexpr QPoint toPoint() const noexcept;
140 constexpr QPointF toPointF() const noexcept;
141
142 Q_GUI_EXPORT operator QVariant() const;
143
144private:
145 float v[2];
146
147 friend class QVector3D;
148 friend class QVector4D;
149
150 template <std::size_t I,
151 typename V,
152 std::enable_if_t<(I < 2), bool> = true,
153 std::enable_if_t<std::is_same_v<q20::remove_cvref_t<V>, QVector2D>, bool> = true>
154 friend constexpr decltype(auto) get(V &&vec) noexcept
155 {
156 return q23::forward_like<V>(vec.v[I]);
157 }
158};
159
160Q_DECLARE_TYPEINFO(QVector2D, Q_PRIMITIVE_TYPE);
161
162#endif // QT_NO_VECTOR2D
163
164
165
166/***************************** QVector3D *****************************/
167
168#ifndef QT_NO_VECTOR3D
169
170class QVector3D
171{
172public:
173 constexpr QVector3D() noexcept;
174 explicit QVector3D(Qt::Initialization) noexcept {}
175 constexpr QVector3D(float xpos, float ypos, float zpos) noexcept : v{xpos, ypos, zpos} {}
176
177 constexpr explicit QVector3D(QPoint point) noexcept;
178 constexpr explicit QVector3D(QPointF point) noexcept;
179#ifndef QT_NO_VECTOR2D
180 constexpr explicit QVector3D(QVector2D vector) noexcept;
181 constexpr QVector3D(QVector2D vector, float zpos) noexcept;
182#endif
183#ifndef QT_NO_VECTOR4D
184 constexpr explicit QVector3D(QVector4D vector) noexcept;
185#endif
186
187 constexpr bool isNull() const noexcept;
188
189 constexpr float x() const noexcept;
190 constexpr float y() const noexcept;
191 constexpr float z() const noexcept;
192
193 constexpr void setX(float x) noexcept;
194 constexpr void setY(float y) noexcept;
195 constexpr void setZ(float z) noexcept;
196
197 constexpr float &operator[](int i);
198 constexpr float operator[](int i) const;
199
200 [[nodiscard]] float length() const noexcept;
201 [[nodiscard]] constexpr float lengthSquared() const noexcept;
202
203 [[nodiscard]] QVector3D normalized() const noexcept;
204 void normalize() noexcept;
205
206 constexpr QVector3D &operator+=(QVector3D vector) noexcept;
207 constexpr QVector3D &operator-=(QVector3D vector) noexcept;
208 constexpr QVector3D &operator*=(float factor) noexcept;
209 constexpr QVector3D &operator*=(QVector3D vector) noexcept;
210 constexpr QVector3D &operator/=(float divisor);
211 constexpr QVector3D &operator/=(QVector3D vector);
212
213 [[nodiscard]] static constexpr float dotProduct(QVector3D v1, QVector3D v2) noexcept;
214 [[nodiscard]] static constexpr QVector3D crossProduct(QVector3D v1, QVector3D v2) noexcept;
215
216 [[nodiscard]] static QVector3D normal(QVector3D v1, QVector3D v2) noexcept;
217 [[nodiscard]] static QVector3D normal(QVector3D v1, QVector3D v2, QVector3D v3) noexcept;
218
219 Q_GUI_EXPORT QVector3D project(const QMatrix4x4 &modelView, const QMatrix4x4 &projection, const QRect &viewport) const;
220 Q_GUI_EXPORT QVector3D unproject(const QMatrix4x4 &modelView, const QMatrix4x4 &projection, const QRect &viewport) const;
221
222QT_WARNING_PUSH
223QT_WARNING_DISABLE_FLOAT_COMPARE
224 constexpr friend inline bool operator==(QVector3D v1, QVector3D v2) noexcept
225 {
226 return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2];
227 }
228
229 constexpr friend inline bool operator!=(QVector3D v1, QVector3D v2) noexcept
230 {
231 return v1.v[0] != v2.v[0] || v1.v[1] != v2.v[1] || v1.v[2] != v2.v[2];
232 }
233QT_WARNING_POP
234 float distanceToPoint(QVector3D point) const noexcept;
235 constexpr float distanceToPlane(QVector3D plane, QVector3D normal) const noexcept;
236 float distanceToPlane(QVector3D plane1, QVector3D plane2, QVector3D plane3) const noexcept;
237 float distanceToLine(QVector3D point, QVector3D direction) const noexcept;
238
239
240 constexpr friend inline QVector3D operator+(QVector3D v1, QVector3D v2) noexcept
241 {
242 return QVector3D(v1.v[0] + v2.v[0], v1.v[1] + v2.v[1], v1.v[2] + v2.v[2]);
243 }
244
245 constexpr friend inline QVector3D operator-(QVector3D v1, QVector3D v2) noexcept
246 {
247 return QVector3D(v1.v[0] - v2.v[0], v1.v[1] - v2.v[1], v1.v[2] - v2.v[2]);
248 }
249
250 constexpr friend inline QVector3D operator*(float factor, QVector3D vector) noexcept
251 {
252 return QVector3D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor);
253 }
254
255 constexpr friend inline QVector3D operator*(QVector3D vector, float factor) noexcept
256 {
257 return QVector3D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor);
258 }
259
260 constexpr friend inline QVector3D operator*(QVector3D v1, QVector3D v2) noexcept
261 {
262 return QVector3D(v1.v[0] * v2.v[0], v1.v[1] * v2.v[1], v1.v[2] * v2.v[2]);
263 }
264
265 constexpr friend inline QVector3D operator-(QVector3D vector) noexcept
266 {
267 return QVector3D(-vector.v[0], -vector.v[1], -vector.v[2]);
268 }
269
270 constexpr friend inline QVector3D operator/(QVector3D vector, float divisor)
271 {
272 Q_ASSERT(divisor < 0 || divisor > 0);
273 return QVector3D(vector.v[0] / divisor, vector.v[1] / divisor, vector.v[2] / divisor);
274 }
275
276 constexpr friend inline QVector3D operator/(QVector3D vector, QVector3D divisor)
277 {
278 Q_ASSERT(divisor.v[0] > 0 || divisor.v[0] < 0);
279 Q_ASSERT(divisor.v[1] > 0 || divisor.v[1] < 0);
280 Q_ASSERT(divisor.v[2] > 0 || divisor.v[2] < 0);
281 return QVector3D(vector.v[0] / divisor.v[0], vector.v[1] / divisor.v[1],
282 vector.v[2] / divisor.v[2]);
283 }
284
285 friend Q_GUI_EXPORT bool qFuzzyCompare(QVector3D v1, QVector3D v2) noexcept;
286
287#ifndef QT_NO_VECTOR2D
288 constexpr QVector2D toVector2D() const noexcept;
289#endif
290#ifndef QT_NO_VECTOR4D
291 constexpr QVector4D toVector4D() const noexcept;
292#endif
293
294 constexpr QPoint toPoint() const noexcept;
295 constexpr QPointF toPointF() const noexcept;
296
297 Q_GUI_EXPORT operator QVariant() const;
298
299private:
300 float v[3];
301
302 friend class QVector2D;
303 friend class QVector4D;
304#ifndef QT_NO_MATRIX4X4
305 friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
306 friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
307#endif
308
309 template <std::size_t I,
310 typename V,
311 std::enable_if_t<(I < 3), bool> = true,
312 std::enable_if_t<std::is_same_v<q20::remove_cvref_t<V>, QVector3D>, bool> = true>
313 friend constexpr decltype(auto) get(V &&vec) noexcept
314 {
315 return q23::forward_like<V>(vec.v[I]);
316 }
317};
318
319Q_DECLARE_TYPEINFO(QVector3D, Q_PRIMITIVE_TYPE);
320
321#endif // QT_NO_VECTOR3D
322
323
324
325/***************************** QVector4D *****************************/
326
327#ifndef QT_NO_VECTOR4D
328
329class QVector4D
330{
331public:
332 constexpr QVector4D() noexcept;
333 explicit QVector4D(Qt::Initialization) noexcept {}
334 constexpr QVector4D(float xpos, float ypos, float zpos, float wpos) noexcept;
335 constexpr explicit QVector4D(QPoint point) noexcept;
336 constexpr explicit QVector4D(QPointF point) noexcept;
337#ifndef QT_NO_VECTOR2D
338 constexpr explicit QVector4D(QVector2D vector) noexcept;
339 constexpr QVector4D(QVector2D vector, float zpos, float wpos) noexcept;
340#endif
341#ifndef QT_NO_VECTOR3D
342 constexpr explicit QVector4D(QVector3D vector) noexcept;
343 constexpr QVector4D(QVector3D vector, float wpos) noexcept;
344#endif
345
346 constexpr bool isNull() const noexcept;
347
348 constexpr float x() const noexcept;
349 constexpr float y() const noexcept;
350 constexpr float z() const noexcept;
351 constexpr float w() const noexcept;
352
353 constexpr void setX(float x) noexcept;
354 constexpr void setY(float y) noexcept;
355 constexpr void setZ(float z) noexcept;
356 constexpr void setW(float w) noexcept;
357
358 constexpr float &operator[](int i);
359 constexpr float operator[](int i) const;
360
361 [[nodiscard]] float length() const noexcept;
362 [[nodiscard]] constexpr float lengthSquared() const noexcept;
363
364 [[nodiscard]] QVector4D normalized() const noexcept;
365 void normalize() noexcept;
366
367 constexpr QVector4D &operator+=(QVector4D vector) noexcept;
368 constexpr QVector4D &operator-=(QVector4D vector) noexcept;
369 constexpr QVector4D &operator*=(float factor) noexcept;
370 constexpr QVector4D &operator*=(QVector4D vector) noexcept;
371 constexpr QVector4D &operator/=(float divisor);
372 constexpr inline QVector4D &operator/=(QVector4D vector);
373
374 [[nodiscard]] static constexpr float dotProduct(QVector4D v1, QVector4D v2) noexcept;
375
376QT_WARNING_PUSH
377QT_WARNING_DISABLE_FLOAT_COMPARE
378 constexpr friend inline bool operator==(QVector4D v1, QVector4D v2) noexcept
379 {
380 return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2] && v1.v[3] == v2.v[3];
381 }
382
383 constexpr friend inline bool operator!=(QVector4D v1, QVector4D v2) noexcept
384 {
385 return v1.v[0] != v2.v[0] || v1.v[1] != v2.v[1] || v1.v[2] != v2.v[2] || v1.v[3] != v2.v[3];
386 }
387QT_WARNING_POP
388 constexpr friend inline QVector4D operator+(QVector4D v1, QVector4D v2) noexcept
389 {
390 return QVector4D(v1.v[0] + v2.v[0], v1.v[1] + v2.v[1], v1.v[2] + v2.v[2], v1.v[3] + v2.v[3]);
391 }
392
393 constexpr friend inline QVector4D operator-(QVector4D v1, QVector4D v2) noexcept
394 {
395 return QVector4D(v1.v[0] - v2.v[0], v1.v[1] - v2.v[1], v1.v[2] - v2.v[2], v1.v[3] - v2.v[3]);
396 }
397
398 constexpr friend inline QVector4D operator*(float factor, QVector4D vector) noexcept
399 {
400 return QVector4D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor, vector.v[3] * factor);
401 }
402
403 constexpr friend inline QVector4D operator*(QVector4D vector, float factor) noexcept
404 {
405 return QVector4D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor, vector.v[3] * factor);
406 }
407
408 constexpr friend inline QVector4D operator*(QVector4D v1, QVector4D v2) noexcept
409 {
410 return QVector4D(v1.v[0] * v2.v[0], v1.v[1] * v2.v[1], v1.v[2] * v2.v[2], v1.v[3] * v2.v[3]);
411 }
412
413 constexpr friend inline QVector4D operator-(QVector4D vector) noexcept
414 {
415 return QVector4D(-vector.v[0], -vector.v[1], -vector.v[2], -vector.v[3]);
416 }
417
418 constexpr friend inline QVector4D operator/(QVector4D vector, float divisor)
419 {
420 Q_ASSERT(divisor < 0 || divisor > 0);
421 return QVector4D(vector.v[0] / divisor, vector.v[1] / divisor, vector.v[2] / divisor, vector.v[3] / divisor);
422 }
423
424 constexpr friend inline QVector4D operator/(QVector4D vector, QVector4D divisor)
425 {
426 Q_ASSERT(divisor.v[0] > 0 || divisor.v[0] < 0);
427 Q_ASSERT(divisor.v[1] > 0 || divisor.v[1] < 0);
428 Q_ASSERT(divisor.v[2] > 0 || divisor.v[2] < 0);
429 Q_ASSERT(divisor.v[3] > 0 || divisor.v[3] < 0);
430 return QVector4D(vector.v[0] / divisor.v[0], vector.v[1] / divisor.v[1],
431 vector.v[2] / divisor.v[2], vector.v[3] / divisor.v[3]);
432 }
433
434 friend Q_GUI_EXPORT bool qFuzzyCompare(QVector4D v1, QVector4D v2) noexcept;
435
436#ifndef QT_NO_VECTOR2D
437 constexpr QVector2D toVector2D() const noexcept;
438 constexpr QVector2D toVector2DAffine() const noexcept;
439#endif
440#ifndef QT_NO_VECTOR3D
441 constexpr QVector3D toVector3D() const noexcept;
442 constexpr QVector3D toVector3DAffine() const noexcept;
443#endif
444
445 constexpr QPoint toPoint() const noexcept;
446 constexpr QPointF toPointF() const noexcept;
447
448 Q_GUI_EXPORT operator QVariant() const;
449
450private:
451 float v[4];
452
453 friend class QVector2D;
454 friend class QVector3D;
455 friend class QMatrix4x4;
456#ifndef QT_NO_MATRIX4X4
457 friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
458 friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
459#endif
460
461 template <std::size_t I,
462 typename V,
463 std::enable_if_t<(I < 4), bool> = true,
464 std::enable_if_t<std::is_same_v<q20::remove_cvref_t<V>, QVector4D>, bool> = true>
465 friend constexpr decltype(auto) get(V &&vec) noexcept
466 {
467 return q23::forward_like<V>(vec.v[I]);
468 }
469};
470
471Q_DECLARE_TYPEINFO(QVector4D, Q_PRIMITIVE_TYPE);
472
473#endif // QT_NO_VECTOR4D
474
475
476
477/***************************** QVector2D *****************************/
478
479#ifndef QT_NO_VECTOR2D
480
481constexpr inline QVector2D::QVector2D() noexcept : v{0.0f, 0.0f} {}
482
483constexpr inline QVector2D::QVector2D(float xpos, float ypos) noexcept : v{xpos, ypos} {}
484
485constexpr inline QVector2D::QVector2D(QPoint point) noexcept : v{float(point.x()), float(point.y())} {}
486
487constexpr inline QVector2D::QVector2D(QPointF point) noexcept : v{float(point.x()), float(point.y())} {}
488
489#ifndef QT_NO_VECTOR3D
490constexpr inline QVector2D::QVector2D(QVector3D vector) noexcept : v{vector[0], vector[1]} {}
491#endif
492#ifndef QT_NO_VECTOR4D
493constexpr inline QVector2D::QVector2D(QVector4D vector) noexcept : v{vector[0], vector[1]} {}
494#endif
495
496constexpr inline bool QVector2D::isNull() const noexcept
497{
498 return qIsNull(f: v[0]) && qIsNull(f: v[1]);
499}
500
501constexpr inline float QVector2D::x() const noexcept { return v[0]; }
502constexpr inline float QVector2D::y() const noexcept { return v[1]; }
503
504constexpr inline void QVector2D::setX(float aX) noexcept { v[0] = aX; }
505constexpr inline void QVector2D::setY(float aY) noexcept { v[1] = aY; }
506
507constexpr inline float &QVector2D::operator[](int i)
508{
509 Q_ASSERT(uint(i) < 2u);
510 return v[i];
511}
512
513constexpr inline float QVector2D::operator[](int i) const
514{
515 Q_ASSERT(uint(i) < 2u);
516 return v[i];
517}
518
519inline float QVector2D::length() const noexcept
520{
521 return qHypot(x: v[0], y: v[1]);
522}
523
524constexpr inline float QVector2D::lengthSquared() const noexcept
525{
526 return v[0] * v[0] + v[1] * v[1];
527}
528
529inline QVector2D QVector2D::normalized() const noexcept
530{
531 const float len = length();
532 return qFuzzyIsNull(f: len - 1.0f) ? *this : qFuzzyIsNull(f: len) ? QVector2D()
533 : QVector2D(v[0] / len, v[1] / len);
534}
535
536inline void QVector2D::normalize() noexcept
537{
538 const float len = length();
539 if (qFuzzyIsNull(f: len - 1.0f) || qFuzzyIsNull(f: len))
540 return;
541
542 v[0] /= len;
543 v[1] /= len;
544}
545
546inline float QVector2D::distanceToPoint(QVector2D point) const noexcept
547{
548 return (*this - point).length();
549}
550
551inline float QVector2D::distanceToLine(QVector2D point, QVector2D direction) const noexcept
552{
553 if (direction.isNull())
554 return (*this - point).length();
555 QVector2D p = point + dotProduct(v1: *this - point, v2: direction) * direction;
556 return (*this - p).length();
557}
558
559constexpr inline QVector2D &QVector2D::operator+=(QVector2D vector) noexcept
560{
561 v[0] += vector.v[0];
562 v[1] += vector.v[1];
563 return *this;
564}
565
566constexpr inline QVector2D &QVector2D::operator-=(QVector2D vector) noexcept
567{
568 v[0] -= vector.v[0];
569 v[1] -= vector.v[1];
570 return *this;
571}
572
573constexpr inline QVector2D &QVector2D::operator*=(float factor) noexcept
574{
575 v[0] *= factor;
576 v[1] *= factor;
577 return *this;
578}
579
580constexpr inline QVector2D &QVector2D::operator*=(QVector2D vector) noexcept
581{
582 v[0] *= vector.v[0];
583 v[1] *= vector.v[1];
584 return *this;
585}
586
587constexpr inline QVector2D &QVector2D::operator/=(float divisor)
588{
589 Q_ASSERT(divisor < 0 || divisor > 0);
590 v[0] /= divisor;
591 v[1] /= divisor;
592 return *this;
593}
594
595constexpr inline QVector2D &QVector2D::operator/=(QVector2D vector)
596{
597 Q_ASSERT(vector.v[0] > 0 || vector.v[0] < 0);
598 Q_ASSERT(vector.v[1] > 0 || vector.v[1] < 0);
599 v[0] /= vector.v[0];
600 v[1] /= vector.v[1];
601 return *this;
602}
603
604constexpr inline float QVector2D::dotProduct(QVector2D v1, QVector2D v2) noexcept
605{
606 return v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1];
607}
608
609#ifndef QT_NO_VECTOR3D
610constexpr inline QVector3D QVector2D::toVector3D() const noexcept
611{
612 return QVector3D(v[0], v[1], 0.0f);
613}
614#endif
615#ifndef QT_NO_VECTOR4D
616constexpr inline QVector4D QVector2D::toVector4D() const noexcept
617{
618 return QVector4D(v[0], v[1], 0.0f, 0.0f);
619}
620#endif
621
622
623constexpr inline QPoint QVector2D::toPoint() const noexcept
624{
625 return QPoint(qRound(f: v[0]), qRound(f: v[1]));
626}
627
628constexpr inline QPointF QVector2D::toPointF() const noexcept
629{
630 return QPointF(qreal(v[0]), qreal(v[1]));
631}
632
633#ifndef QT_NO_DEBUG_STREAM
634Q_GUI_EXPORT QDebug operator<<(QDebug dbg, QVector2D vector);
635#endif
636
637#ifndef QT_NO_DATASTREAM
638Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, QVector2D );
639Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector2D &);
640#endif
641
642#endif // QT_NO_VECTOR2D
643
644
645
646/***************************** QVector3D *****************************/
647
648#ifndef QT_NO_VECTOR3D
649
650constexpr inline QVector3D::QVector3D() noexcept : v{0.0f, 0.0f, 0.0f} {}
651
652constexpr inline QVector3D::QVector3D(QPoint point) noexcept : v{float(point.x()), float(point.y()), 0.0f} {}
653
654constexpr inline QVector3D::QVector3D(QPointF point) noexcept : v{float(point.x()), float(point.y()), 0.0f} {}
655
656#ifndef QT_NO_VECTOR2D
657constexpr inline QVector3D::QVector3D(QVector2D vector) noexcept : v{vector[0], vector[1], 0.0f} {}
658constexpr inline QVector3D::QVector3D(QVector2D vector, float zpos) noexcept : v{vector[0], vector[1], zpos} {}
659#endif
660
661#ifndef QT_NO_VECTOR4D
662constexpr inline QVector3D::QVector3D(QVector4D vector) noexcept : v{vector[0], vector[1], vector[2]} {}
663#endif
664
665constexpr inline bool QVector3D::isNull() const noexcept
666{
667 return qIsNull(f: v[0]) && qIsNull(f: v[1]) && qIsNull(f: v[2]);
668}
669
670constexpr inline float QVector3D::x() const noexcept { return v[0]; }
671constexpr inline float QVector3D::y() const noexcept { return v[1]; }
672constexpr inline float QVector3D::z() const noexcept { return v[2]; }
673
674constexpr inline void QVector3D::setX(float aX) noexcept { v[0] = aX; }
675constexpr inline void QVector3D::setY(float aY) noexcept { v[1] = aY; }
676constexpr inline void QVector3D::setZ(float aZ) noexcept { v[2] = aZ; }
677
678constexpr inline float &QVector3D::operator[](int i)
679{
680 Q_ASSERT(uint(i) < 3u);
681 return v[i];
682}
683
684constexpr inline float QVector3D::operator[](int i) const
685{
686 Q_ASSERT(uint(i) < 3u);
687 return v[i];
688}
689
690inline float QVector3D::length() const noexcept
691{
692 return qHypot(x: v[0], y: v[1], z: v[2]);
693}
694
695inline QVector3D QVector3D::normalized() const noexcept
696{
697 const float len = length();
698 return qFuzzyIsNull(f: len - 1.0f) ? *this : qFuzzyIsNull(f: len) ? QVector3D()
699 : QVector3D(v[0] / len, v[1] / len, v[2] / len);
700}
701
702inline void QVector3D::normalize() noexcept
703{
704 const float len = length();
705 if (qFuzzyIsNull(f: len - 1.0f) || qFuzzyIsNull(f: len))
706 return;
707
708 v[0] /= len;
709 v[1] /= len;
710 v[2] /= len;
711}
712
713constexpr inline float QVector3D::lengthSquared() const noexcept
714{
715 return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
716}
717
718constexpr inline QVector3D &QVector3D::operator+=(QVector3D vector) noexcept
719{
720 v[0] += vector.v[0];
721 v[1] += vector.v[1];
722 v[2] += vector.v[2];
723 return *this;
724}
725
726constexpr inline QVector3D &QVector3D::operator-=(QVector3D vector) noexcept
727{
728 v[0] -= vector.v[0];
729 v[1] -= vector.v[1];
730 v[2] -= vector.v[2];
731 return *this;
732}
733
734constexpr inline QVector3D &QVector3D::operator*=(float factor) noexcept
735{
736 v[0] *= factor;
737 v[1] *= factor;
738 v[2] *= factor;
739 return *this;
740}
741
742constexpr inline QVector3D &QVector3D::operator*=(QVector3D vector) noexcept
743{
744 v[0] *= vector.v[0];
745 v[1] *= vector.v[1];
746 v[2] *= vector.v[2];
747 return *this;
748}
749
750constexpr inline QVector3D &QVector3D::operator/=(float divisor)
751{
752 Q_ASSERT(divisor < 0 || divisor > 0);
753 v[0] /= divisor;
754 v[1] /= divisor;
755 v[2] /= divisor;
756 return *this;
757}
758
759constexpr inline QVector3D &QVector3D::operator/=(QVector3D vector)
760{
761 Q_ASSERT(vector.v[0] > 0 || vector.v[0] < 0);
762 Q_ASSERT(vector.v[1] > 0 || vector.v[1] < 0);
763 Q_ASSERT(vector.v[2] > 0 || vector.v[2] < 0);
764 v[0] /= vector.v[0];
765 v[1] /= vector.v[1];
766 v[2] /= vector.v[2];
767 return *this;
768}
769
770constexpr inline float QVector3D::dotProduct(QVector3D v1, QVector3D v2) noexcept
771{
772 return v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1] + v1.v[2] * v2.v[2];
773}
774
775constexpr inline QVector3D QVector3D::crossProduct(QVector3D v1, QVector3D v2) noexcept
776{
777 return QVector3D(v1.v[1] * v2.v[2] - v1.v[2] * v2.v[1],
778 v1.v[2] * v2.v[0] - v1.v[0] * v2.v[2],
779 v1.v[0] * v2.v[1] - v1.v[1] * v2.v[0]);
780}
781
782inline QVector3D QVector3D::normal(QVector3D v1, QVector3D v2) noexcept
783{
784 return crossProduct(v1, v2).normalized();
785}
786
787inline QVector3D QVector3D::normal(QVector3D v1, QVector3D v2, QVector3D v3) noexcept
788{
789 return crossProduct(v1: (v2 - v1), v2: (v3 - v1)).normalized();
790}
791
792inline float QVector3D::distanceToPoint(QVector3D point) const noexcept
793{
794 return (*this - point).length();
795}
796
797constexpr inline float QVector3D::distanceToPlane(QVector3D plane, QVector3D normal) const noexcept
798{
799 return dotProduct(v1: *this - plane, v2: normal);
800}
801
802inline float QVector3D::distanceToPlane(QVector3D plane1, QVector3D plane2, QVector3D plane3) const noexcept
803{
804 QVector3D n = normal(v1: plane2 - plane1, v2: plane3 - plane1);
805 return dotProduct(v1: *this - plane1, v2: n);
806}
807
808inline float QVector3D::distanceToLine(QVector3D point, QVector3D direction) const noexcept
809{
810 if (direction.isNull())
811 return (*this - point).length();
812 QVector3D p = point + dotProduct(v1: *this - point, v2: direction) * direction;
813 return (*this - p).length();
814}
815
816#ifndef QT_NO_VECTOR2D
817constexpr inline QVector2D QVector3D::toVector2D() const noexcept
818{
819 return QVector2D(v[0], v[1]);
820}
821#endif
822#ifndef QT_NO_VECTOR4D
823constexpr inline QVector4D QVector3D::toVector4D() const noexcept
824{
825 return QVector4D(v[0], v[1], v[2], 0.0f);
826}
827#endif
828
829constexpr inline QPoint QVector3D::toPoint() const noexcept
830{
831 return QPoint(qRound(f: v[0]), qRound(f: v[1]));
832}
833
834constexpr inline QPointF QVector3D::toPointF() const noexcept
835{
836 return QPointF(qreal(v[0]), qreal(v[1]));
837}
838
839#ifndef QT_NO_DEBUG_STREAM
840Q_GUI_EXPORT QDebug operator<<(QDebug dbg, QVector3D vector);
841#endif
842
843#ifndef QT_NO_DATASTREAM
844Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, QVector3D );
845Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector3D &);
846#endif
847
848#endif // QT_NO_VECTOR3D
849
850
851
852/***************************** QVector4D *****************************/
853
854#ifndef QT_NO_VECTOR4D
855
856constexpr inline QVector4D::QVector4D() noexcept : v{0.0f, 0.0f, 0.0f, 0.0f} {}
857
858constexpr inline QVector4D::QVector4D(float xpos, float ypos, float zpos, float wpos) noexcept : v{xpos, ypos, zpos, wpos} {}
859
860constexpr inline QVector4D::QVector4D(QPoint point) noexcept : v{float(point.x()), float(point.y()), 0.0f, 0.0f} {}
861
862constexpr inline QVector4D::QVector4D(QPointF point) noexcept : v{float(point.x()), float(point.y()), 0.0f, 0.0f} {}
863
864#ifndef QT_NO_VECTOR2D
865constexpr QVector4D::QVector4D(QVector2D vector) noexcept : v{vector[0], vector[1], 0.0f, 0.0f} {}
866constexpr QVector4D::QVector4D(QVector2D vector, float zpos, float wpos) noexcept : v{vector[0], vector[1], zpos, wpos} {}
867#endif
868#ifndef QT_NO_VECTOR3D
869constexpr QVector4D::QVector4D(QVector3D vector) noexcept : v{vector[0], vector[1], vector[2], 0.0f} {}
870constexpr QVector4D::QVector4D(QVector3D vector, float wpos) noexcept : v{vector[0], vector[1], vector[2], wpos} {}
871#endif
872
873constexpr inline bool QVector4D::isNull() const noexcept
874{
875 return qIsNull(f: v[0]) && qIsNull(f: v[1]) && qIsNull(f: v[2]) && qIsNull(f: v[3]);
876}
877
878constexpr inline float QVector4D::x() const noexcept { return v[0]; }
879constexpr inline float QVector4D::y() const noexcept { return v[1]; }
880constexpr inline float QVector4D::z() const noexcept { return v[2]; }
881constexpr inline float QVector4D::w() const noexcept { return v[3]; }
882
883constexpr inline void QVector4D::setX(float aX) noexcept { v[0] = aX; }
884constexpr inline void QVector4D::setY(float aY) noexcept { v[1] = aY; }
885constexpr inline void QVector4D::setZ(float aZ) noexcept { v[2] = aZ; }
886constexpr inline void QVector4D::setW(float aW) noexcept { v[3] = aW; }
887
888constexpr inline float &QVector4D::operator[](int i)
889{
890 Q_ASSERT(uint(i) < 4u);
891 return v[i];
892}
893
894constexpr inline float QVector4D::operator[](int i) const
895{
896 Q_ASSERT(uint(i) < 4u);
897 return v[i];
898}
899
900inline float QVector4D::length() const noexcept
901{
902 return qHypot(first: v[0], rest: v[1], rest: v[2], rest: v[3]);
903}
904
905constexpr inline float QVector4D::lengthSquared() const noexcept
906{
907 return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
908}
909
910inline QVector4D QVector4D::normalized() const noexcept
911{
912 const float len = length();
913 return qFuzzyIsNull(f: len - 1.0f) ? *this : qFuzzyIsNull(f: len) ? QVector4D()
914 : QVector4D(v[0] / len, v[1] / len, v[2] / len, v[3] / len);
915}
916
917inline void QVector4D::normalize() noexcept
918{
919 const float len = length();
920 if (qFuzzyIsNull(f: len - 1.0f) || qFuzzyIsNull(f: len))
921 return;
922
923 v[0] /= len;
924 v[1] /= len;
925 v[2] /= len;
926 v[3] /= len;
927}
928
929constexpr inline QVector4D &QVector4D::operator+=(QVector4D vector) noexcept
930{
931 v[0] += vector.v[0];
932 v[1] += vector.v[1];
933 v[2] += vector.v[2];
934 v[3] += vector.v[3];
935 return *this;
936}
937
938constexpr inline QVector4D &QVector4D::operator-=(QVector4D vector) noexcept
939{
940 v[0] -= vector.v[0];
941 v[1] -= vector.v[1];
942 v[2] -= vector.v[2];
943 v[3] -= vector.v[3];
944 return *this;
945}
946
947constexpr inline QVector4D &QVector4D::operator*=(float factor) noexcept
948{
949 v[0] *= factor;
950 v[1] *= factor;
951 v[2] *= factor;
952 v[3] *= factor;
953 return *this;
954}
955
956constexpr inline QVector4D &QVector4D::operator*=(QVector4D vector) noexcept
957{
958 v[0] *= vector.v[0];
959 v[1] *= vector.v[1];
960 v[2] *= vector.v[2];
961 v[3] *= vector.v[3];
962 return *this;
963}
964
965constexpr inline QVector4D &QVector4D::operator/=(float divisor)
966{
967 Q_ASSERT(divisor < 0 || divisor > 0);
968 v[0] /= divisor;
969 v[1] /= divisor;
970 v[2] /= divisor;
971 v[3] /= divisor;
972 return *this;
973}
974
975constexpr inline QVector4D &QVector4D::operator/=(QVector4D vector)
976{
977 Q_ASSERT(vector.v[0] > 0 || vector.v[0] < 0);
978 Q_ASSERT(vector.v[1] > 0 || vector.v[1] < 0);
979 Q_ASSERT(vector.v[2] > 0 || vector.v[2] < 0);
980 Q_ASSERT(vector.v[3] > 0 || vector.v[3] < 0);
981 v[0] /= vector.v[0];
982 v[1] /= vector.v[1];
983 v[2] /= vector.v[2];
984 v[3] /= vector.v[3];
985 return *this;
986}
987
988constexpr float QVector4D::dotProduct(QVector4D v1, QVector4D v2) noexcept
989{
990 return v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1] + v1.v[2] * v2.v[2] + v1.v[3] * v2.v[3];
991}
992
993#ifndef QT_NO_VECTOR2D
994
995constexpr inline QVector2D QVector4D::toVector2D() const noexcept
996{
997 return QVector2D(v[0], v[1]);
998}
999
1000constexpr inline QVector2D QVector4D::toVector2DAffine() const noexcept
1001{
1002 if (qIsNull(f: v[3]))
1003 return QVector2D();
1004 return QVector2D(v[0] / v[3], v[1] / v[3]);
1005}
1006
1007#endif // QT_NO_VECTOR2D
1008
1009#ifndef QT_NO_VECTOR3D
1010
1011constexpr inline QVector3D QVector4D::toVector3D() const noexcept
1012{
1013 return QVector3D(v[0], v[1], v[2]);
1014}
1015
1016constexpr QVector3D QVector4D::toVector3DAffine() const noexcept
1017{
1018 if (qIsNull(f: v[3]))
1019 return QVector3D();
1020 return QVector3D(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
1021}
1022
1023#endif // QT_NO_VECTOR3D
1024
1025constexpr inline QPoint QVector4D::toPoint() const noexcept
1026{
1027 return QPoint(qRound(f: v[0]), qRound(f: v[1]));
1028}
1029
1030constexpr inline QPointF QVector4D::toPointF() const noexcept
1031{
1032 return QPointF(qreal(v[0]), qreal(v[1]));
1033}
1034
1035#ifndef QT_NO_DEBUG_STREAM
1036Q_GUI_EXPORT QDebug operator<<(QDebug dbg, QVector4D vector);
1037#endif
1038
1039#ifndef QT_NO_DATASTREAM
1040Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, QVector4D );
1041Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector4D &);
1042#endif
1043
1044#endif // QT_NO_VECTOR4D
1045
1046
1047QT_END_NAMESPACE
1048
1049/***************************** Tuple protocol *****************************/
1050
1051namespace std {
1052#ifndef QT_NO_VECTOR2D
1053 template <>
1054 class tuple_size<QT_PREPEND_NAMESPACE(QVector2D)> : public integral_constant<size_t, 2> {};
1055 template <>
1056 class tuple_element<0, QT_PREPEND_NAMESPACE(QVector2D)> { public: using type = float; };
1057 template <>
1058 class tuple_element<1, QT_PREPEND_NAMESPACE(QVector2D)> { public: using type = float; };
1059#endif // QT_NO_VECTOR2D
1060
1061#ifndef QT_NO_VECTOR3D
1062 template <>
1063 class tuple_size<QT_PREPEND_NAMESPACE(QVector3D)> : public integral_constant<size_t, 3> {};
1064 template <>
1065 class tuple_element<0, QT_PREPEND_NAMESPACE(QVector3D)> { public: using type = float; };
1066 template <>
1067 class tuple_element<1, QT_PREPEND_NAMESPACE(QVector3D)> { public: using type = float; };
1068 template <>
1069 class tuple_element<2, QT_PREPEND_NAMESPACE(QVector3D)> { public: using type = float; };
1070#endif // QT_NO_VECTOR3D
1071
1072#ifndef QT_NO_VECTOR4D
1073 template <>
1074 class tuple_size<QT_PREPEND_NAMESPACE(QVector4D)> : public integral_constant<size_t, 4> {};
1075 template <>
1076 class tuple_element<0, QT_PREPEND_NAMESPACE(QVector4D)> { public: using type = float; };
1077 template <>
1078 class tuple_element<1, QT_PREPEND_NAMESPACE(QVector4D)> { public: using type = float; };
1079 template <>
1080 class tuple_element<2, QT_PREPEND_NAMESPACE(QVector4D)> { public: using type = float; };
1081 template <>
1082 class tuple_element<3, QT_PREPEND_NAMESPACE(QVector4D)> { public: using type = float; };
1083#endif // QT_NO_VECTOR4D
1084}
1085
1086#endif // QVECTORND_H
1087

source code of qtbase/src/gui/math3d/qvectornd.h