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