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 | |
37 | class tst_QLine : public QObject |
38 | { |
39 | Q_OBJECT |
40 | private 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 | |
78 | const qreal epsilon = sizeof(qreal) == sizeof(double) ? 1e-8 : 1e-4; |
79 | |
80 | void 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 | |
130 | void 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 | |
191 | void 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 | |
222 | void 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 | |
275 | void 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 | |
300 | void 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 | |
314 | void 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 | |
339 | void 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 | |
353 | void 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 | |
372 | void 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 | |
388 | void 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) |
408 | void 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 | |
438 | void 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 | |
458 | void 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 | |
477 | void 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 | |
496 | void 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 | |
511 | void 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 | |
536 | void 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 | |
567 | QTEST_MAIN(tst_QLine) |
568 | #include "tst_qline.moc" |
569 | |