~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/corelib/tools/qline.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the core module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qline.h"
 
30
#include "qdebug.h"
 
31
#include "qdatastream.h"
 
32
#include <private/qnumeric_p.h>
 
33
 
 
34
#include <math.h>
 
35
 
 
36
/*!
 
37
    \class QLine
 
38
 
 
39
    \brief The QLine class provides a two-dimensional vector that
 
40
    uses integer point accuracy for coordinates.
 
41
 
 
42
    A QLine describes a finite length line (or line segment) on a two-dimensional surface.
 
43
    The start and end points of the line are specified using integer point
 
44
    coordinates.
 
45
 
 
46
    Use isNull() to determine whether the QLine represents a valid line
 
47
    or a null line.
 
48
 
 
49
    The positions of the line's end points can be found with the p1(),
 
50
    x1(), y1(), p2(), x2(), and y2() functions. The horizontal and vertical
 
51
    components of the line are returned by the dx() and dy() functions.
 
52
 
 
53
    The line can be translated along the length of another line with the
 
54
    translate() function.
 
55
 
 
56
    \sa QPoint QSize QRect QLineF
 
57
*/
 
58
 
 
59
/*!
 
60
    \fn QLine::QLine()
 
61
 
 
62
    Constructs a null line.
 
63
*/
 
64
 
 
65
/*!
 
66
    \fn QLine::QLine(const QPoint &pt1, const QPoint &pt2)
 
67
 
 
68
    Constructs a line object that represents the line between \a pt1 and
 
69
    \a pt2.
 
70
*/
 
71
 
 
72
/*!
 
73
    \fn QLine::QLine(int x1, int y1, int x2, int y2)
 
74
 
 
75
    Constructs a line object that represents the line between (\a x1, \a y1) and
 
76
    (\a x2, \a y2).
 
77
*/
 
78
 
 
79
/*!
 
80
    \fn bool QLine::isNull() const
 
81
 
 
82
    Returns true if the line is not set up with valid start and end point;
 
83
    otherwise returns false.
 
84
*/
 
85
 
 
86
/*!
 
87
    \fn QPoint QLine::p1() const
 
88
 
 
89
    Returns the line's start point.
 
90
 
 
91
    \sa x1() y1() p2()
 
92
*/
 
93
 
 
94
/*!
 
95
    \fn QPoint QLine::p2() const
 
96
 
 
97
    Returns the line's end point.
 
98
 
 
99
    \sa x2() y2() p1()
 
100
*/
 
101
 
 
102
/*!
 
103
    \fn int QLine::x1() const
 
104
 
 
105
    Returns the x-coordinate of the line's start point.
 
106
 
 
107
    \sa y1() x2() p1()
 
108
*/
 
109
 
 
110
/*!
 
111
    \fn int QLine::y1() const
 
112
 
 
113
    Returns the y-coordinate of the line's start point.
 
114
 
 
115
    \sa x1() y2() p1()
 
116
*/
 
117
 
 
118
/*!
 
119
    \fn int QLine::x2() const
 
120
 
 
121
    Returns the x-coordinate of the line's end point.
 
122
 
 
123
    \sa y2() x1() p2()
 
124
*/
 
125
 
 
126
/*!
 
127
    \fn int QLine::y2() const
 
128
 
 
129
    Returns the y-coordinate of the line's end point.
 
130
 
 
131
    \sa x2() y1() p2()
 
132
*/
 
133
 
 
134
/*!
 
135
    \fn int QLine::dx() const
 
136
 
 
137
    Returns the horizontal component of the line's vector.
 
138
 
 
139
    \sa dy()
 
140
*/
 
141
 
 
142
/*!
 
143
    \fn int QLine::dy() const
 
144
 
 
145
    Returns the vertical component of the line's vector.
 
146
 
 
147
    \sa dx()
 
148
*/
 
149
 
 
150
/*!
 
151
    \fn bool QLine::operator!=(const QLine &other) const
 
152
 
 
153
    Returns true if \a other is not the same as this line.
 
154
 
 
155
    A line is different from another line if any of their points are
 
156
    different or their order is different.
 
157
*/
 
158
 
 
159
/*!
 
160
    \fn bool QLine::operator==(const QLine &other) const
 
161
 
 
162
    Returns true if \a other is the same line as this line.
 
163
 
 
164
    A line is identical to another line if the points are the same and their
 
165
    order is the same.
 
166
*/
 
167
 
 
168
/*!
 
169
    \fn void QLine::translate(const QPoint &point)
 
170
 
 
171
    Translates this line with the \a point given.
 
172
*/
 
173
 
 
174
/*!
 
175
    \fn void QLine::translate(int dx, int dy)
 
176
 
 
177
    \overload
 
178
 
 
179
    Translates this line the distance \a dx and \a dy.
 
180
*/
 
181
 
 
182
#ifndef QT_NO_DEBUG_STREAM
 
183
QDebug operator<<(QDebug d, const QLine &p)
 
184
{
 
185
    d << "QLine(" << p.p1() << "," << p.p2() << ")";
 
186
    return d;
 
187
}
 
188
#endif
 
189
 
 
190
#ifndef QT_NO_DATASTREAM
 
191
/*!
 
192
    \relates QLine
 
193
 
 
194
    Writes the \a line to the \a stream and returns a reference to
 
195
    the stream.
 
196
 
 
197
    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
 
198
*/
 
199
 
 
200
QDataStream &operator<<(QDataStream &stream, const QLine &line)
 
201
{
 
202
    stream << line.p1() << line.p2();
 
203
    return stream;
 
204
}
 
205
 
 
206
/*!
 
207
    \relates QLine
 
208
 
 
209
    Reads a QLine from the \a stream into the \a line and returns a
 
210
    reference to the stream.
 
211
 
 
212
    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
 
213
*/
 
214
 
 
215
QDataStream &operator>>(QDataStream &stream, QLine &line)
 
216
{
 
217
    QPoint p1, p2;
 
218
    stream >> p1;
 
219
    stream >> p2;
 
220
    line = QLine(p1, p2);
 
221
 
 
222
    return stream;
 
223
}
 
224
 
 
225
#endif // QT_NO_DATASTREAM
 
226
 
 
227
 
 
228
#ifndef M_2PI
 
229
#define M_2PI 6.28318530717958647692528676655900576
 
230
#endif
 
231
 
 
232
/*!
 
233
    \class QLineF
 
234
 
 
235
    \brief The QLineF class provides a two-dimensional vector that
 
236
    uses floating point accuracy for coordinates.
 
237
 
 
238
    A QLineF describes a finite length line (or line segment) on a two-dimensional surface.
 
239
    The start and end points of the line are specified using floating point
 
240
    coordinates.
 
241
 
 
242
    Use isNull() to determine whether the QLineF represents a valid line
 
243
    or a null line.
 
244
 
 
245
    The positions of the line's end points can be found with the p1(), x1(),
 
246
    y1(), p2(), x2(), and y2() functions. The horizontal and vertical
 
247
    components of the line are returned by the dx() and dy() functions.
 
248
 
 
249
    Convenience functions are provided for finding the lines's length(),
 
250
    the unitVector() along the line, whether two lines intersect(), and
 
251
    the angle() between two lines. The line's length can be changed using
 
252
    setLength().
 
253
 
 
254
    The line can be translated along the length of another line with the
 
255
    moveBy() function, and can be traversed using a parameter with the
 
256
    pointAt() function.
 
257
 
 
258
    \sa QPointF QSizeF QRectF QLine
 
259
*/
 
260
 
 
261
/*!
 
262
    \enum QLineF::IntersectType
 
263
 
 
264
    \value NoIntersection Indicates that the lines do not intersect;
 
265
    i.e. they are parallel.
 
266
 
 
267
    \value UnboundedIntersection The two lines intersect,
 
268
    but not within the range defined by their lengths. This will be
 
269
    the case if the lines are not parallel.
 
270
 
 
271
    \img qlinef-unbounded.png
 
272
 
 
273
    \value BoundedIntersection The two lines intersect with each other
 
274
    within the start and end points of each line.
 
275
 
 
276
    \img qlinef-bounded.png
 
277
 
 
278
*/
 
279
 
 
280
/*!
 
281
    \fn QLineF::QLineF()
 
282
 
 
283
    Constructs a null line.
 
284
*/
 
285
 
 
286
/*!
 
287
    \fn QLineF::QLineF(const QPointF &pt1, const QPointF &pt2)
 
288
 
 
289
    Constructs a line object that represents the line between \a pt1 and
 
290
    \a pt2.
 
291
*/
 
292
 
 
293
/*!
 
294
    \fn QLineF::QLineF(qreal x1, qreal y1, qreal x2, qreal y2)
 
295
 
 
296
    Constructs a line object that represents the line between (\a x1, \a y1) and
 
297
    (\a x2, \a y2).
 
298
*/
 
299
 
 
300
/*!
 
301
    \fn QLineF::QLineF(const QLine &line)
 
302
 
 
303
    Construct a QLineF from a integer-based QLine \a line.
 
304
*/
 
305
 
 
306
/*!
 
307
    Returns true if the line is not set up with valid start and end point;
 
308
    otherwise returns false.
 
309
*/
 
310
 
 
311
bool QLineF::isNull() const
 
312
{
 
313
    return (qFuzzyCompare(pt1.x(), pt2.x()) && qFuzzyCompare(pt1.y(), pt2.y())) ? true : false;
 
314
}
 
315
 
 
316
 
 
317
/*!
 
318
    \fn QPointF QLineF::p1() const
 
319
 
 
320
    Returns the line's start point.
 
321
 
 
322
    \sa x1() y1() p2()
 
323
*/
 
324
 
 
325
/*!
 
326
    \fn QPointF QLineF::p2() const
 
327
 
 
328
    Returns the line's end point.
 
329
 
 
330
    \sa x2() y2() p1()
 
331
*/
 
332
 
 
333
/*!
 
334
    \fn QLine QLineF::toLine() const
 
335
 
 
336
    Returns a QLine. The returned QLine's starting and end points are rounded to
 
337
    the nearest integer.
 
338
 
 
339
*/
 
340
/*!
 
341
    \fn qreal QLineF::x1() const
 
342
 
 
343
    Returns the x-coordinate of the line's start point.
 
344
 
 
345
    \sa y1() p1() x2()
 
346
*/
 
347
 
 
348
/*!
 
349
    \fn qreal QLineF::y1() const
 
350
 
 
351
    Returns the y-coordinate of the line's start point.
 
352
 
 
353
    \sa x1() p1() x2()
 
354
*/
 
355
 
 
356
/*!
 
357
    \fn qreal QLineF::x2() const
 
358
 
 
359
    Returns the x-coordinate of the line's end point.
 
360
 
 
361
    \sa y2() p2() x1()
 
362
*/
 
363
 
 
364
/*!
 
365
    \fn qreal QLineF::y2() const
 
366
 
 
367
    Returns the y-coordinate of the line's end point.
 
368
 
 
369
    \sa x2() p2() y1()
 
370
*/
 
371
 
 
372
/*!
 
373
    \fn qreal QLineF::dx() const
 
374
 
 
375
    Returns the horizontal component of the line's vector.
 
376
 
 
377
    \sa dy() pointAt()
 
378
*/
 
379
 
 
380
/*!
 
381
    \fn qreal QLineF::dy() const
 
382
 
 
383
    Returns the vertical component of the line's vector.
 
384
 
 
385
    \sa dx() pointAt()
 
386
*/
 
387
 
 
388
/*!
 
389
    \fn QLineF::setLength(qreal length)
 
390
 
 
391
    Sets the \a length of the line.
 
392
 
 
393
    \sa length()
 
394
*/
 
395
 
 
396
/*!
 
397
    \fn QLineF QLineF::normalVector() const
 
398
 
 
399
    Returns a line that is perpendicular to this line with the same starting
 
400
    point and length.
 
401
 
 
402
    \sa unitVector()
 
403
 
 
404
    \img qlinef-normalvector.png
 
405
*/
 
406
 
 
407
/*!
 
408
    \fn bool QLineF::operator!=(const QLineF &other) const
 
409
 
 
410
    Returns true if \a other is not the same as this line.
 
411
 
 
412
    A line is different from another line if any of their points are
 
413
    different or their order is different.
 
414
*/
 
415
 
 
416
/*!
 
417
    \fn bool QLineF::operator==(const QLineF &other) const
 
418
 
 
419
    Returns true if \a other is the same line as this line.
 
420
 
 
421
    A line is identical if the two points are the same and their
 
422
    order is the same.
 
423
*/
 
424
 
 
425
/*!
 
426
  \fn qreal QLineF::pointAt(qreal t) const
 
427
 
 
428
  Returns the point at the parameterized position \a t, where
 
429
  the start and end point are defined to be at positions t=0 and t=1.
 
430
 
 
431
  \sa dx() dy()
 
432
*/
 
433
 
 
434
/*!
 
435
    Returns the length of the line.
 
436
 
 
437
    \sa setLength()
 
438
*/
 
439
qreal QLineF::length() const
 
440
{
 
441
    qreal x = pt2.x() - pt1.x();
 
442
    qreal y = pt2.y() - pt1.y();
 
443
    return sqrt(x*x + y*y);
 
444
}
 
445
 
 
446
 
 
447
/*!
 
448
    Returns a normalized version of this line, starting at the same
 
449
    point as this line. A normalized line is a line of unit length
 
450
    (length() is equal to 1.0).
 
451
 
 
452
    \sa normalVector()
 
453
*/
 
454
QLineF QLineF::unitVector() const
 
455
{
 
456
    qreal x = pt2.x() - pt1.x();
 
457
    qreal y = pt2.y() - pt1.y();
 
458
 
 
459
    qreal len = sqrt(x*x + y*y);
 
460
    QLineF f(p1(), QPointF(pt1.x() + x/len, pt1.y() + y/len));
 
461
 
 
462
#ifndef QT_NO_DEBUG
 
463
    if (qAbs(f.length() - 1) >= 0.001)
 
464
        qWarning("QLine::unitVector(), new line does not have length of 1");
 
465
#endif
 
466
 
 
467
    return f;
 
468
}
 
469
 
 
470
#define SAME_SIGNS(a, b) ((a) * (b) >= 0)
 
471
 
 
472
// Line intersection algorithm, copied from Graphics Gems II
 
473
static bool qt_linef_intersect(qreal x1, qreal y1, qreal x2, qreal y2,
 
474
                               qreal x3, qreal y3, qreal x4, qreal y4)
 
475
{
 
476
    qreal a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns. */
 
477
    qreal r1, r2, r3, r4;         /* 'Sign' values */
 
478
 
 
479
    a1 = y2 - y1;
 
480
    b1 = x1 - x2;
 
481
    c1 = x2 * y1 - x1 * y2;
 
482
 
 
483
    r3 = a1 * x3 + b1 * y3 + c1;
 
484
    r4 = a1 * x4 + b1 * y4 + c1;
 
485
 
 
486
    if ( r3 != 0 && r4 != 0 && SAME_SIGNS( r3, r4 ))
 
487
        return false;
 
488
 
 
489
    a2 = y4 - y3;
 
490
    b2 = x3 - x4;
 
491
    c2 = x4 * y3 - x3 * y4;
 
492
 
 
493
    r1 = a2 * x1 + b2 * y1 + c2;
 
494
    r2 = a2 * x2 + b2 * y2 + c2;
 
495
 
 
496
    if ( r1 != 0 && r2 != 0 && SAME_SIGNS( r1, r2 ))
 
497
        return false;
 
498
 
 
499
    return true;
 
500
}
 
501
 
 
502
/*!
 
503
    \fn QLineF::IntersectType QLineF::intersect(const QLineF &other, QPointF *intersectionPoint) const
 
504
 
 
505
    Returns a value indicating whether or not this line intersects the
 
506
    \a other line. By passing a valid pointer as \a intersectionPoint, it
 
507
    is possible to get the actual intersection point. The intersection
 
508
    point is undefined if the lines are parallel.
 
509
*/
 
510
 
 
511
QLineF::IntersectType QLineF::intersect(const QLineF &l, QPointF *intersectionPoint) const
 
512
{
 
513
    if (isNull() || l.isNull()
 
514
        || !qIsFinite(pt1.x()) || !qIsFinite(pt1.y()) || !qIsFinite(pt2.x()) || !qIsFinite(pt2.y())
 
515
        || !qIsFinite(l.pt1.x()) || !qIsFinite(l.pt1.y()) || !qIsFinite(l.pt2.x()) || !qIsFinite(l.pt2.y()))
 
516
        return NoIntersection;
 
517
 
 
518
    QPointF isect;
 
519
    IntersectType type = qt_linef_intersect(pt1.x(), pt1.y(), pt2.x(), pt2.y(),
 
520
                                            l.x1(), l.y1(), l.x2(), l.y2())
 
521
                         ? BoundedIntersection : UnboundedIntersection;
 
522
 
 
523
    // For special case where one of the lines are vertical
 
524
    if (dx() == 0 && l.dx() == 0) {
 
525
        type = NoIntersection;
 
526
    } else if (dx() == 0) {
 
527
        qreal la = l.dy() / l.dx();
 
528
        isect = QPointF(pt1.x(), la * pt1.x() + l.y1() - la*l.x1());
 
529
    } else if (l.dx() == 0) {
 
530
        qreal ta = dy() / dx();
 
531
        isect = QPointF(l.x1(), ta * l.x1() + y1() - ta*x1());
 
532
    } else {
 
533
        qreal ta = dy()/dx();
 
534
        qreal la = l.dy()/l.dx();
 
535
        if (ta == la) // no intersection
 
536
            return NoIntersection;
 
537
 
 
538
        qreal x = ( - l.y1() + la * l.x1() + pt1.y() - ta * pt1.x() ) / (la - ta);
 
539
        isect = QPointF(x, ta*(x - pt1.x()) + pt1.y());
 
540
    }
 
541
    if (intersectionPoint)
 
542
        *intersectionPoint = isect;
 
543
    return type;
 
544
}
 
545
 
 
546
/*!
 
547
    \fn void QLineF::translate(const QPointF &point)
 
548
 
 
549
    Translates this line with the \a point given.
 
550
*/
 
551
 
 
552
/*!
 
553
    \fn void QLineF::translate(qreal dx, qreal dy)
 
554
 
 
555
    \overload
 
556
 
 
557
    Translates this line the distance \a dx and \a dy.
 
558
*/
 
559
 
 
560
/*!
 
561
  \fn qreal QLineF::angle(const QLineF &line) const
 
562
 
 
563
  Returns the smallest angle between the given \a line and this line, not
 
564
  taking into account whether the lines intersect or not. The angle is
 
565
  specified in degrees.
 
566
 
 
567
  \sa intersect()
 
568
*/
 
569
qreal QLineF::angle(const QLineF &l) const
 
570
{
 
571
    if (isNull() || l.isNull())
 
572
        return 0;
 
573
    qreal rad = acos( (dx()*l.dx() + dy()*l.dy()) / (length()*l.length()) );
 
574
    return rad * 360 / M_2PI;
 
575
}
 
576
 
 
577
 
 
578
#ifndef QT_NO_DEBUG_STREAM
 
579
QDebug operator<<(QDebug d, const QLineF &p)
 
580
{
 
581
    d << "QLineF(" << p.p1() << "," << p.p2() << ")";
 
582
    return d;
 
583
}
 
584
#endif
 
585
 
 
586
#ifndef QT_NO_DATASTREAM
 
587
/*!
 
588
    \relates QLineF
 
589
 
 
590
    Writes the \a line to the \a stream and returns a reference to
 
591
    the stream.
 
592
 
 
593
    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
 
594
*/
 
595
 
 
596
QDataStream &operator<<(QDataStream &stream, const QLineF &line)
 
597
{
 
598
    stream << line.p1() << line.p2();
 
599
    return stream;
 
600
}
 
601
 
 
602
/*!
 
603
    \relates QLineF
 
604
 
 
605
    Reads a QLineF from the \a stream into the \a line and returns a
 
606
    reference to the stream.
 
607
 
 
608
    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
 
609
*/
 
610
 
 
611
QDataStream &operator>>(QDataStream &stream, QLineF &line)
 
612
{
 
613
    QPointF start, end;
 
614
    stream >> start;
 
615
    stream >> end;
 
616
    line = QLineF(start, end);
 
617
 
 
618
    return stream;
 
619
}
 
620
 
 
621
#endif // QT_NO_DATASTREAM