1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qvector3d.h"
43 #include "qvector2d.h"
44 #include "qvector4d.h"
45 #include <QtCore/qdatastream.h>
46 #include <QtCore/qmath.h>
47 #include <QtCore/qvariant.h>
48 #include <QtCore/qdebug.h>
52 #ifndef QT_NO_VECTOR3D
56 \brief The QVector3D class represents a vector or vertex in 3D space.
61 Vectors are one of the main building blocks of 3D representation and
62 drawing. They consist of three coordinates, traditionally called
65 The QVector3D class can also be used to represent vertices in 3D space.
66 We therefore do not need to provide a separate vertex class.
68 \sa QVector2D, QVector4D, QQuaternion
72 \fn QVector3D::QVector3D()
74 Constructs a null vector, i.e. with coordinates (0, 0, 0).
78 \fn QVector3D::QVector3D(float xpos, float ypos, float zpos)
80 Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos).
84 \fn QVector3D::QVector3D(const QPoint& point)
86 Constructs a vector with x and y coordinates from a 2D \a point, and a
91 \fn QVector3D::QVector3D(const QPointF& point)
93 Constructs a vector with x and y coordinates from a 2D \a point, and a
97 #ifndef QT_NO_VECTOR2D
100 Constructs a 3D vector from the specified 2D \a vector. The z
101 coordinate is set to zero.
105 QVector3D::QVector3D(const QVector2D& vector)
113 Constructs a 3D vector from the specified 2D \a vector. The z
114 coordinate is set to \a zpos.
118 QVector3D::QVector3D(const QVector2D& vector, float zpos)
127 #ifndef QT_NO_VECTOR4D
130 Constructs a 3D vector from the specified 4D \a vector. The w
131 coordinate is dropped.
135 QVector3D::QVector3D(const QVector4D& vector)
145 \fn bool QVector3D::isNull() const
147 Returns true if the x, y, and z coordinates are set to 0.0,
148 otherwise returns false.
152 \fn float QVector3D::x() const
154 Returns the x coordinate of this point.
160 \fn float QVector3D::y() const
162 Returns the y coordinate of this point.
168 \fn float QVector3D::z() const
170 Returns the z coordinate of this point.
176 \fn void QVector3D::setX(float x)
178 Sets the x coordinate of this point to the given \a x coordinate.
180 \sa x(), setY(), setZ()
184 \fn void QVector3D::setY(float y)
186 Sets the y coordinate of this point to the given \a y coordinate.
188 \sa y(), setX(), setZ()
192 \fn void QVector3D::setZ(float z)
194 Sets the z coordinate of this point to the given \a z coordinate.
196 \sa z(), setX(), setY()
200 Returns the normalized unit vector form of this vector.
202 If this vector is null, then a null vector is returned. If the length
203 of the vector is very close to 1, then the vector will be returned as-is.
204 Otherwise the normalized form of the vector of length 1 will be returned.
206 \sa length(), normalize()
208 QVector3D QVector3D::normalized() const
210 // Need some extra precision if the length is very small.
211 double len = double(xp) * double(xp) +
212 double(yp) * double(yp) +
213 double(zp) * double(zp);
214 if (qFuzzyIsNull(len - 1.0f)) {
216 } else if (!qFuzzyIsNull(len)) {
217 double sqrtLen = sqrt(len);
218 return QVector3D(float(double(xp) / sqrtLen),
219 float(double(yp) / sqrtLen),
220 float(double(zp) / sqrtLen));
227 Normalizes the currect vector in place. Nothing happens if this
228 vector is a null vector or the length of the vector is very close to 1.
230 \sa length(), normalized()
232 void QVector3D::normalize()
234 // Need some extra precision if the length is very small.
235 double len = double(xp) * double(xp) +
236 double(yp) * double(yp) +
237 double(zp) * double(zp);
238 if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
243 xp = float(double(xp) / len);
244 yp = float(double(yp) / len);
245 zp = float(double(zp) / len);
249 \fn QVector3D &QVector3D::operator+=(const QVector3D &vector)
251 Adds the given \a vector to this vector and returns a reference to
258 \fn QVector3D &QVector3D::operator-=(const QVector3D &vector)
260 Subtracts the given \a vector from this vector and returns a reference to
267 \fn QVector3D &QVector3D::operator*=(float factor)
269 Multiplies this vector's coordinates by the given \a factor, and
270 returns a reference to this vector.
276 \fn QVector3D &QVector3D::operator*=(const QVector3D& vector)
279 Multiplies the components of this vector by the corresponding
280 components in \a vector.
282 Note: this is not the same as the crossProduct() of this
283 vector and \a vector.
289 \fn QVector3D &QVector3D::operator/=(float divisor)
291 Divides this vector's coordinates by the given \a divisor, and
292 returns a reference to this vector.
298 Returns the dot product of \a v1 and \a v2.
300 float QVector3D::dotProduct(const QVector3D& v1, const QVector3D& v2)
302 return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp;
306 Returns the cross-product of vectors \a v1 and \a v2, which corresponds
307 to the normal vector of a plane defined by \a v1 and \a v2.
311 QVector3D QVector3D::crossProduct(const QVector3D& v1, const QVector3D& v2)
313 return QVector3D(v1.yp * v2.zp - v1.zp * v2.yp,
314 v1.zp * v2.xp - v1.xp * v2.zp,
315 v1.xp * v2.yp - v1.yp * v2.xp);
319 Returns the normal vector of a plane defined by vectors \a v1 and \a v2,
320 normalized to be a unit vector.
322 Use crossProduct() to compute the cross-product of \a v1 and \a v2 if you
323 do not need the result to be normalized to a unit vector.
325 \sa crossProduct(), distanceToPlane()
327 QVector3D QVector3D::normal(const QVector3D& v1, const QVector3D& v2)
329 return crossProduct(v1, v2).normalized();
335 Returns the normal vector of a plane defined by vectors
336 \a v2 - \a v1 and \a v3 - \a v1, normalized to be a unit vector.
338 Use crossProduct() to compute the cross-product of \a v2 - \a v1 and
339 \a v3 - \a v1 if you do not need the result to be normalized to a
342 \sa crossProduct(), distanceToPlane()
344 QVector3D QVector3D::normal
345 (const QVector3D& v1, const QVector3D& v2, const QVector3D& v3)
347 return crossProduct((v2 - v1), (v3 - v1)).normalized();
351 Returns the distance from this vertex to a plane defined by
352 the vertex \a plane and a \a normal unit vector. The \a normal
353 parameter is assumed to have been normalized to a unit vector.
355 The return value will be negative if the vertex is below the plane,
356 or zero if it is on the plane.
358 \sa normal(), distanceToLine()
360 float QVector3D::distanceToPlane
361 (const QVector3D& plane, const QVector3D& normal) const
363 return dotProduct(*this - plane, normal);
369 Returns the distance from this vertex a plane defined by
370 the vertices \a plane1, \a plane2 and \a plane3.
372 The return value will be negative if the vertex is below the plane,
373 or zero if it is on the plane.
375 The two vectors that define the plane are \a plane2 - \a plane1
376 and \a plane3 - \a plane1.
378 \sa normal(), distanceToLine()
380 float QVector3D::distanceToPlane
381 (const QVector3D& plane1, const QVector3D& plane2, const QVector3D& plane3) const
383 QVector3D n = normal(plane2 - plane1, plane3 - plane1);
384 return dotProduct(*this - plane1, n);
388 Returns the distance that this vertex is from a line defined
389 by \a point and the unit vector \a direction.
391 If \a direction is a null vector, then it does not define a line.
392 In that case, the distance from \a point to this vertex is returned.
394 \sa distanceToPlane()
396 float QVector3D::distanceToLine
397 (const QVector3D& point, const QVector3D& direction) const
399 if (direction.isNull())
400 return (*this - point).length();
401 QVector3D p = point + dotProduct(*this - point, direction) * direction;
402 return (*this - p).length();
406 \fn bool operator==(const QVector3D &v1, const QVector3D &v2)
409 Returns true if \a v1 is equal to \a v2; otherwise returns false.
410 This operator uses an exact floating-point comparison.
414 \fn bool operator!=(const QVector3D &v1, const QVector3D &v2)
417 Returns true if \a v1 is not equal to \a v2; otherwise returns false.
418 This operator uses an exact floating-point comparison.
422 \fn const QVector3D operator+(const QVector3D &v1, const QVector3D &v2)
425 Returns a QVector3D object that is the sum of the given vectors, \a v1
426 and \a v2; each component is added separately.
428 \sa QVector3D::operator+=()
432 \fn const QVector3D operator-(const QVector3D &v1, const QVector3D &v2)
435 Returns a QVector3D object that is formed by subtracting \a v2 from \a v1;
436 each component is subtracted separately.
438 \sa QVector3D::operator-=()
442 \fn const QVector3D operator*(float factor, const QVector3D &vector)
445 Returns a copy of the given \a vector, multiplied by the given \a factor.
447 \sa QVector3D::operator*=()
451 \fn const QVector3D operator*(const QVector3D &vector, float factor)
454 Returns a copy of the given \a vector, multiplied by the given \a factor.
456 \sa QVector3D::operator*=()
460 \fn const QVector3D operator*(const QVector3D &v1, const QVector3D& v2)
463 Multiplies the components of \a v1 by the corresponding components in \a v2.
465 Note: this is not the same as the crossProduct() of \a v1 and \a v2.
467 \sa QVector3D::crossProduct()
471 \fn const QVector3D operator-(const QVector3D &vector)
475 Returns a QVector3D object that is formed by changing the sign of
476 all three components of the given \a vector.
478 Equivalent to \c {QVector3D(0,0,0) - vector}.
482 \fn const QVector3D operator/(const QVector3D &vector, float divisor)
485 Returns the QVector3D object formed by dividing all three components of
486 the given \a vector by the given \a divisor.
488 \sa QVector3D::operator/=()
492 \fn bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2)
495 Returns true if \a v1 and \a v2 are equal, allowing for a small
496 fuzziness factor for floating-point comparisons; false otherwise.
499 #ifndef QT_NO_VECTOR2D
502 Returns the 2D vector form of this 3D vector, dropping the z coordinate.
504 \sa toVector4D(), toPoint()
506 QVector2D QVector3D::toVector2D() const
508 return QVector2D(xp, yp);
513 #ifndef QT_NO_VECTOR4D
516 Returns the 4D form of this 3D vector, with the w coordinate set to zero.
518 \sa toVector2D(), toPoint()
520 QVector4D QVector3D::toVector4D() const
522 return QVector4D(xp, yp, zp, 0.0f);
528 \fn QPoint QVector3D::toPoint() const
530 Returns the QPoint form of this 3D vector. The z coordinate
533 \sa toPointF(), toVector2D()
537 \fn QPointF QVector3D::toPointF() const
539 Returns the QPointF form of this 3D vector. The z coordinate
542 \sa toPoint(), toVector2D()
546 Returns the 3D vector as a QVariant.
548 QVector3D::operator QVariant() const
550 return QVariant(QVariant::Vector3D, this);
554 Returns the length of the vector from the origin.
556 \sa lengthSquared(), normalized()
558 float QVector3D::length() const
560 // Need some extra precision if the length is very small.
561 double len = double(xp) * double(xp) +
562 double(yp) * double(yp) +
563 double(zp) * double(zp);
564 return float(sqrt(len));
568 Returns the squared length of the vector from the origin.
569 This is equivalent to the dot product of the vector with itself.
571 \sa length(), dotProduct()
573 float QVector3D::lengthSquared() const
575 return xp * xp + yp * yp + zp * zp;
578 #ifndef QT_NO_DEBUG_STREAM
580 QDebug operator<<(QDebug dbg, const QVector3D &vector)
582 dbg.nospace() << "QVector3D("
583 << vector.x() << ", " << vector.y() << ", " << vector.z() << ')';
589 #ifndef QT_NO_DATASTREAM
592 \fn QDataStream &operator<<(QDataStream &stream, const QVector3D &vector)
595 Writes the given \a vector to the given \a stream and returns a
596 reference to the stream.
598 \sa {Serializing Qt Data Types}
601 QDataStream &operator<<(QDataStream &stream, const QVector3D &vector)
603 stream << vector.x() << vector.y() << vector.z();
608 \fn QDataStream &operator>>(QDataStream &stream, QVector3D &vector)
611 Reads a 3D vector from the given \a stream into the given \a vector
612 and returns a reference to the stream.
614 \sa {Serializing Qt Data Types}
617 QDataStream &operator>>(QDataStream &stream, QVector3D &vector)
629 #endif // QT_NO_DATASTREAM
631 #endif // QT_NO_VECTOR3D