1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://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 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qvector4d.h"
43 #include "qvector3d.h"
44 #include "qvector2d.h"
45 #include <QtCore/qdebug.h>
46 #include <QtCore/qvariant.h>
47 #include <QtCore/qmath.h>
48
49 QT_BEGIN_NAMESPACE
50
51 #ifndef QT_NO_VECTOR4D
52
53 /*!
54 \class QVector4D
55 \brief The QVector4D class represents a vector or vertex in 4D space.
56 \since 4.6
57 \ingroup painting-3D
58
59 The QVector4D class can also be used to represent vertices in 4D space.
60 We therefore do not need to provide a separate vertex class.
61
62 \bold{Note:} By design values in the QVector4D instance are stored as \c float.
63 This means that on platforms where the \c qreal arguments to QVector4D
64 functions are represented by \c double values, it is possible to
65 lose precision.
66
67 \sa QQuaternion, QVector2D, QVector3D
68 */
69
70 /*!
71 \fn QVector4D::QVector4D()
72
73 Constructs a null vector, i.e. with coordinates (0, 0, 0, 0).
74 */
75
76 /*!
77 \fn QVector4D::QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos)
78
79 Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos, \a wpos).
80 */
81
82 /*!
83 \fn QVector4D::QVector4D(const QPoint& point)
84
85 Constructs a vector with x and y coordinates from a 2D \a point, and
86 z and w coordinates of 0.
87 */
88
89 /*!
90 \fn QVector4D::QVector4D(const QPointF& point)
91
92 Constructs a vector with x and y coordinates from a 2D \a point, and
93 z and w coordinates of 0.
94 */
95
96 #ifndef QT_NO_VECTOR2D
97
98 /*!
99 Constructs a 4D vector from the specified 2D \a vector. The z
100 and w coordinates are set to zero.
101
102 \sa toVector2D()
103 */
QVector4D(const QVector2D & vector)104 QVector4D::QVector4D(const QVector2D& vector)
105 {
106 xp = vector.xp;
107 yp = vector.yp;
108 zp = 0.0f;
109 wp = 0.0f;
110 }
111
112 /*!
113 Constructs a 4D vector from the specified 2D \a vector. The z
114 and w coordinates are set to \a zpos and \a wpos respectively.
115
116 \sa toVector2D()
117 */
QVector4D(const QVector2D & vector,qreal zpos,qreal wpos)118 QVector4D::QVector4D(const QVector2D& vector, qreal zpos, qreal wpos)
119 {
120 xp = vector.xp;
121 yp = vector.yp;
122 zp = zpos;
123 wp = wpos;
124 }
125
126 #endif
127
128 #ifndef QT_NO_VECTOR3D
129
130 /*!
131 Constructs a 4D vector from the specified 3D \a vector. The w
132 coordinate is set to zero.
133
134 \sa toVector3D()
135 */
QVector4D(const QVector3D & vector)136 QVector4D::QVector4D(const QVector3D& vector)
137 {
138 xp = vector.xp;
139 yp = vector.yp;
140 zp = vector.zp;
141 wp = 0.0f;
142 }
143
144 /*!
145 Constructs a 4D vector from the specified 3D \a vector. The w
146 coordinate is set to \a wpos.
147
148 \sa toVector3D()
149 */
QVector4D(const QVector3D & vector,qreal wpos)150 QVector4D::QVector4D(const QVector3D& vector, qreal wpos)
151 {
152 xp = vector.xp;
153 yp = vector.yp;
154 zp = vector.zp;
155 wp = wpos;
156 }
157
158 #endif
159
160 /*!
161 \fn bool QVector4D::isNull() const
162
163 Returns true if the x, y, z, and w coordinates are set to 0.0,
164 otherwise returns false.
165 */
166
167 /*!
168 \fn qreal QVector4D::x() const
169
170 Returns the x coordinate of this point.
171
172 \sa setX(), y(), z(), w()
173 */
174
175 /*!
176 \fn qreal QVector4D::y() const
177
178 Returns the y coordinate of this point.
179
180 \sa setY(), x(), z(), w()
181 */
182
183 /*!
184 \fn qreal QVector4D::z() const
185
186 Returns the z coordinate of this point.
187
188 \sa setZ(), x(), y(), w()
189 */
190
191 /*!
192 \fn qreal QVector4D::w() const
193
194 Returns the w coordinate of this point.
195
196 \sa setW(), x(), y(), z()
197 */
198
199 /*!
200 \fn void QVector4D::setX(qreal x)
201
202 Sets the x coordinate of this point to the given \a x coordinate.
203
204 \sa x(), setY(), setZ(), setW()
205 */
206
207 /*!
208 \fn void QVector4D::setY(qreal y)
209
210 Sets the y coordinate of this point to the given \a y coordinate.
211
212 \sa y(), setX(), setZ(), setW()
213 */
214
215 /*!
216 \fn void QVector4D::setZ(qreal z)
217
218 Sets the z coordinate of this point to the given \a z coordinate.
219
220 \sa z(), setX(), setY(), setW()
221 */
222
223 /*!
224 \fn void QVector4D::setW(qreal w)
225
226 Sets the w coordinate of this point to the given \a w coordinate.
227
228 \sa w(), setX(), setY(), setZ()
229 */
230
231 /*!
232 Returns the length of the vector from the origin.
233
234 \sa lengthSquared(), normalized()
235 */
length() const236 qreal QVector4D::length() const
237 {
238 return qSqrt(xp * xp + yp * yp + zp * zp + wp * wp);
239 }
240
241 /*!
242 Returns the squared length of the vector from the origin.
243 This is equivalent to the dot product of the vector with itself.
244
245 \sa length(), dotProduct()
246 */
lengthSquared() const247 qreal QVector4D::lengthSquared() const
248 {
249 return xp * xp + yp * yp + zp * zp + wp * wp;
250 }
251
252 /*!
253 Returns the normalized unit vector form of this vector.
254
255 If this vector is null, then a null vector is returned. If the length
256 of the vector is very close to 1, then the vector will be returned as-is.
257 Otherwise the normalized form of the vector of length 1 will be returned.
258
259 \sa length(), normalize()
260 */
normalized() const261 QVector4D QVector4D::normalized() const
262 {
263 // Need some extra precision if the length is very small.
264 double len = double(xp) * double(xp) +
265 double(yp) * double(yp) +
266 double(zp) * double(zp) +
267 double(wp) * double(wp);
268 if (qFuzzyIsNull(len - 1.0f))
269 return *this;
270 else if (!qFuzzyIsNull(len))
271 return *this / qSqrt(len);
272 else
273 return QVector4D();
274 }
275
276 /*!
277 Normalizes the currect vector in place. Nothing happens if this
278 vector is a null vector or the length of the vector is very close to 1.
279
280 \sa length(), normalized()
281 */
normalize()282 void QVector4D::normalize()
283 {
284 // Need some extra precision if the length is very small.
285 double len = double(xp) * double(xp) +
286 double(yp) * double(yp) +
287 double(zp) * double(zp) +
288 double(wp) * double(wp);
289 if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
290 return;
291
292 len = qSqrt(len);
293
294 xp /= len;
295 yp /= len;
296 zp /= len;
297 wp /= len;
298 }
299
300 /*!
301 \fn QVector4D &QVector4D::operator+=(const QVector4D &vector)
302
303 Adds the given \a vector to this vector and returns a reference to
304 this vector.
305
306 \sa operator-=()
307 */
308
309 /*!
310 \fn QVector4D &QVector4D::operator-=(const QVector4D &vector)
311
312 Subtracts the given \a vector from this vector and returns a reference to
313 this vector.
314
315 \sa operator+=()
316 */
317
318 /*!
319 \fn QVector4D &QVector4D::operator*=(qreal factor)
320
321 Multiplies this vector's coordinates by the given \a factor, and
322 returns a reference to this vector.
323
324 \sa operator/=()
325 */
326
327 /*!
328 \fn QVector4D &QVector4D::operator*=(const QVector4D &vector)
329
330 Multiplies the components of this vector by the corresponding
331 components in \a vector.
332 */
333
334 /*!
335 \fn QVector4D &QVector4D::operator/=(qreal divisor)
336
337 Divides this vector's coordinates by the given \a divisor, and
338 returns a reference to this vector.
339
340 \sa operator*=()
341 */
342
343 /*!
344 Returns the dot product of \a v1 and \a v2.
345 */
dotProduct(const QVector4D & v1,const QVector4D & v2)346 qreal QVector4D::dotProduct(const QVector4D& v1, const QVector4D& v2)
347 {
348 return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp + v1.wp * v2.wp;
349 }
350
351 /*!
352 \fn bool operator==(const QVector4D &v1, const QVector4D &v2)
353 \relates QVector4D
354
355 Returns true if \a v1 is equal to \a v2; otherwise returns false.
356 This operator uses an exact floating-point comparison.
357 */
358
359 /*!
360 \fn bool operator!=(const QVector4D &v1, const QVector4D &v2)
361 \relates QVector4D
362
363 Returns true if \a v1 is not equal to \a v2; otherwise returns false.
364 This operator uses an exact floating-point comparison.
365 */
366
367 /*!
368 \fn const QVector4D operator+(const QVector4D &v1, const QVector4D &v2)
369 \relates QVector4D
370
371 Returns a QVector4D object that is the sum of the given vectors, \a v1
372 and \a v2; each component is added separately.
373
374 \sa QVector4D::operator+=()
375 */
376
377 /*!
378 \fn const QVector4D operator-(const QVector4D &v1, const QVector4D &v2)
379 \relates QVector4D
380
381 Returns a QVector4D object that is formed by subtracting \a v2 from \a v1;
382 each component is subtracted separately.
383
384 \sa QVector4D::operator-=()
385 */
386
387 /*!
388 \fn const QVector4D operator*(qreal factor, const QVector4D &vector)
389 \relates QVector4D
390
391 Returns a copy of the given \a vector, multiplied by the given \a factor.
392
393 \sa QVector4D::operator*=()
394 */
395
396 /*!
397 \fn const QVector4D operator*(const QVector4D &vector, qreal factor)
398 \relates QVector4D
399
400 Returns a copy of the given \a vector, multiplied by the given \a factor.
401
402 \sa QVector4D::operator*=()
403 */
404
405 /*!
406 \fn const QVector4D operator*(const QVector4D &v1, const QVector4D& v2)
407 \relates QVector4D
408
409 Returns the vector consisting of the multiplication of the
410 components from \a v1 and \a v2.
411
412 \sa QVector4D::operator*=()
413 */
414
415 /*!
416 \fn const QVector4D operator-(const QVector4D &vector)
417 \relates QVector4D
418 \overload
419
420 Returns a QVector4D object that is formed by changing the sign of
421 all three components of the given \a vector.
422
423 Equivalent to \c {QVector4D(0,0,0,0) - vector}.
424 */
425
426 /*!
427 \fn const QVector4D operator/(const QVector4D &vector, qreal divisor)
428 \relates QVector4D
429
430 Returns the QVector4D object formed by dividing all four components of
431 the given \a vector by the given \a divisor.
432
433 \sa QVector4D::operator/=()
434 */
435
436 /*!
437 \fn bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2)
438 \relates QVector4D
439
440 Returns true if \a v1 and \a v2 are equal, allowing for a small
441 fuzziness factor for floating-point comparisons; false otherwise.
442 */
443
444 #ifndef QT_NO_VECTOR2D
445
446 /*!
447 Returns the 2D vector form of this 4D vector, dropping the z and w coordinates.
448
449 \sa toVector2DAffine(), toVector3D(), toPoint()
450 */
toVector2D() const451 QVector2D QVector4D::toVector2D() const
452 {
453 return QVector2D(xp, yp, 1);
454 }
455
456 /*!
457 Returns the 2D vector form of this 4D vector, dividing the x and y
458 coordinates by the w coordinate and dropping the z coordinate.
459 Returns a null vector if w is zero.
460
461 \sa toVector2D(), toVector3DAffine(), toPoint()
462 */
toVector2DAffine() const463 QVector2D QVector4D::toVector2DAffine() const
464 {
465 if (qIsNull(wp))
466 return QVector2D();
467 return QVector2D(xp / wp, yp / wp, 1);
468 }
469
470 #endif
471
472 #ifndef QT_NO_VECTOR3D
473
474 /*!
475 Returns the 3D vector form of this 4D vector, dropping the w coordinate.
476
477 \sa toVector3DAffine(), toVector2D(), toPoint()
478 */
toVector3D() const479 QVector3D QVector4D::toVector3D() const
480 {
481 return QVector3D(xp, yp, zp, 1);
482 }
483
484 /*!
485 Returns the 3D vector form of this 4D vector, dividing the x, y, and
486 z coordinates by the w coordinate. Returns a null vector if w is zero.
487
488 \sa toVector3D(), toVector2DAffine(), toPoint()
489 */
toVector3DAffine() const490 QVector3D QVector4D::toVector3DAffine() const
491 {
492 if (qIsNull(wp))
493 return QVector3D();
494 return QVector3D(xp / wp, yp / wp, zp / wp, 1);
495 }
496
497 #endif
498
499 /*!
500 \fn QPoint QVector4D::toPoint() const
501
502 Returns the QPoint form of this 4D vector. The z and w coordinates
503 are dropped.
504
505 \sa toPointF(), toVector2D()
506 */
507
508 /*!
509 \fn QPointF QVector4D::toPointF() const
510
511 Returns the QPointF form of this 4D vector. The z and w coordinates
512 are dropped.
513
514 \sa toPoint(), toVector2D()
515 */
516
517 /*!
518 Returns the 4D vector as a QVariant.
519 */
operator QVariant() const520 QVector4D::operator QVariant() const
521 {
522 return QVariant(QVariant::Vector4D, this);
523 }
524
525 #ifndef QT_NO_DEBUG_STREAM
526
operator <<(QDebug dbg,const QVector4D & vector)527 QDebug operator<<(QDebug dbg, const QVector4D &vector)
528 {
529 dbg.nospace() << "QVector4D("
530 << vector.x() << ", " << vector.y() << ", "
531 << vector.z() << ", " << vector.w() << ')';
532 return dbg.space();
533 }
534
535 #endif
536
537 #ifndef QT_NO_DATASTREAM
538
539 /*!
540 \fn QDataStream &operator<<(QDataStream &stream, const QVector4D &vector)
541 \relates QVector4D
542
543 Writes the given \a vector to the given \a stream and returns a
544 reference to the stream.
545
546 \sa {Serializing Qt Data Types}
547 */
548
operator <<(QDataStream & stream,const QVector4D & vector)549 QDataStream &operator<<(QDataStream &stream, const QVector4D &vector)
550 {
551 stream << double(vector.x()) << double(vector.y())
552 << double(vector.z()) << double(vector.w());
553 return stream;
554 }
555
556 /*!
557 \fn QDataStream &operator>>(QDataStream &stream, QVector4D &vector)
558 \relates QVector4D
559
560 Reads a 4D vector from the given \a stream into the given \a vector
561 and returns a reference to the stream.
562
563 \sa {Serializing Qt Data Types}
564 */
565
operator >>(QDataStream & stream,QVector4D & vector)566 QDataStream &operator>>(QDataStream &stream, QVector4D &vector)
567 {
568 double x, y, z, w;
569 stream >> x;
570 stream >> y;
571 stream >> z;
572 stream >> w;
573 vector.setX(qreal(x));
574 vector.setY(qreal(y));
575 vector.setZ(qreal(z));
576 vector.setW(qreal(w));
577 return stream;
578 }
579
580 #endif // QT_NO_DATASTREAM
581
582 #endif // QT_NO_VECTOR4D
583
584 QT_END_NAMESPACE
585