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