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