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

source code of qtbase/src/corelib/tools/qline.cpp