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