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 \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
512
513 \sa unitVector()
514*/
515
516/*!
517 \fn bool QLineF::operator!=(const QLineF &lhs, const QLineF &rhs)
518
519 Returns \c true if the line \a lhs is not the same as line \a rhs.
520
521 A line is different from another line if their start or end points
522 differ, or the internal order of the points is different.
523*/
524
525/*!
526 \fn bool QLineF::operator==(const QLineF &lhs, const QLineF &rhs)
527
528 Returns \c true if the line \a lhs is the same as line \a rhs.
529
530 A line is identical to another line if the start and end points
531 are identical, and the internal order of the points is the same.
532*/
533
534/*!
535 \fn qreal QLineF::pointAt(qreal t) const
536
537 Returns the point at the position specified by finite parameter \a t. The
538 function returns the line's start point if t = 0, and its end point if t = 1.
539
540 \sa dx(), dy()
541*/
542
543/*!
544 Returns the length of the line.
545
546 \sa setLength(), isNull()
547*/
548qreal QLineF::length() const
549{
550 return qHypot(x: dx(), y: dy());
551}
552
553/*!
554 \since 4.4
555
556 Returns the angle of the line in degrees.
557
558 The return value will be in the range of values from 0.0 up to but not
559 including 360.0. The angles are measured counter-clockwise from a point
560 on the x-axis to the right of the origin (x > 0).
561
562 \sa setAngle()
563*/
564qreal QLineF::angle() const
565{
566 const qreal dx = pt2.x() - pt1.x();
567 const qreal dy = pt2.y() - pt1.y();
568
569 const qreal theta = qRadiansToDegrees(radians: qAtan2(y: -dy, x: dx));
570
571 const qreal theta_normalized = theta < 0 ? theta + 360 : theta;
572
573 if (qFuzzyCompare(p1: theta_normalized, p2: qreal(360)))
574 return qreal(0);
575 else
576 return theta_normalized;
577}
578
579/*!
580 \since 4.4
581
582 Sets the angle of the line to the given \a angle (in degrees).
583 This will change the position of the second point of the line such that
584 the line has the given angle.
585
586 Positive values for the angles mean counter-clockwise while negative values
587 mean the clockwise direction. Zero degrees is at the 3 o'clock position.
588
589 \sa angle()
590*/
591void QLineF::setAngle(qreal angle)
592{
593 const qreal angleR = qDegreesToRadians(degrees: angle);
594 const qreal l = length();
595
596 const qreal dx = qCos(v: angleR) * l;
597 const qreal dy = -qSin(v: angleR) * l;
598
599 pt2.rx() = pt1.x() + dx;
600 pt2.ry() = pt1.y() + dy;
601}
602
603/*!
604 \since 4.4
605
606 Returns a QLineF with the given \a length and \a angle.
607
608 The first point of the line will be on the origin.
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*/
613QLineF QLineF::fromPolar(qreal length, qreal angle)
614{
615 const qreal angleR = qDegreesToRadians(degrees: angle);
616 return QLineF(0, 0, qCos(v: angleR) * length, -qSin(v: angleR) * length);
617}
618
619/*!
620 Returns the unit vector for this line, i.e a line starting at the
621 same point as \e this line with a length of 1.0, provided the line
622 is non-null.
623
624 \sa normalVector(), setLength()
625*/
626QLineF QLineF::unitVector() const
627{
628 const qreal x = dx();
629 const qreal y = dy();
630
631 const qreal len = qHypot(x, y);
632 QLineF f(p1(), QPointF(pt1.x() + x / len, pt1.y() + y / len));
633
634#ifndef QT_NO_DEBUG
635 if (qAbs(t: f.length() - 1) >= 0.001)
636 qWarning(msg: "QLine::unitVector: New line does not have unit length");
637#endif
638
639 return f;
640}
641
642/*!
643 \fn QLineF::IntersectionType QLineF::intersects(const QLineF &line, QPointF *intersectionPoint) const
644 \since 5.14
645
646 Returns a value indicating whether or not \e this line intersects
647 with the given \a line.
648
649 The actual intersection point is extracted to \a intersectionPoint
650 (if the pointer is valid). If the lines are parallel, the
651 intersection point is undefined.
652*/
653QLineF::IntersectionType QLineF::intersects(const QLineF &l, QPointF *intersectionPoint) const
654{
655 // ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection"
656 const QPointF a = pt2 - pt1;
657 const QPointF b = l.pt1 - l.pt2;
658 const QPointF c = pt1 - l.pt1;
659
660 const qreal denominator = a.y() * b.x() - a.x() * b.y();
661 if (denominator == 0 || !qt_is_finite(d: denominator))
662 return NoIntersection;
663
664 const qreal reciprocal = 1 / denominator;
665 const qreal na = (b.y() * c.x() - b.x() * c.y()) * reciprocal;
666 if (intersectionPoint)
667 *intersectionPoint = pt1 + a * na;
668
669 if (na < 0 || na > 1)
670 return UnboundedIntersection;
671
672 const qreal nb = (a.x() * c.y() - a.y() * c.x()) * reciprocal;
673 if (nb < 0 || nb > 1)
674 return UnboundedIntersection;
675
676 return BoundedIntersection;
677}
678
679/*!
680 \fn void QLineF::translate(const QPointF &offset)
681
682 Translates this line by the given \a offset.
683*/
684
685/*!
686 \fn void QLineF::translate(qreal dx, qreal dy)
687 \overload
688
689 Translates this line the distance specified by \a dx and \a dy.
690*/
691
692/*!
693 \fn QLineF QLineF::translated(const QPointF &offset) const
694
695 \since 4.4
696
697 Returns this line translated by the given \a offset.
698*/
699
700/*!
701 \fn QLineF QLineF::translated(qreal dx, qreal dy) const
702 \overload
703 \since 4.4
704
705 Returns this line translated the distance specified by \a dx and \a dy.
706*/
707
708/*!
709 \fn QPointF QLineF::center() const
710
711 \since 5.8
712
713 Returns the center point of this line. This is equivalent to
714 0.5 * p1() + 0.5 * p2().
715*/
716
717/*!
718 \fn void QLineF::setP1(const QPointF &p1)
719 \since 4.4
720
721 Sets the starting point of this line to \a p1.
722
723 \sa setP2(), p1()
724*/
725
726
727/*!
728 \fn void QLineF::setP2(const QPointF &p2)
729 \since 4.4
730
731 Sets the end point of this line to \a p2.
732
733 \sa setP1(), p2()
734*/
735
736
737/*!
738 \fn void QLineF::setPoints(const QPointF &p1, const QPointF &p2)
739 \since 4.4
740
741 Sets the start point of this line to \a p1 and the end point of this line to \a p2.
742
743 \sa setP1(), setP2(), p1(), p2()
744*/
745
746
747/*!
748 \fn void QLineF::setLine(qreal x1, qreal y1, qreal x2, qreal y2)
749 \since 4.4
750
751 Sets this line to the start in \a x1, \a y1 and end in \a x2, \a y2.
752
753 \sa setP1(), setP2(), p1(), p2()
754*/
755
756/*!
757 \fn qreal QLineF::angleTo(const QLineF &line) const
758
759 \since 4.4
760
761 Returns the angle (in degrees) from this line to the given \a
762 line, taking the direction of the lines into account. If the lines
763 do not \l{intersects()}{intersect} within their range, it is the
764 intersection point of the extended lines that serves as origin (see
765 QLineF::UnboundedIntersection).
766
767 The returned value represents the number of degrees you need to add
768 to this line to make it have the same angle as the given \a line,
769 going counter-clockwise.
770
771 \sa intersects()
772*/
773qreal QLineF::angleTo(const QLineF &l) const
774{
775 if (isNull() || l.isNull())
776 return 0;
777
778 const qreal a1 = angle();
779 const qreal a2 = l.angle();
780
781 const qreal delta = a2 - a1;
782 const qreal delta_normalized = delta < 0 ? delta + 360 : delta;
783
784 if (qFuzzyCompare(p1: delta, p2: qreal(360)))
785 return 0;
786 else
787 return delta_normalized;
788}
789
790/*!
791 \fn bool QLineF::qFuzzyCompare(const QLineF &lhs, const QLineF &rhs)
792 \since 6.8
793
794 Returns \c true if line \a lhs is approximately equal to line \a rhs;
795 otherwise returns \c false.
796
797 The lines are considered approximately equal if their start and end
798 points are approximately equal.
799*/
800
801/*!
802 \fn bool QLineF::qFuzzyIsNull(const QLineF &line)
803 \since 6.8
804
805 Returns \c true if the start point of line \a line is approximately
806 equal to its end point; otherwise returns \c false.
807*/
808
809#ifndef QT_NO_DEBUG_STREAM
810QDebug operator<<(QDebug dbg, const QLineF &p)
811{
812 QDebugStateSaver saver(dbg);
813 dbg.nospace() << "QLineF(" << p.p1() << ',' << p.p2() << ')';
814 return dbg;
815}
816#endif
817
818#ifndef QT_NO_DATASTREAM
819/*!
820 \relates QLineF
821
822 Writes the given \a line to the given \a stream and returns a
823 reference to the stream.
824
825 \sa {Serializing Qt Data Types}
826*/
827
828QDataStream &operator<<(QDataStream &stream, const QLineF &line)
829{
830 stream << line.p1() << line.p2();
831 return stream;
832}
833
834/*!
835 \relates QLineF
836
837 Reads a line from the given \a stream into the given \a line and
838 returns a reference to the stream.
839
840 \sa {Serializing Qt Data Types}
841*/
842
843QDataStream &operator>>(QDataStream &stream, QLineF &line)
844{
845 QPointF start, end;
846 stream >> start;
847 stream >> end;
848 line = QLineF(start, end);
849
850 return stream;
851}
852
853#endif // QT_NO_DATASTREAM
854
855QT_END_NAMESPACE
856

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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