1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30#include <qline.h>
31#include <math.h>
32
33#ifndef M_2PI
34#define M_2PI 6.28318530717958647692528676655900576
35#endif
36
37class tst_QLine : public QObject
38{
39 Q_OBJECT
40private slots:
41 void testIntersection();
42 void testIntersection_data();
43
44 void testLength();
45 void testLength_data();
46
47 void testCenter();
48 void testCenter_data();
49
50 void testCenterF();
51 void testCenterF_data();
52
53 void testNormalVector();
54 void testNormalVector_data();
55
56#if QT_DEPRECATED_SINCE(5, 14)
57 void testAngle();
58 void testAngle_data();
59#endif
60
61 void testAngle2();
62 void testAngle2_data();
63
64 void testAngle3();
65
66 void testAngleTo();
67 void testAngleTo_data();
68
69 void testSet();
70};
71
72// Square root of two
73#define SQRT2 1.4142135623731
74
75// Length of unit vector projected to x from 45 degrees
76#define UNITX_45 0.707106781186547
77
78const qreal epsilon = sizeof(qreal) == sizeof(double) ? 1e-8 : 1e-4;
79
80void tst_QLine::testSet()
81{
82 {
83 QLine l;
84 l.setP1(QPoint(1, 2));
85 l.setP2(QPoint(3, 4));
86
87 QCOMPARE(l.x1(), 1);
88 QCOMPARE(l.y1(), 2);
89 QCOMPARE(l.x2(), 3);
90 QCOMPARE(l.y2(), 4);
91
92 l.setPoints(aP1: QPoint(5, 6), aP2: QPoint(7, 8));
93 QCOMPARE(l.x1(), 5);
94 QCOMPARE(l.y1(), 6);
95 QCOMPARE(l.x2(), 7);
96 QCOMPARE(l.y2(), 8);
97
98 l.setLine(aX1: 9, aY1: 10, aX2: 11, aY2: 12);
99 QCOMPARE(l.x1(), 9);
100 QCOMPARE(l.y1(), 10);
101 QCOMPARE(l.x2(), 11);
102 QCOMPARE(l.y2(), 12);
103 }
104
105 {
106 QLineF l;
107 l.setP1(QPointF(1, 2));
108 l.setP2(QPointF(3, 4));
109
110 QCOMPARE(l.x1(), 1.0);
111 QCOMPARE(l.y1(), 2.0);
112 QCOMPARE(l.x2(), 3.0);
113 QCOMPARE(l.y2(), 4.0);
114
115 l.setPoints(aP1: QPointF(5, 6), aP2: QPointF(7, 8));
116 QCOMPARE(l.x1(), 5.0);
117 QCOMPARE(l.y1(), 6.0);
118 QCOMPARE(l.x2(), 7.0);
119 QCOMPARE(l.y2(), 8.0);
120
121 l.setLine(aX1: 9.0, aY1: 10.0, aX2: 11.0, aY2: 12.0);
122 QCOMPARE(l.x1(), 9.0);
123 QCOMPARE(l.y1(), 10.0);
124 QCOMPARE(l.x2(), 11.0);
125 QCOMPARE(l.y2(), 12.0);
126 }
127
128}
129
130void tst_QLine::testIntersection_data()
131{
132 QTest::addColumn<double>(name: "xa1");
133 QTest::addColumn<double>(name: "ya1");
134 QTest::addColumn<double>(name: "xa2");
135 QTest::addColumn<double>(name: "ya2");
136 QTest::addColumn<double>(name: "xb1");
137 QTest::addColumn<double>(name: "yb1");
138 QTest::addColumn<double>(name: "xb2");
139 QTest::addColumn<double>(name: "yb2");
140 QTest::addColumn<int>(name: "type");
141 QTest::addColumn<double>(name: "ix");
142 QTest::addColumn<double>(name: "iy");
143
144 QTest::newRow(dataTag: "parallel") << 1.0 << 1.0 << 3.0 << 4.0
145 << 5.0 << 6.0 << 7.0 << 9.0
146 << int(QLineF::NoIntersection) << 0.0 << 0.0;
147 QTest::newRow(dataTag: "unbounded") << 1.0 << 1.0 << 5.0 << 5.0
148 << 0.0 << 4.0 << 3.0 << 4.0
149 << int(QLineF::UnboundedIntersection) << 4.0 << 4.0;
150 QTest::newRow(dataTag: "bounded") << 1.0 << 1.0 << 5.0 << 5.0
151 << 0.0 << 4.0 << 5.0 << 4.0
152 << int(QLineF::BoundedIntersection) << 4.0 << 4.0;
153
154 QTest::newRow(dataTag: "almost vertical") << 0.0 << 10.0 << 20.0000000000001 << 10.0
155 << 10.0 << 0.0 << 10.0 << 20.0
156 << int(QLineF::BoundedIntersection) << 10.0 << 10.0;
157
158 QTest::newRow(dataTag: "almost horizontal") << 0.0 << 10.0 << 20.0 << 10.0
159 << 10.0000000000001 << 0.0 << 10.0 << 20.0
160 << int(QLineF::BoundedIntersection) << 10.0 << 10.0;
161
162 QTest::newRow(dataTag: "long vertical") << 100.1599256468623
163 << 100.7861905065196
164 << 100.1599256468604
165 << -9999.78619050651
166 << 10.0 << 50.0 << 190.0 << 50.0
167 << int(QLineF::BoundedIntersection)
168 << 100.1599256468622
169 << 50.0;
170
171 for (int i = 0; i < 1000; ++i) {
172 QLineF a = QLineF::fromPolar(length: 50, angle: i);
173 a.setP1(-a.p2());
174
175 QLineF b = QLineF::fromPolar(length: 50, angle: i * 0.997 + 90);
176 b.setP1(-b.p2());
177
178 // make the qFuzzyCompare be a bit more lenient
179 a = a.translated(adx: 1, ady: 1);
180 b = b.translated(adx: 1, ady: 1);
181
182 QTest::newRow(dataTag: ("rotation-" + QByteArray::number(i)).constData())
183 << (double)a.x1() << (double)a.y1() << (double)a.x2() << (double)a.y2()
184 << (double)b.x1() << (double)b.y1() << (double)b.x2() << (double)b.y2()
185 << int(QLineF::BoundedIntersection)
186 << 1.0
187 << 1.0;
188 }
189}
190
191void tst_QLine::testIntersection()
192{
193 QFETCH(double, xa1);
194 QFETCH(double, ya1);
195 QFETCH(double, xa2);
196 QFETCH(double, ya2);
197 QFETCH(double, xb1);
198 QFETCH(double, yb1);
199 QFETCH(double, xb2);
200 QFETCH(double, yb2);
201 QFETCH(int, type);
202 QFETCH(double, ix);
203 QFETCH(double, iy);
204
205 QLineF a(xa1, ya1, xa2, ya2);
206 QLineF b(xb1, yb1, xb2, yb2);
207
208
209 QPointF ip;
210 QLineF::IntersectionType itype = a.intersects(l: b, intersectionPoint: &ip);
211#if QT_DEPRECATED_SINCE(5, 14)
212 QCOMPARE(a.intersect(b, &ip), itype);
213#endif
214
215 QCOMPARE(int(itype), type);
216 if (type != QLineF::NoIntersection) {
217 QVERIFY(qAbs(ip.x() - ix) < epsilon);
218 QVERIFY(qAbs(ip.y() - iy) < epsilon);
219 }
220}
221
222void tst_QLine::testLength_data()
223{
224 QTest::addColumn<double>(name: "x1");
225 QTest::addColumn<double>(name: "y1");
226 QTest::addColumn<double>(name: "x2");
227 QTest::addColumn<double>(name: "y2");
228 QTest::addColumn<double>(name: "length");
229 QTest::addColumn<double>(name: "lengthToSet");
230 QTest::addColumn<double>(name: "vx");
231 QTest::addColumn<double>(name: "vy");
232
233 // Test name: [dx,dy]->|lenToSet| (x1,x2)
234 // with the last part omitted if (0,0)
235 QTest::newRow(dataTag: "[1,0]->|2|") << 0.0 << 0.0 << 1.0 << 0.0 << 1.0 << 2.0 << 2.0 << 0.0;
236 QTest::newRow(dataTag: "[0,1]->|2|") << 0.0 << 0.0 << 0.0 << 1.0 << 1.0 << 2.0 << 0.0 << 2.0;
237 QTest::newRow(dataTag: "[-1,0]->|2|") << 0.0 << 0.0 << -1.0 << 0.0 << 1.0 << 2.0 << -2.0 << 0.0;
238 QTest::newRow(dataTag: "[0,-1]->|2|") << 0.0 << 0.0 << 0.0 << -1.0 << 1.0 << 2.0 << 0.0 << -2.0;
239 QTest::newRow(dataTag: "[1,1]->|1|") << 0.0 << 0.0 << 1.0 << 1.0
240 << double(SQRT2) << 1.0 << double(UNITX_45) << double(UNITX_45);
241 QTest::newRow(dataTag: "[-1,1]->|1|") << 0.0 << 0.0 << -1.0 << 1.0
242 << double(SQRT2) << 1.0 << double(-UNITX_45) << double(UNITX_45);
243 QTest::newRow(dataTag: "[1,-1]->|1|") << 0.0 << 0.0 << 1.0 << -1.0
244 << double(SQRT2) << 1.0 << double(UNITX_45) << double(-UNITX_45);
245 QTest::newRow(dataTag: "[-1,-1]->|1|") << 0.0 << 0.0 << -1.0 << -1.0
246 << double(SQRT2) << 1.0 << double(-UNITX_45) << double(-UNITX_45);
247 QTest::newRow(dataTag: "[1,0]->|2| (2,2)") << 2.0 << 2.0 << 3.0 << 2.0 << 1.0 << 2.0 << 2.0 << 0.0;
248 QTest::newRow(dataTag: "[0,1]->|2| (2,2)") << 2.0 << 2.0 << 2.0 << 3.0 << 1.0 << 2.0 << 0.0 << 2.0;
249 QTest::newRow(dataTag: "[-1,0]->|2| (2,2)") << 2.0 << 2.0 << 1.0 << 2.0 << 1.0 << 2.0 << -2.0 << 0.0;
250 QTest::newRow(dataTag: "[0,-1]->|2| (2,2)") << 2.0 << 2.0 << 2.0 << 1.0 << 1.0 << 2.0 << 0.0 << -2.0;
251 QTest::newRow(dataTag: "[1,1]->|1| (2,2)") << 2.0 << 2.0 << 3.0 << 3.0
252 << double(SQRT2) << 1.0 << double(UNITX_45) << double(UNITX_45);
253 QTest::newRow(dataTag: "[-1,1]->|1| (2,2)") << 2.0 << 2.0 << 1.0 << 3.0
254 << double(SQRT2) << 1.0 << double(-UNITX_45) << double(UNITX_45);
255 QTest::newRow(dataTag: "[1,-1]->|1| (2,2)") << 2.0 << 2.0 << 3.0 << 1.0
256 << double(SQRT2) << 1.0 << double(UNITX_45) << double(-UNITX_45);
257 QTest::newRow(dataTag: "[-1,-1]->|1| (2,2)") << 2.0 << 2.0 << 1.0 << 1.0
258 << double(SQRT2) << 1.0 << double(-UNITX_45) << double(-UNITX_45);
259 const double small = qSqrt(v: std::numeric_limits<qreal>::denorm_min()) / 8;
260 QTest::newRow(dataTag: "[small,small]->|2| (-small/2,-small/2)")
261 << -(small * .5) << -(small * .5) << (small * .5) << (small * .5)
262 << (small * M_SQRT2) << (2 * M_SQRT2) << 2.0 << 2.0;
263 const double tiny = std::numeric_limits<qreal>::min() / 2;
264 QTest::newRow(dataTag: "[tiny,tiny]->|2| (-tiny/2,-tiny/2)")
265 << -(tiny * .5) << -(tiny * .5) << (tiny * .5) << (tiny * .5)
266 << (tiny * M_SQRT2) << (2 * M_SQRT2) << 2.0 << 2.0;
267 QTest::newRow(dataTag: "[1+3e-13,1+4e-13]|1895| (1, 1)")
268 << 1.0 << 1.0 << (1 + 3e-13) << (1 + 4e-13)
269 << 5e-13 << 1895.0 << 1137.0 << 1516.0;
270 QTest::newRow(dataTag: "[4e-323,5e-324]|1892|") // Unavoidable underflow: denormals
271 << 0.0 << 0.0 << 4e-323 << 5e-324
272 << 4e-323 << 1892.0 << 4e-323 << 5e-324; // vx, vy values ignored
273}
274
275void tst_QLine::testLength()
276{
277 QFETCH(double, x1);
278 QFETCH(double, y1);
279 QFETCH(double, x2);
280 QFETCH(double, y2);
281 QFETCH(double, length);
282 QFETCH(double, lengthToSet);
283 QFETCH(double, vx);
284 QFETCH(double, vy);
285
286 QLineF l(x1, y1, x2, y2);
287 QCOMPARE(l.length(), qreal(length));
288
289 l.setLength(lengthToSet);
290 // Scaling tiny values up to big can be imprecise: don't try to test vx, vy
291 if (length > 0 && qFuzzyIsNull(d: length)) {
292 QVERIFY(l.length() > lengthToSet / 2 && l.length() < lengthToSet * 2);
293 } else {
294 QCOMPARE(l.length(), length > 0 ? qreal(lengthToSet) : qreal(length));
295 QCOMPARE(l.dx(), qreal(vx));
296 QCOMPARE(l.dy(), qreal(vy));
297 }
298}
299
300void tst_QLine::testCenter()
301{
302 QFETCH(int, x1);
303 QFETCH(int, y1);
304 QFETCH(int, x2);
305 QFETCH(int, y2);
306 QFETCH(int, centerX);
307 QFETCH(int, centerY);
308
309 const QPoint c = QLine(x1, y1, x2, y2).center();
310 QCOMPARE(centerX, c.x());
311 QCOMPARE(centerY, c.y());
312}
313
314void tst_QLine::testCenter_data()
315{
316 QTest::addColumn<int>(name: "x1");
317 QTest::addColumn<int>(name: "y1");
318 QTest::addColumn<int>(name: "x2");
319 QTest::addColumn<int>(name: "y2");
320 QTest::addColumn<int>(name: "centerX");
321 QTest::addColumn<int>(name: "centerY");
322
323 QTest::newRow(dataTag: "[0, 0]") << 0 << 0 << 0 << 0 << 0 << 0;
324 QTest::newRow(dataTag: "top") << 0 << 0 << 2 << 0 << 1 << 0;
325 QTest::newRow(dataTag: "right") << 0 << 0 << 0 << 2 << 0 << 1;
326 QTest::newRow(dataTag: "bottom") << 0 << 0 << -2 << 0 << -1 << 0;
327 QTest::newRow(dataTag: "left") << 0 << 0 << 0 << -2 << 0 << -1;
328
329 QTest::newRow(dataTag: "precision+") << 0 << 0 << 1 << 1 << 0 << 0;
330 QTest::newRow(dataTag: "precision-") << -1 << -1 << 0 << 0 << 0 << 0;
331
332 const int max = std::numeric_limits<int>::max();
333 const int min = std::numeric_limits<int>::min();
334 QTest::newRow(dataTag: "max") << max << max << max << max << max << max;
335 QTest::newRow(dataTag: "min") << min << min << min << min << min << min;
336 QTest::newRow(dataTag: "minmax") << min << min << max << max << 0 << 0;
337}
338
339void tst_QLine::testCenterF()
340{
341 QFETCH(double, x1);
342 QFETCH(double, y1);
343 QFETCH(double, x2);
344 QFETCH(double, y2);
345 QFETCH(double, centerX);
346 QFETCH(double, centerY);
347
348 const QPointF c = QLineF(x1, y1, x2, y2).center();
349 QCOMPARE(centerX, c.x());
350 QCOMPARE(centerY, c.y());
351}
352
353void tst_QLine::testCenterF_data()
354{
355 QTest::addColumn<double>(name: "x1");
356 QTest::addColumn<double>(name: "y1");
357 QTest::addColumn<double>(name: "x2");
358 QTest::addColumn<double>(name: "y2");
359 QTest::addColumn<double>(name: "centerX");
360 QTest::addColumn<double>(name: "centerY");
361
362 QTest::newRow(dataTag: "[0, 0]") << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0;
363 QTest::newRow(dataTag: "top") << 0.0 << 0.0 << 1.0 << 0.0 << 0.5 << 0.0;
364 QTest::newRow(dataTag: "right") << 0.0 << 0.0 << 0.0 << 1.0 << 0.0 << 0.5;
365 QTest::newRow(dataTag: "bottom") << 0.0 << 0.0 << -1.0 << 0.0 << -0.5 << 0.0;
366 QTest::newRow(dataTag: "left") << 0.0 << 0.0 << 0.0 << -1.0 << 0.0 << -0.5;
367
368 const double max = std::numeric_limits<qreal>::max();
369 QTest::newRow(dataTag: "max") << max << max << max << max << max << max;
370}
371
372void tst_QLine::testNormalVector_data()
373{
374 QTest::addColumn<double>(name: "x1");
375 QTest::addColumn<double>(name: "y1");
376 QTest::addColumn<double>(name: "x2");
377 QTest::addColumn<double>(name: "y2");
378 QTest::addColumn<double>(name: "nvx");
379 QTest::addColumn<double>(name: "nvy");
380
381 QTest::newRow(dataTag: "[1, 0]") << 0.0 << 0.0 << 1.0 << 0.0 << 0.0 << -1.0;
382 QTest::newRow(dataTag: "[-1, 0]") << 0.0 << 0.0 << -1.0 << 0.0 << 0.0 << 1.0;
383 QTest::newRow(dataTag: "[0, 1]") << 0.0 << 0.0 << 0.0 << 1.0 << 1.0 << 0.0;
384 QTest::newRow(dataTag: "[0, -1]") << 0.0 << 0.0 << 0.0 << -1.0 << -1.0 << 0.0;
385 QTest::newRow(dataTag: "[2, 3]") << 2.0 << 3.0 << 4.0 << 6.0 << 3.0 << -2.0;
386}
387
388void tst_QLine::testNormalVector()
389{
390 QFETCH(double, x1);
391 QFETCH(double, y1);
392 QFETCH(double, x2);
393 QFETCH(double, y2);
394 QFETCH(double, nvx);
395 QFETCH(double, nvy);
396
397 QLineF l(x1, y1, x2, y2);
398 QLineF n = l.normalVector();
399
400 QCOMPARE(l.x1(), n.x1());
401 QCOMPARE(l.y1(), n.y1());
402
403 QCOMPARE(n.dx(), qreal(nvx));
404 QCOMPARE(n.dy(), qreal(nvy));
405}
406
407#if QT_DEPRECATED_SINCE(5, 14)
408void tst_QLine::testAngle_data()
409{
410 QTest::addColumn<double>(name: "xa1");
411 QTest::addColumn<double>(name: "ya1");
412 QTest::addColumn<double>(name: "xa2");
413 QTest::addColumn<double>(name: "ya2");
414 QTest::addColumn<double>(name: "xb1");
415 QTest::addColumn<double>(name: "yb1");
416 QTest::addColumn<double>(name: "xb2");
417 QTest::addColumn<double>(name: "yb2");
418 QTest::addColumn<double>(name: "angle");
419
420 QTest::newRow(dataTag: "parallel") << 1.0 << 1.0 << 3.0 << 4.0
421 << 5.0 << 6.0 << 7.0 << 9.0
422 << 0.0;
423 QTest::newRow(dataTag: "[4,4]-[4,0]") << 1.0 << 1.0 << 5.0 << 5.0
424 << 0.0 << 4.0 << 3.0 << 4.0
425 << 45.0;
426 QTest::newRow(dataTag: "[4,4]-[-4,0]") << 1.0 << 1.0 << 5.0 << 5.0
427 << 3.0 << 4.0 << 0.0 << 4.0
428 << 135.0;
429
430 for (int i=0; i<180; ++i) {
431 QTest::newRow(dataTag: ("angle:" + QByteArray::number(i)).constData())
432 << 0.0 << 0.0 << double(cos(x: i*M_2PI/360)) << double(sin(x: i*M_2PI/360))
433 << 0.0 << 0.0 << 1.0 << 0.0
434 << double(i);
435 }
436}
437
438void tst_QLine::testAngle()
439{
440 QFETCH(double, xa1);
441 QFETCH(double, ya1);
442 QFETCH(double, xa2);
443 QFETCH(double, ya2);
444 QFETCH(double, xb1);
445 QFETCH(double, yb1);
446 QFETCH(double, xb2);
447 QFETCH(double, yb2);
448 QFETCH(double, angle);
449
450 QLineF a(xa1, ya1, xa2, ya2);
451 QLineF b(xb1, yb1, xb2, yb2);
452
453 double resultAngle = a.angle(l: b);
454 QCOMPARE(qRound(resultAngle), qRound(angle));
455}
456#endif
457
458void tst_QLine::testAngle2_data()
459{
460 QTest::addColumn<qreal>(name: "x1");
461 QTest::addColumn<qreal>(name: "y1");
462 QTest::addColumn<qreal>(name: "x2");
463 QTest::addColumn<qreal>(name: "y2");
464 QTest::addColumn<qreal>(name: "angle");
465
466 QTest::newRow(dataTag: "right") << qreal(0.0) << qreal(0.0) << qreal(10.0) << qreal(0.0) << qreal(0.0);
467 QTest::newRow(dataTag: "left") << qreal(0.0) << qreal(0.0) << qreal(-10.0) << qreal(0.0) << qreal(180.0);
468 QTest::newRow(dataTag: "up") << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(-10.0) << qreal(90.0);
469 QTest::newRow(dataTag: "down") << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(10.0) << qreal(270.0);
470
471 QTest::newRow(dataTag: "diag a") << qreal(0.0) << qreal(0.0) << qreal(10.0) << qreal(-10.0) << qreal(45.0);
472 QTest::newRow(dataTag: "diag b") << qreal(0.0) << qreal(0.0) << qreal(-10.0) << qreal(-10.0) << qreal(135.0);
473 QTest::newRow(dataTag: "diag c") << qreal(0.0) << qreal(0.0) << qreal(-10.0) << qreal(10.0) << qreal(225.0);
474 QTest::newRow(dataTag: "diag d") << qreal(0.0) << qreal(0.0) << qreal(10.0) << qreal(10.0) << qreal(315.0);
475}
476
477void tst_QLine::testAngle2()
478{
479 QFETCH(qreal, x1);
480 QFETCH(qreal, y1);
481 QFETCH(qreal, x2);
482 QFETCH(qreal, y2);
483 QFETCH(qreal, angle);
484
485 QLineF line(x1, y1, x2, y2);
486 QCOMPARE(line.angle(), angle);
487
488 QLineF polar = QLineF::fromPolar(length: line.length(), angle);
489
490 QVERIFY(qAbs(line.x1() - polar.x1()) < epsilon);
491 QVERIFY(qAbs(line.y1() - polar.y1()) < epsilon);
492 QVERIFY(qAbs(line.x2() - polar.x2()) < epsilon);
493 QVERIFY(qAbs(line.y2() - polar.y2()) < epsilon);
494}
495
496void tst_QLine::testAngle3()
497{
498 for (int i = -720; i <= 720; ++i) {
499 QLineF line(0, 0, 100, 0);
500 line.setAngle(i);
501 const int expected = (i + 720) % 360;
502
503 QVERIFY2(qAbs(line.angle() - qreal(expected)) < epsilon, qPrintable(QString::fromLatin1("value: %1").arg(i)));
504
505 QCOMPARE(line.length(), qreal(100.0));
506
507 QCOMPARE(QLineF::fromPolar(100.0, i), line);
508 }
509}
510
511void tst_QLine::testAngleTo()
512{
513 QFETCH(qreal, xa1);
514 QFETCH(qreal, ya1);
515 QFETCH(qreal, xa2);
516 QFETCH(qreal, ya2);
517 QFETCH(qreal, xb1);
518 QFETCH(qreal, yb1);
519 QFETCH(qreal, xb2);
520 QFETCH(qreal, yb2);
521 QFETCH(qreal, angle);
522
523 QLineF a(xa1, ya1, xa2, ya2);
524 QLineF b(xb1, yb1, xb2, yb2);
525
526 const qreal resultAngle = a.angleTo(l: b);
527 QVERIFY(qAbs(resultAngle - angle) < epsilon);
528
529 a.translate(point: b.p1() - a.p1());
530 a.setAngle(a.angle() + resultAngle);
531 a.setLength(b.length());
532
533 QCOMPARE(a, b);
534}
535
536void tst_QLine::testAngleTo_data()
537{
538 QTest::addColumn<qreal>(name: "xa1");
539 QTest::addColumn<qreal>(name: "ya1");
540 QTest::addColumn<qreal>(name: "xa2");
541 QTest::addColumn<qreal>(name: "ya2");
542 QTest::addColumn<qreal>(name: "xb1");
543 QTest::addColumn<qreal>(name: "yb1");
544 QTest::addColumn<qreal>(name: "xb2");
545 QTest::addColumn<qreal>(name: "yb2");
546 QTest::addColumn<qreal>(name: "angle");
547
548 QTest::newRow(dataTag: "parallel") << qreal(1.0) << qreal(1.0) << qreal(3.0) << qreal(4.0)
549 << qreal(5.0) << qreal(6.0) << qreal(7.0) << qreal(9.0)
550 << qreal(0.0);
551 QTest::newRow(dataTag: "[4,4]-[4,0]") << qreal(1.0) << qreal(1.0) << qreal(5.0) << qreal(5.0)
552 << qreal(0.0) << qreal(4.0) << qreal(3.0) << qreal(4.0)
553 << qreal(45.0);
554 QTest::newRow(dataTag: "[4,4]-[-4,0]") << qreal(1.0) << qreal(1.0) << qreal(5.0) << qreal(5.0)
555 << qreal(3.0) << qreal(4.0) << qreal(0.0) << qreal(4.0)
556 << qreal(225.0);
557
558 for (int i = 0; i < 360; ++i) {
559 const QLineF l = QLineF::fromPolar(length: 1, angle: i);
560 QTest::newRow(dataTag: ("angle:" + QByteArray::number(i)).constData())
561 << qreal(0.0) << qreal(0.0) << qreal(1.0) << qreal(0.0)
562 << qreal(0.0) << qreal(0.0) << l.p2().x() << l.p2().y()
563 << qreal(i);
564 }
565}
566
567QTEST_MAIN(tst_QLine)
568#include "tst_qline.moc"
569

source code of qtbase/tests/auto/corelib/tools/qline/tst_qline.cpp