source: trunk/src/corelib/tools/qline.cpp@ 659

Last change on this file since 659 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 20.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
48QT_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
261QDebug 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 {Format of the QDataStream Operators}
276*/
277
278QDataStream &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 {Format of the QDataStream Operators}
291*/
292
293QDataStream &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
306#ifndef M_2PI
307#define M_2PI 6.28318530717958647692528676655900576
308#endif
309
310/*!
311 \class QLineF
312 \ingroup painting
313
314 \brief The QLineF class provides a two-dimensional vector using
315 floating point precision.
316
317 A QLineF describes a finite length line (or line segment) on a
318 two-dimensional surface. QLineF defines the start and end points
319 of the line using floating point accuracy for coordinates. Use
320 the toLine() function to retrieve an integer based copy of this
321 line.
322
323 \table
324 \row
325 \o \inlineimage qline-point.png
326 \o \inlineimage qline-coordinates.png
327 \endtable
328
329 The positions of the line's start and end points can be retrieved
330 using the p1(), x1(), y1(), p2(), x2(), and y2() functions. The
331 dx() and dy() functions return the horizontal and vertical
332 components of the line, respectively.
333
334 The line's length can be retrieved using the length() function,
335 and altered using the setLength() function. Similarly, angle()
336 and setAngle() are respectively used for retrieving and altering
337 the angle of the line. Use the isNull()
338 function to determine whether the QLineF represents a valid line
339 or a null line.
340
341 The intersect() function determines the IntersectType for this
342 line and a given line, while the angle() function returns the
343 angle between the lines. In addition, the unitVector() function
344 returns a line that has the same starting point as this line, but
345 with a length of only 1, while the normalVector() function returns
346 a line that is perpendicular to this line with the same starting
347 point and length.
348
349 Finally, the line can be translated a given offset using the
350 translate() function, and can be traversed using the pointAt()
351 function.
352
353 \sa QLine, QPolygonF, QRectF
354*/
355
356/*!
357 \enum QLineF::IntersectType
358
359 Describes the intersection between two lines.
360
361 \table
362 \row
363 \o \inlineimage qlinef-unbounded.png
364 \o \inlineimage qlinef-bounded.png
365 \row
366 \o QLineF::UnboundedIntersection
367 \o QLineF::BoundedIntersection
368 \endtable
369
370 \value NoIntersection Indicates that the lines do not intersect;
371 i.e. they are parallel.
372
373 \value UnboundedIntersection The two lines intersect, but not
374 within the range defined by their lengths. This will be the case
375 if the lines are not parallel.
376
377 intersect() will also return this value if the intersect point is
378 within the start and end point of only one of the lines.
379
380 \value BoundedIntersection The two lines intersect with each other
381 within the start and end points of each line.
382
383 \sa intersect()
384*/
385
386/*!
387 \fn QLineF::QLineF()
388
389 Constructs a null line.
390*/
391
392/*!
393 \fn QLineF::QLineF(const QPointF &p1, const QPointF &p2)
394
395 Constructs a line object that represents the line between \a p1 and
396 \a p2.
397*/
398
399/*!
400 \fn QLineF::QLineF(qreal x1, qreal y1, qreal x2, qreal y2)
401
402 Constructs a line object that represents the line between (\a x1, \a y1) and
403 (\a x2, \a y2).
404*/
405
406/*!
407 \fn QLineF::QLineF(const QLine &line)
408
409 Construct a QLineF object from the given integer-based \a line.
410
411 \sa toLine()
412*/
413
414/*!
415 Returns true if the line is not set up with valid start and end point;
416 otherwise returns false.
417*/
418
419bool QLineF::isNull() const
420{
421 return (qFuzzyCompare(pt1.x(), pt2.x()) && qFuzzyCompare(pt1.y(), pt2.y())) ? true : false;
422}
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()
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 QLineF::setLength(qreal length)
501
502 Sets the length of the line to the given \a length. QLineF will
503 move the end point - p2() - of the line to give the line its new length.
504
505 If the line is a null line, the length will remain zero regardless
506 of the length specified.
507
508 \sa length(), isNull()
509*/
510
511/*!
512 \fn QLineF QLineF::normalVector() const
513
514 Returns a line that is perpendicular to this line with the same starting
515 point and length.
516
517 \image qlinef-normalvector.png
518
519 \sa unitVector()
520*/
521
522/*!
523 \fn bool QLineF::operator!=(const QLineF &line) const
524
525 Returns true if the given \a line is not the same as \e this line.
526
527 A line is different from another line if their start or end points
528 differ, or the internal order of the points is different.
529*/
530
531/*!
532 \fn bool QLineF::operator==(const QLineF &line) const
533
534 Returns true if the given \a line is the same as this line.
535
536 A line is identical to another line if the start and end points
537 are identical, and the internal order of the points is the same.
538*/
539
540/*!
541 \fn qreal QLineF::pointAt(qreal t) const
542
543 Returns the point at the parameterized position specified by \a
544 t. The function returns the line's start point if t = 0, and its end
545 point if t = 1.
546
547 \sa dx(), dy()
548*/
549
550/*!
551 Returns the length of the line.
552
553 \sa setLength()
554*/
555qreal QLineF::length() const
556{
557 qreal x = pt2.x() - pt1.x();
558 qreal y = pt2.y() - pt1.y();
559 return qSqrt(x*x + y*y);
560}
561
562/*!
563 \since 4.4
564
565 Returns the angle of the line in degrees.
566
567 Positive values for the angles mean counter-clockwise while negative values
568 mean the clockwise direction. Zero degrees is at the 3 o'clock position.
569
570 \sa setAngle()
571*/
572qreal QLineF::angle() const
573{
574 const qreal dx = pt2.x() - pt1.x();
575 const qreal dy = pt2.y() - pt1.y();
576
577 const qreal theta = qAtan2(-dy, dx) * 360.0 / M_2PI;
578
579 const qreal theta_normalized = theta < 0 ? theta + 360 : theta;
580
581 if (qFuzzyCompare(theta_normalized, qreal(360)))
582 return qreal(0);
583 else
584 return theta_normalized;
585}
586
587/*!
588 \since 4.4
589
590 Sets the angle of the line to the given \a angle (in degrees).
591 This will change the position of the second point of the line such that
592 the line has the given angle.
593
594 Positive values for the angles mean counter-clockwise while negative values
595 mean the clockwise direction. Zero degrees is at the 3 o'clock position.
596
597 \sa angle()
598*/
599void QLineF::setAngle(qreal angle)
600{
601 const qreal angleR = angle * M_2PI / 360.0;
602 const qreal l = length();
603
604 const qreal dx = qCos(angleR) * l;
605 const qreal dy = -qSin(angleR) * l;
606
607 pt2.rx() = pt1.x() + dx;
608 pt2.ry() = pt1.y() + dy;
609}
610
611/*!
612 \since 4.4
613
614 Returns a QLineF with the given \a length and \a angle.
615
616 The first point of the line will be on the origin.
617
618 Positive values for the angles mean counter-clockwise while negative values
619 mean the clockwise direction. Zero degrees is at the 3 o'clock position.
620*/
621QLineF QLineF::fromPolar(qreal length, qreal angle)
622{
623 const qreal angleR = angle * M_2PI / 360.0;
624 return QLineF(0, 0, qCos(angleR) * length, -qSin(angleR) * length);
625}
626
627/*!
628 Returns the unit vector for this line, i.e a line starting at the
629 same point as \e this line with a length of 1.0.
630
631 \sa normalVector()
632*/
633QLineF QLineF::unitVector() const
634{
635 qreal x = pt2.x() - pt1.x();
636 qreal y = pt2.y() - pt1.y();
637
638 qreal len = qSqrt(x*x + y*y);
639 QLineF f(p1(), QPointF(pt1.x() + x/len, pt1.y() + y/len));
640
641#ifndef QT_NO_DEBUG
642 if (qAbs(f.length() - 1) >= 0.001)
643 qWarning("QLine::unitVector: New line does not have unit length");
644#endif
645
646 return f;
647}
648
649/*!
650 \fn QLineF::IntersectType QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const
651
652 Returns a value indicating whether or not \e this line intersects
653 with the given \a line.
654
655 The actual intersection point is extracted to \a intersectionPoint
656 (if the pointer is valid). If the lines are parallel, the
657 intersection point is undefined.
658*/
659
660QLineF::IntersectType QLineF::intersect(const QLineF &l, QPointF *intersectionPoint) const
661{
662 // ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection"
663 const QPointF a = pt2 - pt1;
664 const QPointF b = l.pt1 - l.pt2;
665 const QPointF c = pt1 - l.pt1;
666
667 const qreal denominator = a.y() * b.x() - a.x() * b.y();
668 if (denominator == 0 || !qt_is_finite(denominator))
669 return NoIntersection;
670
671 const qreal reciprocal = 1 / denominator;
672 const qreal na = (b.y() * c.x() - b.x() * c.y()) * reciprocal;
673 if (intersectionPoint)
674 *intersectionPoint = pt1 + a * na;
675
676 if (na < 0 || na > 1)
677 return UnboundedIntersection;
678
679 const qreal nb = (a.x() * c.y() - a.y() * c.x()) * reciprocal;
680 if (nb < 0 || nb > 1)
681 return UnboundedIntersection;
682
683 return BoundedIntersection;
684}
685
686/*!
687 \fn void QLineF::translate(const QPointF &offset)
688
689 Translates this line by the given \a offset.
690*/
691
692/*!
693 \fn void QLineF::translate(qreal dx, qreal dy)
694 \overload
695
696 Translates this line the distance specified by \a dx and \a dy.
697*/
698
699/*!
700 \fn QLineF QLineF::translated(const QPointF &offset) const
701
702 \since 4.4
703
704 Returns this line translated by the given \a offset.
705*/
706
707/*!
708 \fn QLineF QLineF::translated(qreal dx, qreal dy) const
709 \overload
710 \since 4.4
711
712 Returns this line translated the distance specified by \a dx and \a dy.
713*/
714
715/*!
716 \fn void QLineF::setP1(const QPointF &p1)
717 \since 4.4
718
719 Sets the starting point of this line to \a p1.
720
721 \sa setP2(), p1()
722*/
723
724
725/*!
726 \fn void QLineF::setP2(const QPointF &p2)
727 \since 4.4
728
729 Sets the end point of this line to \a p2.
730
731 \sa setP1(), p2()
732*/
733
734
735/*!
736 \fn void QLineF::setPoints(const QPointF &p1, const QPointF &p2)
737 \since 4.4
738
739 Sets the start point of this line to \a p1 and the end point of this line to \a p2.
740
741 \sa setP1(), setP2(), p1(), p2()
742*/
743
744
745/*!
746 \fn void QLineF::setLine(qreal x1, qreal y1, qreal x2, qreal y2)
747 \since 4.4
748
749 Sets this line to the start in \a x1, \a y1 and end in \a x2, \a y2.
750
751 \sa setP1(), setP2(), p1(), p2()
752*/
753
754/*!
755 \fn qreal QLineF::angleTo(const QLineF &line) const
756
757 \since 4.4
758
759 Returns the angle (in degrees) from this line to the given \a
760 line, taking the direction of the lines into account. If the lines
761 do not intersect within their range, it is the intersection point of
762 the extended lines that serves as origin (see
763 QLineF::UnboundedIntersection).
764
765 The returned value represents the number of degrees you need to add
766 to this line to make it have the same angle as the given \a line,
767 going counter-clockwise.
768
769 \sa intersect()
770*/
771qreal QLineF::angleTo(const QLineF &l) const
772{
773 if (isNull() || l.isNull())
774 return 0;
775
776 const qreal a1 = angle();
777 const qreal a2 = l.angle();
778
779 const qreal delta = a2 - a1;
780 const qreal delta_normalized = delta < 0 ? delta + 360 : delta;
781
782 if (qFuzzyCompare(delta, qreal(360)))
783 return 0;
784 else
785 return delta_normalized;
786}
787
788/*!
789 \fn qreal QLineF::angle(const QLineF &line) const
790
791 \obsolete
792
793 Returns the angle (in degrees) between this line and the given \a
794 line, taking the direction of the lines into account. If the lines
795 do not intersect within their range, it is the intersection point of
796 the extended lines that serves as origin (see
797 QLineF::UnboundedIntersection).
798
799 \table
800 \row
801 \o \inlineimage qlinef-angle-identicaldirection.png
802 \o \inlineimage qlinef-angle-oppositedirection.png
803 \endtable
804
805 When the lines are parallel, this function returns 0 if they have
806 the same direction; otherwise it returns 180.
807
808 \sa intersect()
809*/
810qreal QLineF::angle(const QLineF &l) const
811{
812 if (isNull() || l.isNull())
813 return 0;
814 qreal cos_line = (dx()*l.dx() + dy()*l.dy()) / (length()*l.length());
815 qreal rad = 0;
816 // only accept cos_line in the range [-1,1], if it is outside, use 0 (we return 0 rather than PI for those cases)
817 if (cos_line >= -1.0 && cos_line <= 1.0) rad = qAcos( cos_line );
818 return rad * 360 / M_2PI;
819}
820
821
822#ifndef QT_NO_DEBUG_STREAM
823QDebug operator<<(QDebug d, const QLineF &p)
824{
825 d << "QLineF(" << p.p1() << ',' << p.p2() << ')';
826 return d;
827}
828#endif
829
830#ifndef QT_NO_DATASTREAM
831/*!
832 \relates QLineF
833
834 Writes the given \a line to the given \a stream and returns a
835 reference to the stream.
836
837 \sa {Format of the QDataStream Operators}
838*/
839
840QDataStream &operator<<(QDataStream &stream, const QLineF &line)
841{
842 stream << line.p1() << line.p2();
843 return stream;
844}
845
846/*!
847 \relates QLineF
848
849 Reads a line from the given \a stream into the given \a line and
850 returns a reference to the stream.
851
852 \sa {Format of the QDataStream Operators}
853*/
854
855QDataStream &operator>>(QDataStream &stream, QLineF &line)
856{
857 QPointF start, end;
858 stream >> start;
859 stream >> end;
860 line = QLineF(start, end);
861
862 return stream;
863}
864
865#endif // QT_NO_DATASTREAM
866
867QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.