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