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 QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qvector4d.h"
41#include "qvector3d.h"
42#include "qvector2d.h"
43#include <QtCore/qdatastream.h>
44#include <QtCore/qdebug.h>
45#include <QtCore/qvariant.h>
46#include <QtCore/qmath.h>
47
48QT_BEGIN_NAMESPACE
49
50#ifndef QT_NO_VECTOR4D
51
52Q_STATIC_ASSERT_X(std::is_standard_layout<QVector4D>::value, "QVector4D is supposed to be standard layout");
53Q_STATIC_ASSERT_X(sizeof(QVector4D) == sizeof(float) * 4, "QVector4D is not supposed to have padding at the end");
54
55// QVector4D used to be defined as class QVector4D { float x, y, z, w; };,
56// now instead it is defined as classs QVector4D { float v[4]; };.
57// Check that binary compatibility is preserved.
58// ### Qt 6: remove all of these checks.
59
60namespace {
61
62struct QVector4DOld
63{
64 float x, y, z, w;
65};
66
67struct QVector4DNew
68{
69 float v[4];
70};
71
72Q_STATIC_ASSERT_X(std::is_standard_layout<QVector4DOld>::value, "Binary compatibility break in QVector4D");
73Q_STATIC_ASSERT_X(std::is_standard_layout<QVector4DNew>::value, "Binary compatibility break in QVector4D");
74
75Q_STATIC_ASSERT_X(sizeof(QVector4DOld) == sizeof(QVector4DNew), "Binary compatibility break in QVector4D");
76
77// requires a constexpr offsetof
78#if !defined(Q_CC_MSVC) || (_MSC_VER >= 1910)
79Q_STATIC_ASSERT_X(offsetof(QVector4DOld, x) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 0, "Binary compatibility break in QVector4D");
80Q_STATIC_ASSERT_X(offsetof(QVector4DOld, y) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 1, "Binary compatibility break in QVector4D");
81Q_STATIC_ASSERT_X(offsetof(QVector4DOld, z) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 2, "Binary compatibility break in QVector4D");
82Q_STATIC_ASSERT_X(offsetof(QVector4DOld, w) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 3, "Binary compatibility break in QVector4D");
83#endif
84
85
86} // anonymous namespace
87
88/*!
89 \class QVector4D
90 \brief The QVector4D class represents a vector or vertex in 4D space.
91 \since 4.6
92 \ingroup painting-3D
93 \inmodule QtGui
94
95 The QVector4D class can also be used to represent vertices in 4D space.
96 We therefore do not need to provide a separate vertex class.
97
98 \sa QQuaternion, QVector2D, QVector3D
99*/
100
101/*!
102 \fn QVector4D::QVector4D()
103
104 Constructs a null vector, i.e. with coordinates (0, 0, 0, 0).
105*/
106
107/*!
108 \fn QVector4D::QVector4D(Qt::Initialization)
109 \since 5.5
110 \internal
111
112 Constructs a vector without initializing the contents.
113*/
114
115/*!
116 \fn QVector4D::QVector4D(float xpos, float ypos, float zpos, float wpos)
117
118 Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos, \a wpos).
119*/
120
121/*!
122 \fn QVector4D::QVector4D(const QPoint& point)
123
124 Constructs a vector with x and y coordinates from a 2D \a point, and
125 z and w coordinates of 0.
126*/
127
128/*!
129 \fn QVector4D::QVector4D(const QPointF& point)
130
131 Constructs a vector with x and y coordinates from a 2D \a point, and
132 z and w coordinates of 0.
133*/
134
135#ifndef QT_NO_VECTOR2D
136
137/*!
138 Constructs a 4D vector from the specified 2D \a vector. The z
139 and w coordinates are set to zero.
140
141 \sa toVector2D()
142*/
143QVector4D::QVector4D(const QVector2D& vector)
144{
145 v[0] = vector.v[0];
146 v[1] = vector.v[1];
147 v[2] = 0.0f;
148 v[3] = 0.0f;
149}
150
151/*!
152 Constructs a 4D vector from the specified 2D \a vector. The z
153 and w coordinates are set to \a zpos and \a wpos respectively.
154
155 \sa toVector2D()
156*/
157QVector4D::QVector4D(const QVector2D& vector, float zpos, float wpos)
158{
159 v[0] = vector.v[0];
160 v[1] = vector.v[1];
161 v[2] = zpos;
162 v[3] = wpos;
163}
164
165#endif
166
167#ifndef QT_NO_VECTOR3D
168
169/*!
170 Constructs a 4D vector from the specified 3D \a vector. The w
171 coordinate is set to zero.
172
173 \sa toVector3D()
174*/
175QVector4D::QVector4D(const QVector3D& vector)
176{
177 v[0] = vector.v[0];
178 v[1] = vector.v[1];
179 v[2] = vector.v[2];
180 v[3] = 0.0f;
181}
182
183/*!
184 Constructs a 4D vector from the specified 3D \a vector. The w
185 coordinate is set to \a wpos.
186
187 \sa toVector3D()
188*/
189QVector4D::QVector4D(const QVector3D& vector, float wpos)
190{
191 v[0] = vector.v[0];
192 v[1] = vector.v[1];
193 v[2] = vector.v[2];
194 v[3] = wpos;
195}
196
197#endif
198
199/*!
200 \fn bool QVector4D::isNull() const
201
202 Returns \c true if the x, y, z, and w coordinates are set to 0.0,
203 otherwise returns \c false.
204*/
205
206/*!
207 \fn float QVector4D::x() const
208
209 Returns the x coordinate of this point.
210
211 \sa setX(), y(), z(), w()
212*/
213
214/*!
215 \fn float QVector4D::y() const
216
217 Returns the y coordinate of this point.
218
219 \sa setY(), x(), z(), w()
220*/
221
222/*!
223 \fn float QVector4D::z() const
224
225 Returns the z coordinate of this point.
226
227 \sa setZ(), x(), y(), w()
228*/
229
230/*!
231 \fn float QVector4D::w() const
232
233 Returns the w coordinate of this point.
234
235 \sa setW(), x(), y(), z()
236*/
237
238/*!
239 \fn void QVector4D::setX(float x)
240
241 Sets the x coordinate of this point to the given \a x coordinate.
242
243 \sa x(), setY(), setZ(), setW()
244*/
245
246/*!
247 \fn void QVector4D::setY(float y)
248
249 Sets the y coordinate of this point to the given \a y coordinate.
250
251 \sa y(), setX(), setZ(), setW()
252*/
253
254/*!
255 \fn void QVector4D::setZ(float z)
256
257 Sets the z coordinate of this point to the given \a z coordinate.
258
259 \sa z(), setX(), setY(), setW()
260*/
261
262/*!
263 \fn void QVector4D::setW(float w)
264
265 Sets the w coordinate of this point to the given \a w coordinate.
266
267 \sa w(), setX(), setY(), setZ()
268*/
269
270/*! \fn float &QVector4D::operator[](int i)
271 \since 5.2
272
273 Returns the component of the vector at index position \a i
274 as a modifiable reference.
275
276 \a i must be a valid index position in the vector (i.e., 0 <= \a i
277 < 4).
278*/
279
280/*! \fn float QVector4D::operator[](int i) const
281 \since 5.2
282
283 Returns the component of the vector at index position \a i.
284
285 \a i must be a valid index position in the vector (i.e., 0 <= \a i
286 < 4).
287*/
288
289/*!
290 Returns the length of the vector from the origin.
291
292 \sa lengthSquared(), normalized()
293*/
294float QVector4D::length() const
295{
296 // Need some extra precision if the length is very small.
297 double len = double(v[0]) * double(v[0]) +
298 double(v[1]) * double(v[1]) +
299 double(v[2]) * double(v[2]) +
300 double(v[3]) * double(v[3]);
301 return float(std::sqrt(len));
302}
303
304/*!
305 Returns the squared length of the vector from the origin.
306 This is equivalent to the dot product of the vector with itself.
307
308 \sa length(), dotProduct()
309*/
310float QVector4D::lengthSquared() const
311{
312 return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
313}
314
315/*!
316 Returns the normalized unit vector form of this vector.
317
318 If this vector is null, then a null vector is returned. If the length
319 of the vector is very close to 1, then the vector will be returned as-is.
320 Otherwise the normalized form of the vector of length 1 will be returned.
321
322 \sa length(), normalize()
323*/
324QVector4D QVector4D::normalized() const
325{
326 // Need some extra precision if the length is very small.
327 double len = double(v[0]) * double(v[0]) +
328 double(v[1]) * double(v[1]) +
329 double(v[2]) * double(v[2]) +
330 double(v[3]) * double(v[3]);
331 if (qFuzzyIsNull(len - 1.0f)) {
332 return *this;
333 } else if (!qFuzzyIsNull(len)) {
334 double sqrtLen = std::sqrt(len);
335 return QVector4D(float(double(v[0]) / sqrtLen),
336 float(double(v[1]) / sqrtLen),
337 float(double(v[2]) / sqrtLen),
338 float(double(v[3]) / sqrtLen));
339 } else {
340 return QVector4D();
341 }
342}
343
344/*!
345 Normalizes the currect vector in place. Nothing happens if this
346 vector is a null vector or the length of the vector is very close to 1.
347
348 \sa length(), normalized()
349*/
350void QVector4D::normalize()
351{
352 // Need some extra precision if the length is very small.
353 double len = double(v[0]) * double(v[0]) +
354 double(v[1]) * double(v[1]) +
355 double(v[2]) * double(v[2]) +
356 double(v[3]) * double(v[3]);
357 if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
358 return;
359
360 len = std::sqrt(len);
361
362 v[0] = float(double(v[0]) / len);
363 v[1] = float(double(v[1]) / len);
364 v[2] = float(double(v[2]) / len);
365 v[3] = float(double(v[3]) / len);
366}
367
368/*!
369 \fn QVector4D &QVector4D::operator+=(const QVector4D &vector)
370
371 Adds the given \a vector to this vector and returns a reference to
372 this vector.
373
374 \sa operator-=()
375*/
376
377/*!
378 \fn QVector4D &QVector4D::operator-=(const QVector4D &vector)
379
380 Subtracts the given \a vector from this vector and returns a reference to
381 this vector.
382
383 \sa operator+=()
384*/
385
386/*!
387 \fn QVector4D &QVector4D::operator*=(float factor)
388
389 Multiplies this vector's coordinates by the given \a factor, and
390 returns a reference to this vector.
391
392 \sa operator/=()
393*/
394
395/*!
396 \fn QVector4D &QVector4D::operator*=(const QVector4D &vector)
397
398 Multiplies the components of this vector by the corresponding
399 components in \a vector.
400*/
401
402/*!
403 \fn QVector4D &QVector4D::operator/=(float divisor)
404
405 Divides this vector's coordinates by the given \a divisor, and
406 returns a reference to this vector.
407
408 \sa operator*=()
409*/
410
411/*!
412 \fn QVector4D &QVector4D::operator/=(const QVector4D &vector)
413 \since 5.5
414
415 Divides the components of this vector by the corresponding
416 components in \a vector.
417
418 \sa operator*=()
419*/
420
421/*!
422 Returns the dot product of \a v1 and \a v2.
423*/
424float QVector4D::dotProduct(const QVector4D& v1, const QVector4D& v2)
425{
426 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];
427}
428
429/*!
430 \fn bool operator==(const QVector4D &v1, const QVector4D &v2)
431 \relates QVector4D
432
433 Returns \c true if \a v1 is equal to \a v2; otherwise returns \c false.
434 This operator uses an exact floating-point comparison.
435*/
436
437/*!
438 \fn bool operator!=(const QVector4D &v1, const QVector4D &v2)
439 \relates QVector4D
440
441 Returns \c true if \a v1 is not equal to \a v2; otherwise returns \c false.
442 This operator uses an exact floating-point comparison.
443*/
444
445/*!
446 \fn const QVector4D operator+(const QVector4D &v1, const QVector4D &v2)
447 \relates QVector4D
448
449 Returns a QVector4D object that is the sum of the given vectors, \a v1
450 and \a v2; each component is added separately.
451
452 \sa QVector4D::operator+=()
453*/
454
455/*!
456 \fn const QVector4D operator-(const QVector4D &v1, const QVector4D &v2)
457 \relates QVector4D
458
459 Returns a QVector4D object that is formed by subtracting \a v2 from \a v1;
460 each component is subtracted separately.
461
462 \sa QVector4D::operator-=()
463*/
464
465/*!
466 \fn const QVector4D operator*(float factor, const QVector4D &vector)
467 \relates QVector4D
468
469 Returns a copy of the given \a vector, multiplied by the given \a factor.
470
471 \sa QVector4D::operator*=()
472*/
473
474/*!
475 \fn const QVector4D operator*(const QVector4D &vector, float factor)
476 \relates QVector4D
477
478 Returns a copy of the given \a vector, multiplied by the given \a factor.
479
480 \sa QVector4D::operator*=()
481*/
482
483/*!
484 \fn const QVector4D operator*(const QVector4D &v1, const QVector4D& v2)
485 \relates QVector4D
486
487 Returns the vector consisting of the multiplication of the
488 components from \a v1 and \a v2.
489
490 \sa QVector4D::operator*=()
491*/
492
493/*!
494 \fn const QVector4D operator-(const QVector4D &vector)
495 \relates QVector4D
496 \overload
497
498 Returns a QVector4D object that is formed by changing the sign of
499 all three components of the given \a vector.
500
501 Equivalent to \c {QVector4D(0,0,0,0) - vector}.
502*/
503
504/*!
505 \fn const QVector4D operator/(const QVector4D &vector, float divisor)
506 \relates QVector4D
507
508 Returns the QVector4D object formed by dividing all four components of
509 the given \a vector by the given \a divisor.
510
511 \sa QVector4D::operator/=()
512*/
513
514/*!
515 \fn const QVector4D operator/(const QVector4D &vector, const QVector4D &divisor)
516 \relates QVector4D
517 \since 5.5
518
519 Returns the QVector4D object formed by dividing components of the given
520 \a vector by a respective components of the given \a divisor.
521
522 \sa QVector4D::operator/=()
523*/
524
525/*!
526 \fn bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2)
527 \relates QVector4D
528
529 Returns \c true if \a v1 and \a v2 are equal, allowing for a small
530 fuzziness factor for floating-point comparisons; false otherwise.
531*/
532
533#ifndef QT_NO_VECTOR2D
534
535/*!
536 Returns the 2D vector form of this 4D vector, dropping the z and w coordinates.
537
538 \sa toVector2DAffine(), toVector3D(), toPoint()
539*/
540QVector2D QVector4D::toVector2D() const
541{
542 return QVector2D(v[0], v[1]);
543}
544
545/*!
546 Returns the 2D vector form of this 4D vector, dividing the x and y
547 coordinates by the w coordinate and dropping the z coordinate.
548 Returns a null vector if w is zero.
549
550 \sa toVector2D(), toVector3DAffine(), toPoint()
551*/
552QVector2D QVector4D::toVector2DAffine() const
553{
554 if (qIsNull(v[3]))
555 return QVector2D();
556 return QVector2D(v[0] / v[3], v[1] / v[3]);
557}
558
559#endif
560
561#ifndef QT_NO_VECTOR3D
562
563/*!
564 Returns the 3D vector form of this 4D vector, dropping the w coordinate.
565
566 \sa toVector3DAffine(), toVector2D(), toPoint()
567*/
568QVector3D QVector4D::toVector3D() const
569{
570 return QVector3D(v[0], v[1], v[2]);
571}
572
573/*!
574 Returns the 3D vector form of this 4D vector, dividing the x, y, and
575 z coordinates by the w coordinate. Returns a null vector if w is zero.
576
577 \sa toVector3D(), toVector2DAffine(), toPoint()
578*/
579QVector3D QVector4D::toVector3DAffine() const
580{
581 if (qIsNull(v[3]))
582 return QVector3D();
583 return QVector3D(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
584}
585
586#endif
587
588/*!
589 \fn QPoint QVector4D::toPoint() const
590
591 Returns the QPoint form of this 4D vector. The z and w coordinates
592 are dropped.
593
594 \sa toPointF(), toVector2D()
595*/
596
597/*!
598 \fn QPointF QVector4D::toPointF() const
599
600 Returns the QPointF form of this 4D vector. The z and w coordinates
601 are dropped.
602
603 \sa toPoint(), toVector2D()
604*/
605
606/*!
607 Returns the 4D vector as a QVariant.
608*/
609QVector4D::operator QVariant() const
610{
611 return QVariant(QVariant::Vector4D, this);
612}
613
614#ifndef QT_NO_DEBUG_STREAM
615
616QDebug operator<<(QDebug dbg, const QVector4D &vector)
617{
618 QDebugStateSaver saver(dbg);
619 dbg.nospace() << "QVector4D("
620 << vector.x() << ", " << vector.y() << ", "
621 << vector.z() << ", " << vector.w() << ')';
622 return dbg;
623}
624
625#endif
626
627#ifndef QT_NO_DATASTREAM
628
629/*!
630 \fn QDataStream &operator<<(QDataStream &stream, const QVector4D &vector)
631 \relates QVector4D
632
633 Writes the given \a vector to the given \a stream and returns a
634 reference to the stream.
635
636 \sa {Serializing Qt Data Types}
637*/
638
639QDataStream &operator<<(QDataStream &stream, const QVector4D &vector)
640{
641 stream << vector.x() << vector.y()
642 << vector.z() << vector.w();
643 return stream;
644}
645
646/*!
647 \fn QDataStream &operator>>(QDataStream &stream, QVector4D &vector)
648 \relates QVector4D
649
650 Reads a 4D vector from the given \a stream into the given \a vector
651 and returns a reference to the stream.
652
653 \sa {Serializing Qt Data Types}
654*/
655
656QDataStream &operator>>(QDataStream &stream, QVector4D &vector)
657{
658 float x, y, z, w;
659 stream >> x;
660 stream >> y;
661 stream >> z;
662 stream >> w;
663 vector.setX(x);
664 vector.setY(y);
665 vector.setZ(z);
666 vector.setW(w);
667 return stream;
668}
669
670#endif // QT_NO_DATASTREAM
671
672#endif // QT_NO_VECTOR4D
673
674QT_END_NAMESPACE
675