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