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 
48 QT_BEGIN_NAMESPACE
49 
50 #ifndef QT_NO_VECTOR4D
51 
52 Q_STATIC_ASSERT_X(std::is_standard_layout<QVector4D>::value, "QVector4D is supposed to be standard layout");
53 Q_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 
60 namespace {
61 
62 struct QVector4DOld
63 {
64     float x, y, z, w;
65 };
66 
67 struct QVector4DNew
68 {
69     float v[4];
70 };
71 
72 Q_STATIC_ASSERT_X(std::is_standard_layout<QVector4DOld>::value, "Binary compatibility break in QVector4D");
73 Q_STATIC_ASSERT_X(std::is_standard_layout<QVector4DNew>::value, "Binary compatibility break in QVector4D");
74 
75 Q_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)
79 Q_STATIC_ASSERT_X(offsetof(QVector4DOld, x) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 0, "Binary compatibility break in QVector4D");
80 Q_STATIC_ASSERT_X(offsetof(QVector4DOld, y) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 1, "Binary compatibility break in QVector4D");
81 Q_STATIC_ASSERT_X(offsetof(QVector4DOld, z) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 2, "Binary compatibility break in QVector4D");
82 Q_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 */
QVector4D(const QVector2D & vector)143 QVector4D::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 */
QVector4D(const QVector2D & vector,float zpos,float wpos)157 QVector4D::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 */
QVector4D(const QVector3D & vector)175 QVector4D::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 */
QVector4D(const QVector3D & vector,float wpos)189 QVector4D::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 */
length() const294 float 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 */
lengthSquared() const310 float 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 */
normalized() const324 QVector4D 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 */
normalize()350 void 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 */
dotProduct(const QVector4D & v1,const QVector4D & v2)424 float 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 */
toVector2D() const540 QVector2D 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 */
toVector2DAffine() const552 QVector2D 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 */
toVector3D() const568 QVector3D 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 */
toVector3DAffine() const579 QVector3D 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 */
operator QVariant() const609 QVector4D::operator QVariant() const
610 {
611     return QVariant(QMetaType::QVector4D, this);
612 }
613 
614 #ifndef QT_NO_DEBUG_STREAM
615 
operator <<(QDebug dbg,const QVector4D & vector)616 QDebug 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 
operator <<(QDataStream & stream,const QVector4D & vector)639 QDataStream &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 
operator >>(QDataStream & stream,QVector4D & vector)656 QDataStream &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 
674 QT_END_NAMESPACE
675