| 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 | |