src/gui/math3d/qvector3d.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    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     \sa QVector2D, QVector4D, QQuaternion
       
    67 */
       
    68 
       
    69 /*!
       
    70     \fn QVector3D::QVector3D()
       
    71 
       
    72     Constructs a null vector, i.e. with coordinates (0, 0, 0).
       
    73 */
       
    74 
       
    75 /*!
       
    76     \fn QVector3D::QVector3D(qreal xpos, qreal ypos, qreal zpos)
       
    77 
       
    78     Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos).
       
    79 */
       
    80 
       
    81 /*!
       
    82     \fn QVector3D::QVector3D(const QPoint& point)
       
    83 
       
    84     Constructs a vector with x and y coordinates from a 2D \a point, and a
       
    85     z coordinate of 0.
       
    86 */
       
    87 
       
    88 /*!
       
    89     \fn QVector3D::QVector3D(const QPointF& point)
       
    90 
       
    91     Constructs a vector with x and y coordinates from a 2D \a point, and a
       
    92     z coordinate of 0.
       
    93 */
       
    94 
       
    95 #ifndef QT_NO_VECTOR2D
       
    96 
       
    97 /*!
       
    98     Constructs a 3D vector from the specified 2D \a vector.  The z
       
    99     coordinate is set to zero.
       
   100 
       
   101     \sa toVector2D()
       
   102 */
       
   103 QVector3D::QVector3D(const QVector2D& vector)
       
   104 {
       
   105     xp = vector.xp;
       
   106     yp = vector.yp;
       
   107     zp = 0.0f;
       
   108 }
       
   109 
       
   110 /*!
       
   111     Constructs a 3D vector from the specified 2D \a vector.  The z
       
   112     coordinate is set to \a zpos.
       
   113 
       
   114     \sa toVector2D()
       
   115 */
       
   116 QVector3D::QVector3D(const QVector2D& vector, qreal zpos)
       
   117 {
       
   118     xp = vector.xp;
       
   119     yp = vector.yp;
       
   120     zp = zpos;
       
   121 }
       
   122 
       
   123 #endif
       
   124 
       
   125 #ifndef QT_NO_VECTOR4D
       
   126 
       
   127 /*!
       
   128     Constructs a 3D vector from the specified 4D \a vector.  The w
       
   129     coordinate is dropped.
       
   130 
       
   131     \sa toVector4D()
       
   132 */
       
   133 QVector3D::QVector3D(const QVector4D& vector)
       
   134 {
       
   135     xp = vector.xp;
       
   136     yp = vector.yp;
       
   137     zp = vector.zp;
       
   138 }
       
   139 
       
   140 #endif
       
   141 
       
   142 /*!
       
   143     \fn bool QVector3D::isNull() const
       
   144 
       
   145     Returns true if the x, y, and z coordinates are set to 0.0,
       
   146     otherwise returns false.
       
   147 */
       
   148 
       
   149 /*!
       
   150     \fn qreal QVector3D::x() const
       
   151 
       
   152     Returns the x coordinate of this point.
       
   153 
       
   154     \sa setX(), y(), z()
       
   155 */
       
   156 
       
   157 /*!
       
   158     \fn qreal QVector3D::y() const
       
   159 
       
   160     Returns the y coordinate of this point.
       
   161 
       
   162     \sa setY(), x(), z()
       
   163 */
       
   164 
       
   165 /*!
       
   166     \fn qreal QVector3D::z() const
       
   167 
       
   168     Returns the z coordinate of this point.
       
   169 
       
   170     \sa setZ(), x(), y()
       
   171 */
       
   172 
       
   173 /*!
       
   174     \fn void QVector3D::setX(qreal x)
       
   175 
       
   176     Sets the x coordinate of this point to the given \a x coordinate.
       
   177 
       
   178     \sa x(), setY(), setZ()
       
   179 */
       
   180 
       
   181 /*!
       
   182     \fn void QVector3D::setY(qreal y)
       
   183 
       
   184     Sets the y coordinate of this point to the given \a y coordinate.
       
   185 
       
   186     \sa y(), setX(), setZ()
       
   187 */
       
   188 
       
   189 /*!
       
   190     \fn void QVector3D::setZ(qreal z)
       
   191 
       
   192     Sets the z coordinate of this point to the given \a z coordinate.
       
   193 
       
   194     \sa z(), setX(), setY()
       
   195 */
       
   196 
       
   197 /*!
       
   198     Returns the normalized unit vector form of this vector.
       
   199 
       
   200     If this vector is null, then a null vector is returned.  If the length
       
   201     of the vector is very close to 1, then the vector will be returned as-is.
       
   202     Otherwise the normalized form of the vector of length 1 will be returned.
       
   203 
       
   204     \sa length(), normalize()
       
   205 */
       
   206 QVector3D QVector3D::normalized() const
       
   207 {
       
   208     // Need some extra precision if the length is very small.
       
   209     double len = double(xp) * double(xp) +
       
   210                  double(yp) * double(yp) +
       
   211                  double(zp) * double(zp);
       
   212     if (qFuzzyIsNull(len - 1.0f))
       
   213         return *this;
       
   214     else if (!qFuzzyIsNull(len))
       
   215         return *this / qSqrt(len);
       
   216     else
       
   217         return QVector3D();
       
   218 }
       
   219 
       
   220 /*!
       
   221     Normalizes the currect vector in place.  Nothing happens if this
       
   222     vector is a null vector or the length of the vector is very close to 1.
       
   223 
       
   224     \sa length(), normalized()
       
   225 */
       
   226 void QVector3D::normalize()
       
   227 {
       
   228     // Need some extra precision if the length is very small.
       
   229     double len = double(xp) * double(xp) +
       
   230                  double(yp) * double(yp) +
       
   231                  double(zp) * double(zp);
       
   232     if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
       
   233         return;
       
   234 
       
   235     len = qSqrt(len);
       
   236 
       
   237     xp /= len;
       
   238     yp /= len;
       
   239     zp /= len;
       
   240 }
       
   241 
       
   242 /*!
       
   243     \fn QVector3D &QVector3D::operator+=(const QVector3D &vector)
       
   244 
       
   245     Adds the given \a vector to this vector and returns a reference to
       
   246     this vector.
       
   247 
       
   248     \sa operator-=()
       
   249 */
       
   250 
       
   251 /*!
       
   252     \fn QVector3D &QVector3D::operator-=(const QVector3D &vector)
       
   253 
       
   254     Subtracts the given \a vector from this vector and returns a reference to
       
   255     this vector.
       
   256 
       
   257     \sa operator+=()
       
   258 */
       
   259 
       
   260 /*!
       
   261     \fn QVector3D &QVector3D::operator*=(qreal factor)
       
   262 
       
   263     Multiplies this vector's coordinates by the given \a factor, and
       
   264     returns a reference to this vector.
       
   265 
       
   266     \sa operator/=()
       
   267 */
       
   268 
       
   269 /*!
       
   270     \fn QVector3D &QVector3D::operator*=(const QVector3D& vector)
       
   271     \overload
       
   272 
       
   273     Multiplies the components of this vector by the corresponding
       
   274     components in \a vector.
       
   275 
       
   276     Note: this is not the same as the crossProduct() of this
       
   277     vector and \a vector.
       
   278 
       
   279     \sa crossProduct()
       
   280 */
       
   281 
       
   282 /*!
       
   283     \fn QVector3D &QVector3D::operator/=(qreal divisor)
       
   284 
       
   285     Divides this vector's coordinates by the given \a divisor, and
       
   286     returns a reference to this vector.
       
   287 
       
   288     \sa operator*=()
       
   289 */
       
   290 
       
   291 /*!
       
   292     Returns the dot product of \a v1 and \a v2.
       
   293 */
       
   294 qreal QVector3D::dotProduct(const QVector3D& v1, const QVector3D& v2)
       
   295 {
       
   296     return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp;
       
   297 }
       
   298 
       
   299 /*!
       
   300     Returns the cross-product of vectors \a v1 and \a v2, which corresponds
       
   301     to the normal vector of a plane defined by \a v1 and \a v2.
       
   302 
       
   303     \sa normal()
       
   304 */
       
   305 QVector3D QVector3D::crossProduct(const QVector3D& v1, const QVector3D& v2)
       
   306 {
       
   307     return QVector3D(v1.yp * v2.zp - v1.zp * v2.yp,
       
   308                     v1.zp * v2.xp - v1.xp * v2.zp,
       
   309                     v1.xp * v2.yp - v1.yp * v2.xp, 1);
       
   310 }
       
   311 
       
   312 /*!
       
   313     Returns the normal vector of a plane defined by vectors \a v1 and \a v2,
       
   314     normalized to be a unit vector.
       
   315 
       
   316     Use crossProduct() to compute the cross-product of \a v1 and \a v2 if you
       
   317     do not need the result to be normalized to a unit vector.
       
   318 
       
   319     \sa crossProduct(), distanceToPlane()
       
   320 */
       
   321 QVector3D QVector3D::normal(const QVector3D& v1, const QVector3D& v2)
       
   322 {
       
   323     return crossProduct(v1, v2).normalized();
       
   324 }
       
   325 
       
   326 /*!
       
   327     \overload
       
   328 
       
   329     Returns the normal vector of a plane defined by vectors
       
   330     \a v2 - \a v1 and \a v3 - \a v1, normalized to be a unit vector.
       
   331 
       
   332     Use crossProduct() to compute the cross-product of \a v2 - \a v1 and
       
   333     \a v3 - \a v1 if you do not need the result to be normalized to a
       
   334     unit vector.
       
   335 
       
   336     \sa crossProduct(), distanceToPlane()
       
   337 */
       
   338 QVector3D QVector3D::normal
       
   339         (const QVector3D& v1, const QVector3D& v2, const QVector3D& v3)
       
   340 {
       
   341     return crossProduct((v2 - v1), (v3 - v1)).normalized();
       
   342 }
       
   343 
       
   344 /*!
       
   345     Returns the distance from this vertex to a plane defined by
       
   346     the vertex \a plane and a \a normal unit vector.  The \a normal
       
   347     parameter is assumed to have been normalized to a unit vector.
       
   348 
       
   349     The return value will be negative if the vertex is below the plane,
       
   350     or zero if it is on the plane.
       
   351 
       
   352     \sa normal(), distanceToLine()
       
   353 */
       
   354 qreal QVector3D::distanceToPlane
       
   355         (const QVector3D& plane, const QVector3D& normal) const
       
   356 {
       
   357     return dotProduct(*this - plane, normal);
       
   358 }
       
   359 
       
   360 /*!
       
   361     \overload
       
   362 
       
   363     Returns the distance from this vertex a plane defined by
       
   364     the vertices \a plane1, \a plane2 and \a plane3.
       
   365 
       
   366     The return value will be negative if the vertex is below the plane,
       
   367     or zero if it is on the plane.
       
   368 
       
   369     The two vectors that define the plane are \a plane2 - \a plane1
       
   370     and \a plane3 - \a plane1.
       
   371 
       
   372     \sa normal(), distanceToLine()
       
   373 */
       
   374 qreal QVector3D::distanceToPlane
       
   375     (const QVector3D& plane1, const QVector3D& plane2, const QVector3D& plane3) const
       
   376 {
       
   377     QVector3D n = normal(plane2 - plane1, plane3 - plane1);
       
   378     return dotProduct(*this - plane1, n);
       
   379 }
       
   380 
       
   381 /*!
       
   382     Returns the distance that this vertex is from a line defined
       
   383     by \a point and the unit vector \a direction.
       
   384 
       
   385     If \a direction is a null vector, then it does not define a line.
       
   386     In that case, the distance from \a point to this vertex is returned.
       
   387 
       
   388     \sa distanceToPlane()
       
   389 */
       
   390 qreal QVector3D::distanceToLine
       
   391         (const QVector3D& point, const QVector3D& direction) const
       
   392 {
       
   393     if (direction.isNull())
       
   394         return (*this - point).length();
       
   395     QVector3D p = point + dotProduct(*this - point, direction) * direction;
       
   396     return (*this - p).length();
       
   397 }
       
   398 
       
   399 /*!
       
   400     \fn bool operator==(const QVector3D &v1, const QVector3D &v2)
       
   401     \relates QVector3D
       
   402 
       
   403     Returns true if \a v1 is equal to \a v2; otherwise returns false.
       
   404     This operator uses an exact floating-point comparison.
       
   405 */
       
   406 
       
   407 /*!
       
   408     \fn bool operator!=(const QVector3D &v1, const QVector3D &v2)
       
   409     \relates QVector3D
       
   410 
       
   411     Returns true if \a v1 is not equal to \a v2; otherwise returns false.
       
   412     This operator uses an exact floating-point comparison.
       
   413 */
       
   414 
       
   415 /*!
       
   416     \fn const QVector3D operator+(const QVector3D &v1, const QVector3D &v2)
       
   417     \relates QVector3D
       
   418 
       
   419     Returns a QVector3D object that is the sum of the given vectors, \a v1
       
   420     and \a v2; each component is added separately.
       
   421 
       
   422     \sa QVector3D::operator+=()
       
   423 */
       
   424 
       
   425 /*!
       
   426     \fn const QVector3D operator-(const QVector3D &v1, const QVector3D &v2)
       
   427     \relates QVector3D
       
   428 
       
   429     Returns a QVector3D object that is formed by subtracting \a v2 from \a v1;
       
   430     each component is subtracted separately.
       
   431 
       
   432     \sa QVector3D::operator-=()
       
   433 */
       
   434 
       
   435 /*!
       
   436     \fn const QVector3D operator*(qreal factor, const QVector3D &vector)
       
   437     \relates QVector3D
       
   438 
       
   439     Returns a copy of the given \a vector,  multiplied by the given \a factor.
       
   440 
       
   441     \sa QVector3D::operator*=()
       
   442 */
       
   443 
       
   444 /*!
       
   445     \fn const QVector3D operator*(const QVector3D &vector, qreal factor)
       
   446     \relates QVector3D
       
   447 
       
   448     Returns a copy of the given \a vector,  multiplied by the given \a factor.
       
   449 
       
   450     \sa QVector3D::operator*=()
       
   451 */
       
   452 
       
   453 /*!
       
   454     \fn const QVector3D operator*(const QVector3D &v1, const QVector3D& v2)
       
   455     \relates QVector3D
       
   456 
       
   457     Multiplies the components of \a v1 by the corresponding components in \a v2.
       
   458 
       
   459     Note: this is not the same as the crossProduct() of \a v1 and \a v2.
       
   460 
       
   461     \sa QVector3D::crossProduct()
       
   462 */
       
   463 
       
   464 /*!
       
   465     \fn const QVector3D operator-(const QVector3D &vector)
       
   466     \relates QVector3D
       
   467     \overload
       
   468 
       
   469     Returns a QVector3D object that is formed by changing the sign of
       
   470     all three components of the given \a vector.
       
   471 
       
   472     Equivalent to \c {QVector3D(0,0,0) - vector}.
       
   473 */
       
   474 
       
   475 /*!
       
   476     \fn const QVector3D operator/(const QVector3D &vector, qreal divisor)
       
   477     \relates QVector3D
       
   478 
       
   479     Returns the QVector3D object formed by dividing all three components of
       
   480     the given \a vector by the given \a divisor.
       
   481 
       
   482     \sa QVector3D::operator/=()
       
   483 */
       
   484 
       
   485 /*!
       
   486     \fn bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2)
       
   487     \relates QVector3D
       
   488 
       
   489     Returns true if \a v1 and \a v2 are equal, allowing for a small
       
   490     fuzziness factor for floating-point comparisons; false otherwise.
       
   491 */
       
   492 
       
   493 #ifndef QT_NO_VECTOR2D
       
   494 
       
   495 /*!
       
   496     Returns the 2D vector form of this 3D vector, dropping the z coordinate.
       
   497 
       
   498     \sa toVector4D(), toPoint()
       
   499 */
       
   500 QVector2D QVector3D::toVector2D() const
       
   501 {
       
   502     return QVector2D(xp, yp, 1);
       
   503 }
       
   504 
       
   505 #endif
       
   506 
       
   507 #ifndef QT_NO_VECTOR4D
       
   508 
       
   509 /*!
       
   510     Returns the 4D form of this 3D vector, with the w coordinate set to zero.
       
   511 
       
   512     \sa toVector2D(), toPoint()
       
   513 */
       
   514 QVector4D QVector3D::toVector4D() const
       
   515 {
       
   516     return QVector4D(xp, yp, zp, 0.0f, 1);
       
   517 }
       
   518 
       
   519 #endif
       
   520 
       
   521 /*!
       
   522     \fn QPoint QVector3D::toPoint() const
       
   523 
       
   524     Returns the QPoint form of this 3D vector. The z coordinate
       
   525     is dropped.
       
   526 
       
   527     \sa toPointF(), toVector2D()
       
   528 */
       
   529 
       
   530 /*!
       
   531     \fn QPointF QVector3D::toPointF() const
       
   532 
       
   533     Returns the QPointF form of this 3D vector. The z coordinate
       
   534     is dropped.
       
   535 
       
   536     \sa toPoint(), toVector2D()
       
   537 */
       
   538 
       
   539 /*!
       
   540     Returns the 3D vector as a QVariant.
       
   541 */
       
   542 QVector3D::operator QVariant() const
       
   543 {
       
   544     return QVariant(QVariant::Vector3D, this);
       
   545 }
       
   546 
       
   547 /*!
       
   548     Returns the length of the vector from the origin.
       
   549 
       
   550     \sa lengthSquared(), normalized()
       
   551 */
       
   552 qreal QVector3D::length() const
       
   553 {
       
   554     return qSqrt(xp * xp + yp * yp + zp * zp);
       
   555 }
       
   556 
       
   557 /*!
       
   558     Returns the squared length of the vector from the origin.
       
   559     This is equivalent to the dot product of the vector with itself.
       
   560 
       
   561     \sa length(), dotProduct()
       
   562 */
       
   563 qreal QVector3D::lengthSquared() const
       
   564 {
       
   565     return xp * xp + yp * yp + zp * zp;
       
   566 }
       
   567 
       
   568 #ifndef QT_NO_DEBUG_STREAM
       
   569 
       
   570 QDebug operator<<(QDebug dbg, const QVector3D &vector)
       
   571 {
       
   572     dbg.nospace() << "QVector3D("
       
   573         << vector.x() << ", " << vector.y() << ", " << vector.z() << ')';
       
   574     return dbg.space();
       
   575 }
       
   576 
       
   577 #endif
       
   578 
       
   579 #ifndef QT_NO_DATASTREAM
       
   580 
       
   581 /*!
       
   582     \fn QDataStream &operator<<(QDataStream &stream, const QVector3D &vector)
       
   583     \relates QVector3D
       
   584 
       
   585     Writes the given \a vector to the given \a stream and returns a
       
   586     reference to the stream.
       
   587 
       
   588     \sa {Format of the QDataStream Operators}
       
   589 */
       
   590 
       
   591 QDataStream &operator<<(QDataStream &stream, const QVector3D &vector)
       
   592 {
       
   593     stream << double(vector.x()) << double(vector.y())
       
   594            << double(vector.z());
       
   595     return stream;
       
   596 }
       
   597 
       
   598 /*!
       
   599     \fn QDataStream &operator>>(QDataStream &stream, QVector3D &vector)
       
   600     \relates QVector3D
       
   601 
       
   602     Reads a 3D vector from the given \a stream into the given \a vector
       
   603     and returns a reference to the stream.
       
   604 
       
   605     \sa {Format of the QDataStream Operators}
       
   606 */
       
   607 
       
   608 QDataStream &operator>>(QDataStream &stream, QVector3D &vector)
       
   609 {
       
   610     double x, y, z;
       
   611     stream >> x;
       
   612     stream >> y;
       
   613     stream >> z;
       
   614     vector.setX(qreal(x));
       
   615     vector.setY(qreal(y));
       
   616     vector.setZ(qreal(z));
       
   617     return stream;
       
   618 }
       
   619 
       
   620 #endif // QT_NO_DATASTREAM
       
   621 
       
   622 #endif // QT_NO_VECTOR3D
       
   623 
       
   624 QT_END_NAMESPACE