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