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 QtCore 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 "qline.h"
41#include "qdebug.h"
42#include "qdatastream.h"
43#include "qmath.h"
44#include <private/qnumeric_p.h>
45
46QT_BEGIN_NAMESPACE
47
48/*!
49 \class QLine
50 \inmodule QtCore
51 \ingroup painting
52
53 \brief The QLine class provides a two-dimensional vector using
54 integer precision.
55
56 A QLine describes a finite length line (or a line segment) on a
57 two-dimensional surface. The start and end points of the line are
58 specified using integer point accuracy for coordinates. Use the
59 QLineF constructor to retrieve a floating point copy.
60
61 \table
62 \row
63 \li \inlineimage qline-point.png
64 \li \inlineimage qline-coordinates.png
65 \endtable
66
67 The positions of the line's start and end points can be retrieved
68 using the p1(), x1(), y1(), p2(), x2(), and y2() functions. The
69 dx() and dy() functions return the horizontal and vertical
70 components of the line. Use isNull() to determine whether the
71 QLine represents a valid line or a null line.
72
73 Finally, the line can be translated a given offset using the
74 translate() function.
75
76 \sa QLineF, QPolygon, QRect
77*/
78
79/*!
80 \fn QLine::QLine()
81
82 Constructs a null line.
83*/
84
85/*!
86 \fn QLine::QLine(const QPoint &p1, const QPoint &p2)
87
88 Constructs a line object that represents the line between \a p1 and
89 \a p2.
90*/
91
92/*!
93 \fn QLine::QLine(int x1, int y1, int x2, int y2)
94
95 Constructs a line object that represents the line between (\a x1, \a y1) and
96 (\a x2, \a y2).
97*/
98
99/*!
100 \fn bool QLine::isNull() const
101
102 Returns \c true if the line is not set up with valid start and end point;
103 otherwise returns \c false.
104*/
105
106/*!
107 \fn QPoint QLine::p1() const
108
109 Returns the line's start point.
110
111 \sa x1(), y1(), p2()
112*/
113
114/*!
115 \fn QPoint QLine::p2() const
116
117 Returns the line's end point.
118
119 \sa x2(), y2(), p1()
120*/
121
122/*!
123 \fn int QLine::x1() const
124
125 Returns the x-coordinate of the line's start point.
126
127 \sa p1()
128*/
129
130/*!
131 \fn int QLine::y1() const
132
133 Returns the y-coordinate of the line's start point.
134
135 \sa p1()
136*/
137
138/*!
139 \fn int QLine::x2() const
140
141 Returns the x-coordinate of the line's end point.
142
143 \sa p2()
144*/
145
146/*!
147 \fn int QLine::y2() const
148
149 Returns the y-coordinate of the line's end point.
150
151 \sa p2()
152*/
153
154/*!
155 \fn int QLine::dx() const
156
157 Returns the horizontal component of the line's vector.
158
159 \sa dy()
160*/
161
162/*!
163 \fn int QLine::dy() const
164
165 Returns the vertical component of the line's vector.
166
167 \sa dx()
168*/
169
170/*!
171 \fn bool QLine::operator!=(const QLine &line) const
172
173 Returns \c true if the given \a line is not the same as \e this line.
174
175 A line is different from another line if any of their start or
176 end points differ, or the internal order of the points is different.
177*/
178
179/*!
180 \fn bool QLine::operator==(const QLine &line) const
181
182 Returns \c true if the given \a line is the same as \e this line.
183
184 A line is identical to another line if the start and end points
185 are identical, and the internal order of the points is the same.
186*/
187
188/*!
189 \fn void QLine::translate(const QPoint &offset)
190
191 Translates this line by the given \a offset.
192*/
193
194/*!
195 \fn void QLine::translate(int dx, int dy)
196 \overload
197
198 Translates this line the distance specified by \a dx and \a dy.
199*/
200
201/*!
202 \fn QLine QLine::translated(const QPoint &offset) const
203
204 \since 4.4
205
206 Returns this line translated by the given \a offset.
207*/
208
209/*!
210 \fn QLine QLine::translated(int dx, int dy) const
211 \overload
212 \since 4.4
213
214 Returns this line translated the distance specified by \a dx and \a dy.
215*/
216
217/*!
218 \fn QPoint QLine::center() const
219
220 \since 5.8
221
222 Returns the center point of this line. This is equivalent to
223 (p1() + p2()) / 2, except it will never overflow.
224*/
225
226/*!
227 \fn void QLine::setP1(const QPoint &p1)
228 \since 4.4
229
230 Sets the starting point of this line to \a p1.
231
232 \sa setP2(), p1()
233*/
234
235
236/*!
237 \fn void QLine::setP2(const QPoint &p2)
238 \since 4.4
239
240 Sets the end point of this line to \a p2.
241
242 \sa setP1(), p2()
243*/
244
245
246/*!
247 \fn void QLine::setPoints(const QPoint &p1, const QPoint &p2)
248 \since 4.4
249
250 Sets the start point of this line to \a p1 and the end point of this line to \a p2.
251
252 \sa setP1(), setP2(), p1(), p2()
253*/
254
255
256/*!
257 \fn void QLine::setLine(int x1, int y1, int x2, int y2)
258 \since 4.4
259
260 Sets this line to the start in \a x1, \a y1 and end in \a x2, \a y2.
261
262 \sa setP1(), setP2(), p1(), p2()
263*/
264
265
266
267#ifndef QT_NO_DEBUG_STREAM
268QDebug operator<<(QDebug dbg, const QLine &p)
269{
270 QDebugStateSaver saver(dbg);
271 dbg.nospace() << "QLine(" << p.p1() << ',' << p.p2() << ')';
272 return dbg;
273}
274#endif
275
276#ifndef QT_NO_DATASTREAM
277/*!
278 \relates QLine
279
280 Writes the given \a line to the given \a stream and returns a
281 reference to the stream.
282
283 \sa {Serializing Qt Data Types}
284*/
285
286QDataStream &operator<<(QDataStream &stream, const QLine &line)
287{
288 stream << line.p1() << line.p2();
289 return stream;
290}
291
292/*!
293 \relates QLine
294
295 Reads a line from the given \a stream into the given \a line and
296 returns a reference to the stream.
297
298 \sa {Serializing Qt Data Types}
299*/
300
301QDataStream &operator>>(QDataStream &stream, QLine &line)
302{
303 QPoint p1, p2;
304 stream >> p1;
305 stream >> p2;
306 line = QLine(p1, p2);
307
308 return stream;
309}
310
311#endif // QT_NO_DATASTREAM
312
313
314#ifndef M_2PI
315#define M_2PI 6.28318530717958647692528676655900576
316#endif
317
318/*!
319 \class QLineF
320 \inmodule QtCore
321 \ingroup painting
322
323 \brief The QLineF class provides a two-dimensional vector using
324 floating point precision.
325
326 A QLineF describes a finite length line (or line segment) on a
327 two-dimensional surface. QLineF defines the start and end points
328 of the line using floating point accuracy for coordinates. Use
329 the toLine() function to retrieve an integer based copy of this
330 line.
331
332 \table
333 \row
334 \li \inlineimage qline-point.png
335 \li \inlineimage qline-coordinates.png
336 \endtable
337
338 The positions of the line's start and end points can be retrieved
339 using the p1(), x1(), y1(), p2(), x2(), and y2() functions. The
340 dx() and dy() functions return the horizontal and vertical
341 components of the line, respectively.
342
343 The line's length can be retrieved using the length() function,
344 and altered using the setLength() function. Similarly, angle()
345 and setAngle() are respectively used for retrieving and altering
346 the angle of the line. Use the isNull()
347 function to determine whether the QLineF represents a valid line
348 or a null line.
349
350 The intersects() function determines the IntersectionType for this
351 line and a given line, while the angleTo() function returns the
352 angle between the lines. In addition, the unitVector() function
353 returns a line that has the same starting point as this line, but
354 with a length of only 1, while the normalVector() function returns
355 a line that is perpendicular to this line with the same starting
356 point and length.
357
358 Finally, the line can be translated a given offset using the
359 translate() function, and can be traversed using the pointAt()
360 function.
361
362 \section1 Constraints
363
364 QLine is limited to the minimum and maximum values for the
365 \c int type. Operations on a QLine that could potentially result
366 in values outside this range will result in undefined behavior.
367
368 \sa QLine, QPolygonF, QRectF
369*/
370
371/*!
372 \enum QLineF::IntersectType
373 \obsolete Use QLineF::IntersectionType instead
374*/
375
376/*!
377 \enum QLineF::IntersectionType
378
379 Describes the intersection between two lines.
380
381 \table
382 \row
383 \li \inlineimage qlinef-unbounded.png
384 \li \inlineimage qlinef-bounded.png
385 \row
386 \li QLineF::UnboundedIntersection
387 \li QLineF::BoundedIntersection
388 \endtable
389
390 \value NoIntersection Indicates that the lines do not intersect;
391 i.e. they are parallel.
392
393 \value UnboundedIntersection The two lines intersect, but not
394 within the range defined by their lengths. This will be the case
395 if the lines are not parallel. intersect() will also return this
396 value if the intersect point is within the start and end point of
397 only one of the lines.
398
399 \value BoundedIntersection The two lines intersect with each other
400 within the start and end points of each line.
401
402 \sa intersect()
403*/
404
405/*!
406 \fn QLineF::QLineF()
407
408 Constructs a null line.
409*/
410
411/*!
412 \fn QLineF::QLineF(const QPointF &p1, const QPointF &p2)
413
414 Constructs a line object that represents the line between \a p1 and
415 \a p2.
416*/
417
418/*!
419 \fn QLineF::QLineF(qreal x1, qreal y1, qreal x2, qreal y2)
420
421 Constructs a line object that represents the line between (\a x1, \a y1) and
422 (\a x2, \a y2).
423*/
424
425/*!
426 \fn QLineF::QLineF(const QLine &line)
427
428 Construct a QLineF object from the given integer-based \a line.
429
430 \sa toLine()
431*/
432
433/*!
434 \fn bool QLineF::isNull() const
435
436 Returns \c true if the line is not set up with valid start and end point;
437 otherwise returns \c false.
438*/
439
440/*!
441 \fn QPointF QLineF::p1() const
442
443 Returns the line's start point.
444
445 \sa x1(), y1(), p2()
446*/
447
448/*!
449 \fn QPointF QLineF::p2() const
450
451 Returns the line's end point.
452
453 \sa x2(), y2(), p1()
454*/
455
456/*!
457 \fn QLine QLineF::toLine() const
458
459 Returns an integer based copy of this line.
460
461 Note that the returned line's start and end points are rounded to
462 the nearest integer.
463
464 \sa QLineF()
465*/
466/*!
467 \fn qreal QLineF::x1() const
468
469 Returns the x-coordinate of the line's start point.
470
471 \sa p1()
472*/
473
474/*!
475 \fn qreal QLineF::y1() const
476
477 Returns the y-coordinate of the line's start point.
478
479 \sa p1()
480*/
481
482/*!
483 \fn qreal QLineF::x2() const
484
485 Returns the x-coordinate of the line's end point.
486
487 \sa p2()
488*/
489
490/*!
491 \fn qreal QLineF::y2() const
492
493 Returns the y-coordinate of the line's end point.
494
495 \sa p2()
496*/
497
498/*!
499 \fn qreal QLineF::dx() const
500
501 Returns the horizontal component of the line's vector.
502
503 \sa dy(), pointAt()
504*/
505
506/*!
507 \fn qreal QLineF::dy() const
508
509 Returns the vertical component of the line's vector.
510
511 \sa dx(), pointAt()
512*/
513
514/*!
515 \fn void QLineF::setLength(qreal length)
516
517 Sets the length of the line to the given \a length. QLineF will
518 move the end point - p2() - of the line to give the line its new length.
519
520 If the line is a null line, the length will remain zero regardless
521 of the length specified.
522
523 \sa length(), isNull()
524*/
525
526/*!
527 \fn QLineF QLineF::normalVector() const
528
529 Returns a line that is perpendicular to this line with the same starting
530 point and length.
531
532 \image qlinef-normalvector.png
533
534 \sa unitVector()
535*/
536
537/*!
538 \fn bool QLineF::operator!=(const QLineF &line) const
539
540 Returns \c true if the given \a line is not the same as \e this line.
541
542 A line is different from another line if their start or end points
543 differ, or the internal order of the points is different.
544*/
545
546/*!
547 \fn bool QLineF::operator==(const QLineF &line) const
548
549 Returns \c true if the given \a line is the same as this line.
550
551 A line is identical to another line if the start and end points
552 are identical, and the internal order of the points is the same.
553*/
554
555/*!
556 \fn qreal QLineF::pointAt(qreal t) const
557
558 Returns the point at the parameterized position specified by \a
559 t. The function returns the line's start point if t = 0, and its end
560 point if t = 1.
561
562 \sa dx(), dy()
563*/
564
565/*!
566 Returns the length of the line.
567
568 \sa setLength()
569*/
570qreal QLineF::length() const
571{
572 qreal x = pt2.x() - pt1.x();
573 qreal y = pt2.y() - pt1.y();
574 return qSqrt(x*x + y*y);
575}
576
577/*!
578 \since 4.4
579
580 Returns the angle of the line in degrees.
581
582 The return value will be in the range of values from 0.0 up to but not
583 including 360.0. The angles are measured counter-clockwise from a point
584 on the x-axis to the right of the origin (x > 0).
585
586 \sa setAngle()
587*/
588qreal QLineF::angle() const
589{
590 const qreal dx = pt2.x() - pt1.x();
591 const qreal dy = pt2.y() - pt1.y();
592
593 const qreal theta = qAtan2(-dy, dx) * 360.0 / M_2PI;
594
595 const qreal theta_normalized = theta < 0 ? theta + 360 : theta;
596
597 if (qFuzzyCompare(theta_normalized, qreal(360)))
598 return qreal(0);
599 else
600 return theta_normalized;
601}
602
603/*!
604 \since 4.4
605
606 Sets the angle of the line to the given \a angle (in degrees).
607 This will change the position of the second point of the line such that
608 the line has the given angle.
609
610 Positive values for the angles mean counter-clockwise while negative values
611 mean the clockwise direction. Zero degrees is at the 3 o'clock position.
612
613 \sa angle()
614*/
615void QLineF::setAngle(qreal angle)
616{
617 const qreal angleR = angle * M_2PI / 360.0;
618 const qreal l = length();
619
620 const qreal dx = qCos(angleR) * l;
621 const qreal dy = -qSin(angleR) * l;
622
623 pt2.rx() = pt1.x() + dx;
624 pt2.ry() = pt1.y() + dy;
625}
626
627/*!
628 \since 4.4
629
630 Returns a QLineF with the given \a length and \a angle.
631
632 The first point of the line will be on the origin.
633
634 Positive values for the angles mean counter-clockwise while negative values
635 mean the clockwise direction. Zero degrees is at the 3 o'clock position.
636*/
637QLineF QLineF::fromPolar(qreal length, qreal angle)
638{
639 const qreal angleR = angle * M_2PI / 360.0;
640 return QLineF(0, 0, qCos(angleR) * length, -qSin(angleR) * length);
641}
642
643/*!
644 Returns the unit vector for this line, i.e a line starting at the
645 same point as \e this line with a length of 1.0.
646
647 \sa normalVector()
648*/
649QLineF QLineF::unitVector() const
650{
651 qreal x = pt2.x() - pt1.x();
652 qreal y = pt2.y() - pt1.y();
653
654 qreal len = qSqrt(x*x + y*y);
655 QLineF f(p1(), QPointF(pt1.x() + x/len, pt1.y() + y/len));
656
657#ifndef QT_NO_DEBUG
658 if (qAbs(f.length() - 1) >= 0.001)
659 qWarning("QLine::unitVector: New line does not have unit length");
660#endif
661
662 return f;
663}
664
665#if QT_DEPRECATED_SINCE(5, 14)
666/*!
667 \fn QLineF::IntersectType QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const
668 \obsolete Use intersects() instead
669
670 Returns a value indicating whether or not \e this line intersects
671 with the given \a line.
672
673 The actual intersection point is extracted to \a intersectionPoint
674 (if the pointer is valid). If the lines are parallel, the
675 intersection point is undefined.
676*/
677
678QLineF::IntersectType QLineF::intersect(const QLineF &l, QPointF *intersectionPoint) const
679{
680 return intersects(l, intersectionPoint);
681}
682#endif
683
684/*!
685 \fn QLineF::IntersectionType QLineF::intersects(const QLineF &line, QPointF *intersectionPoint) const
686 \since 5.14
687
688 Returns a value indicating whether or not \e this line intersects
689 with the given \a line.
690
691 The actual intersection point is extracted to \a intersectionPoint
692 (if the pointer is valid). If the lines are parallel, the
693 intersection point is undefined.
694*/
695QLineF::IntersectionType QLineF::intersects(const QLineF &l, QPointF *intersectionPoint) const
696{
697 // ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection"
698 const QPointF a = pt2 - pt1;
699 const QPointF b = l.pt1 - l.pt2;
700 const QPointF c = pt1 - l.pt1;
701
702 const qreal denominator = a.y() * b.x() - a.x() * b.y();
703 if (denominator == 0 || !qt_is_finite(denominator))
704 return NoIntersection;
705
706 const qreal reciprocal = 1 / denominator;
707 const qreal na = (b.y() * c.x() - b.x() * c.y()) * reciprocal;
708 if (intersectionPoint)
709 *intersectionPoint = pt1 + a * na;
710
711 if (na < 0 || na > 1)
712 return UnboundedIntersection;
713
714 const qreal nb = (a.x() * c.y() - a.y() * c.x()) * reciprocal;
715 if (nb < 0 || nb > 1)
716 return UnboundedIntersection;
717
718 return BoundedIntersection;
719}
720
721/*!
722 \fn void QLineF::translate(const QPointF &offset)
723
724 Translates this line by the given \a offset.
725*/
726
727/*!
728 \fn void QLineF::translate(qreal dx, qreal dy)
729 \overload
730
731 Translates this line the distance specified by \a dx and \a dy.
732*/
733
734/*!
735 \fn QLineF QLineF::translated(const QPointF &offset) const
736
737 \since 4.4
738
739 Returns this line translated by the given \a offset.
740*/
741
742/*!
743 \fn QLineF QLineF::translated(qreal dx, qreal dy) const
744 \overload
745 \since 4.4
746
747 Returns this line translated the distance specified by \a dx and \a dy.
748*/
749
750/*!
751 \fn QPointF QLineF::center() const
752
753 \since 5.8
754
755 Returns the center point of this line. This is equivalent to
756 0.5 * p1() + 0.5 * p2().
757*/
758
759/*!
760 \fn void QLineF::setP1(const QPointF &p1)
761 \since 4.4
762
763 Sets the starting point of this line to \a p1.
764
765 \sa setP2(), p1()
766*/
767
768
769/*!
770 \fn void QLineF::setP2(const QPointF &p2)
771 \since 4.4
772
773 Sets the end point of this line to \a p2.
774
775 \sa setP1(), p2()
776*/
777
778
779/*!
780 \fn void QLineF::setPoints(const QPointF &p1, const QPointF &p2)
781 \since 4.4
782
783 Sets the start point of this line to \a p1 and the end point of this line to \a p2.
784
785 \sa setP1(), setP2(), p1(), p2()
786*/
787
788
789/*!
790 \fn void QLineF::setLine(qreal x1, qreal y1, qreal x2, qreal y2)
791 \since 4.4
792
793 Sets this line to the start in \a x1, \a y1 and end in \a x2, \a y2.
794
795 \sa setP1(), setP2(), p1(), p2()
796*/
797
798/*!
799 \fn qreal QLineF::angleTo(const QLineF &line) const
800
801 \since 4.4
802
803 Returns the angle (in degrees) from this line to the given \a
804 line, taking the direction of the lines into account. If the lines
805 do not intersect within their range, it is the intersection point of
806 the extended lines that serves as origin (see
807 QLineF::UnboundedIntersection).
808
809 The returned value represents the number of degrees you need to add
810 to this line to make it have the same angle as the given \a line,
811 going counter-clockwise.
812
813 \sa intersect()
814*/
815qreal QLineF::angleTo(const QLineF &l) const
816{
817 if (isNull() || l.isNull())
818 return 0;
819
820 const qreal a1 = angle();
821 const qreal a2 = l.angle();
822
823 const qreal delta = a2 - a1;
824 const qreal delta_normalized = delta < 0 ? delta + 360 : delta;
825
826 if (qFuzzyCompare(delta, qreal(360)))
827 return 0;
828 else
829 return delta_normalized;
830}
831
832#if QT_DEPRECATED_SINCE(5, 14)
833/*!
834 \fn qreal QLineF::angle(const QLineF &line) const
835
836 \obsolete
837
838 Returns the angle (in degrees) between this line and the given \a
839 line, taking the direction of the lines into account. If the lines
840 do not intersect within their range, it is the intersection point of
841 the extended lines that serves as origin (see
842 QLineF::UnboundedIntersection).
843
844 \table
845 \row
846 \li \inlineimage qlinef-angle-identicaldirection.png
847 \li \inlineimage qlinef-angle-oppositedirection.png
848 \endtable
849
850 When the lines are parallel, this function returns 0 if they have
851 the same direction; otherwise it returns 180.
852
853 \sa intersect()
854*/
855qreal QLineF::angle(const QLineF &l) const
856{
857 if (isNull() || l.isNull())
858 return 0;
859 qreal cos_line = (dx()*l.dx() + dy()*l.dy()) / (length()*l.length());
860 qreal rad = 0;
861 // only accept cos_line in the range [-1,1], if it is outside, use 0 (we return 0 rather than PI for those cases)
862 if (cos_line >= -1.0 && cos_line <= 1.0) rad = qAcos( cos_line );
863 return rad * 360 / M_2PI;
864}
865#endif
866
867
868#ifndef QT_NO_DEBUG_STREAM
869QDebug operator<<(QDebug dbg, const QLineF &p)
870{
871 QDebugStateSaver saver(dbg);
872 dbg.nospace() << "QLineF(" << p.p1() << ',' << p.p2() << ')';
873 return dbg;
874}
875#endif
876
877#ifndef QT_NO_DATASTREAM
878/*!
879 \relates QLineF
880
881 Writes the given \a line to the given \a stream and returns a
882 reference to the stream.
883
884 \sa {Serializing Qt Data Types}
885*/
886
887QDataStream &operator<<(QDataStream &stream, const QLineF &line)
888{
889 stream << line.p1() << line.p2();
890 return stream;
891}
892
893/*!
894 \relates QLineF
895
896 Reads a line from the given \a stream into the given \a line and
897 returns a reference to the stream.
898
899 \sa {Serializing Qt Data Types}
900*/
901
902QDataStream &operator>>(QDataStream &stream, QLineF &line)
903{
904 QPointF start, end;
905 stream >> start;
906 stream >> end;
907 line = QLineF(start, end);
908
909 return stream;
910}
911
912#endif // QT_NO_DATASTREAM
913
914QT_END_NAMESPACE
915