Coverage Report

Created: 2025-09-27 07:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/math3d/qvector4d.cpp
Line
Count
Source
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
*/
143
QVector4D::QVector4D(const QVector2D& vector)
144
0
{
145
0
    v[0] = vector.v[0];
146
0
    v[1] = vector.v[1];
147
0
    v[2] = 0.0f;
148
0
    v[3] = 0.0f;
149
0
}
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
*/
157
QVector4D::QVector4D(const QVector2D& vector, float zpos, float wpos)
158
0
{
159
0
    v[0] = vector.v[0];
160
0
    v[1] = vector.v[1];
161
0
    v[2] = zpos;
162
0
    v[3] = wpos;
163
0
}
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
*/
175
QVector4D::QVector4D(const QVector3D& vector)
176
0
{
177
0
    v[0] = vector.v[0];
178
0
    v[1] = vector.v[1];
179
0
    v[2] = vector.v[2];
180
0
    v[3] = 0.0f;
181
0
}
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
*/
189
QVector4D::QVector4D(const QVector3D& vector, float wpos)
190
0
{
191
0
    v[0] = vector.v[0];
192
0
    v[1] = vector.v[1];
193
0
    v[2] = vector.v[2];
194
0
    v[3] = wpos;
195
0
}
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
*/
294
float QVector4D::length() const
295
0
{
296
    // Need some extra precision if the length is very small.
297
0
    double len = double(v[0]) * double(v[0]) +
298
0
                 double(v[1]) * double(v[1]) +
299
0
                 double(v[2]) * double(v[2]) +
300
0
                 double(v[3]) * double(v[3]);
301
0
    return float(std::sqrt(len));
302
0
}
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
*/
310
float QVector4D::lengthSquared() const
311
0
{
312
0
    return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
313
0
}
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
*/
324
QVector4D QVector4D::normalized() const
325
0
{
326
    // Need some extra precision if the length is very small.
327
0
    double len = double(v[0]) * double(v[0]) +
328
0
                 double(v[1]) * double(v[1]) +
329
0
                 double(v[2]) * double(v[2]) +
330
0
                 double(v[3]) * double(v[3]);
331
0
    if (qFuzzyIsNull(len - 1.0f)) {
332
0
        return *this;
333
0
    } else if (!qFuzzyIsNull(len)) {
334
0
        double sqrtLen = std::sqrt(len);
335
0
        return QVector4D(float(double(v[0]) / sqrtLen),
336
0
                         float(double(v[1]) / sqrtLen),
337
0
                         float(double(v[2]) / sqrtLen),
338
0
                         float(double(v[3]) / sqrtLen));
339
0
    } else {
340
0
        return QVector4D();
341
0
    }
342
0
}
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
*/
350
void QVector4D::normalize()
351
0
{
352
    // Need some extra precision if the length is very small.
353
0
    double len = double(v[0]) * double(v[0]) +
354
0
                 double(v[1]) * double(v[1]) +
355
0
                 double(v[2]) * double(v[2]) +
356
0
                 double(v[3]) * double(v[3]);
357
0
    if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
358
0
        return;
359
360
0
    len = std::sqrt(len);
361
362
0
    v[0] = float(double(v[0]) / len);
363
0
    v[1] = float(double(v[1]) / len);
364
0
    v[2] = float(double(v[2]) / len);
365
0
    v[3] = float(double(v[3]) / len);
366
0
}
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
*/
424
float QVector4D::dotProduct(const QVector4D& v1, const QVector4D& v2)
425
0
{
426
0
    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
0
}
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
*/
540
QVector2D QVector4D::toVector2D() const
541
0
{
542
0
    return QVector2D(v[0], v[1]);
543
0
}
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
*/
552
QVector2D QVector4D::toVector2DAffine() const
553
0
{
554
0
    if (qIsNull(v[3]))
555
0
        return QVector2D();
556
0
    return QVector2D(v[0] / v[3], v[1] / v[3]);
557
0
}
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
*/
568
QVector3D QVector4D::toVector3D() const
569
0
{
570
0
    return QVector3D(v[0], v[1], v[2]);
571
0
}
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
*/
579
QVector3D QVector4D::toVector3DAffine() const
580
0
{
581
0
    if (qIsNull(v[3]))
582
0
        return QVector3D();
583
0
    return QVector3D(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
584
0
}
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
*/
609
QVector4D::operator QVariant() const
610
0
{
611
0
    return QVariant(QMetaType::QVector4D, this);
612
0
}
613
614
#ifndef QT_NO_DEBUG_STREAM
615
616
QDebug operator<<(QDebug dbg, const QVector4D &vector)
617
0
{
618
0
    QDebugStateSaver saver(dbg);
619
0
    dbg.nospace() << "QVector4D("
620
0
        << vector.x() << ", " << vector.y() << ", "
621
0
        << vector.z() << ", " << vector.w() << ')';
622
0
    return dbg;
623
0
}
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
639
QDataStream &operator<<(QDataStream &stream, const QVector4D &vector)
640
0
{
641
0
    stream << vector.x() << vector.y()
642
0
           << vector.z() << vector.w();
643
0
    return stream;
644
0
}
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
656
QDataStream &operator>>(QDataStream &stream, QVector4D &vector)
657
0
{
658
0
    float x, y, z, w;
659
0
    stream >> x;
660
0
    stream >> y;
661
0
    stream >> z;
662
0
    stream >> w;
663
0
    vector.setX(x);
664
0
    vector.setY(y);
665
0
    vector.setZ(z);
666
0
    vector.setW(w);
667
0
    return stream;
668
0
}
669
670
#endif // QT_NO_DATASTREAM
671
672
#endif // QT_NO_VECTOR4D
673
674
QT_END_NAMESPACE