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