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 <QtPositioning/QGeoCoordinate>
31#include <QtPositioning/QGeoCircle>
32#include <QtPositioning/QGeoRectangle>
33
34QT_USE_NAMESPACE
35
36class tst_QGeoCircle : public QObject
37{
38 Q_OBJECT
39
40private slots:
41 void defaultConstructor();
42 void centerRadiusConstructor();
43 void assignment();
44
45 void comparison();
46 void type();
47
48 void radius();
49 void center();
50
51 void translate_data();
52 void translate();
53
54 void valid_data();
55 void valid();
56
57 void empty_data();
58 void empty();
59
60 void contains_data();
61 void contains();
62
63 void boundingGeoRectangle_data();
64 void boundingGeoRectangle();
65
66 void extendCircle();
67 void extendCircle_data();
68
69 void areaComparison();
70 void areaComparison_data();
71
72 void boxComparison();
73 void boxComparison_data();
74};
75
76void tst_QGeoCircle::defaultConstructor()
77{
78 QGeoCircle c;
79 QVERIFY(!c.center().isValid());
80 QCOMPARE(c.radius(), qreal(-1.0));
81}
82
83void tst_QGeoCircle::centerRadiusConstructor()
84{
85 QGeoCircle c(QGeoCoordinate(1,1), qreal(50.0));
86 QCOMPARE(c.center(), QGeoCoordinate(1,1));
87 QCOMPARE(c.radius(), qreal(50.0));
88}
89
90void tst_QGeoCircle::assignment()
91{
92 QGeoCircle c1 = QGeoCircle(QGeoCoordinate(10.0, 0.0), 20.0);
93 QGeoCircle c2 = QGeoCircle(QGeoCoordinate(20.0, 0.0), 30.0);
94
95 QVERIFY(c1 != c2);
96
97 c2 = c1;
98 QCOMPARE(c2.center(), QGeoCoordinate(10.0, 0.0));
99 QCOMPARE(c2.radius(), 20.0);
100 QCOMPARE(c1, c2);
101
102 c2.setCenter(QGeoCoordinate(30.0, 0.0));
103 c2.setRadius(15.0);
104 QCOMPARE(c1.center(), QGeoCoordinate(10.0, 0.0));
105 QCOMPARE(c1.radius(), 20.0);
106
107 // Assign c1 to an area
108 QGeoShape area = c1;
109 QCOMPARE(area.type(), c1.type());
110 QVERIFY(area == c1);
111
112 // Assign the area back to a bounding circle
113 QGeoCircle ca = area;
114 QCOMPARE(ca.center(), c1.center());
115 QCOMPARE(ca.radius(), c1.radius());
116
117 // Check that the copy is not modified when modifying the original.
118 c1.setCenter(QGeoCoordinate(15.0, 15.0));
119 QVERIFY(ca.center() != c1.center());
120 QVERIFY(ca != c1);
121}
122
123void tst_QGeoCircle::comparison()
124{
125 QGeoCircle c1(QGeoCoordinate(1,1), qreal(50.0));
126 QGeoCircle c2(QGeoCoordinate(1,1), qreal(50.0));
127 QGeoCircle c3(QGeoCoordinate(1,1), qreal(35.0));
128 QGeoCircle c4(QGeoCoordinate(1,2), qreal(50.0));
129
130 QVERIFY(c1 == c2);
131 QVERIFY(!(c1 != c2));
132
133 QVERIFY(!(c1 == c3));
134 QVERIFY(c1 != c3);
135
136 QVERIFY(!(c1 == c4));
137 QVERIFY(c1 != c4);
138
139 QVERIFY(!(c2 == c3));
140 QVERIFY(c2 != c3);
141
142 QGeoRectangle b1(QGeoCoordinate(20,20),QGeoCoordinate(10,30));
143 QVERIFY(!(c1 == b1));
144 QVERIFY(c1 != b1);
145
146 QGeoShape *c2Ptr = &c2;
147 QVERIFY(c1 == *c2Ptr);
148 QVERIFY(!(c1 != *c2Ptr));
149
150 QGeoShape *c3Ptr = &c3;
151 QVERIFY(!(c1 == *c3Ptr));
152 QVERIFY(c1 != *c3Ptr);
153}
154
155void tst_QGeoCircle::type()
156{
157 QGeoCircle c;
158 QCOMPARE(c.type(), QGeoShape::CircleType);
159}
160
161void tst_QGeoCircle::radius()
162{
163 QGeoCircle c;
164 c.setRadius(1.0);
165 QCOMPARE(c.radius(), qreal(1.0));
166 c.setRadius(5.0);
167 QCOMPARE(c.radius(), qreal(5.0));
168}
169
170void tst_QGeoCircle::center()
171{
172 QGeoCircle c;
173 c.setCenter(QGeoCoordinate(1,1));
174 QCOMPARE(c.center(), QGeoCoordinate(1,1));
175
176 QGeoShape shape = c;
177 QCOMPARE(shape.center(), c.center());
178
179 c.setCenter(QGeoCoordinate(5,10));
180 QCOMPARE(c.center(), QGeoCoordinate(5,10));
181}
182
183void tst_QGeoCircle::translate_data()
184{
185 QTest::addColumn<QGeoCoordinate>(name: "center");
186 QTest::addColumn<qreal>(name: "radius");
187 QTest::addColumn<double>(name: "lat");
188 QTest::addColumn<double>(name: "lon");
189 QTest::addColumn<QGeoCoordinate>(name: "newCenter");
190
191 QTest::newRow(dataTag: "from 0,0") << QGeoCoordinate(0,0) << qreal(10.0) <<
192 5.0 << 5.0 << QGeoCoordinate(5.0, 5.0);
193 QTest::newRow(dataTag: "across 0,0") << QGeoCoordinate(-2, -2) << qreal(20.0) <<
194 5.0 << 5.0 << QGeoCoordinate(3.0, 3.0);
195 QTest::newRow(dataTag: "backwards across 0,0") << QGeoCoordinate(5,5) << qreal(50.0)
196 << -13.0 << 5.0
197 << QGeoCoordinate(-8.0, 10.0);
198}
199
200void tst_QGeoCircle::translate()
201{
202 QFETCH(QGeoCoordinate, center);
203 QFETCH(qreal, radius);
204 QFETCH(double, lat);
205 QFETCH(double, lon);
206 QFETCH(QGeoCoordinate, newCenter);
207
208 QGeoCircle c(center, radius);
209 QGeoCircle d = c;
210
211 c.translate(degreesLatitude: lat, degreesLongitude: lon);
212
213 QCOMPARE(c.radius(), radius);
214 QCOMPARE(c.center(), newCenter);
215
216 c = d.translated(degreesLatitude: lat, degreesLongitude: lon);
217 d.setRadius(1.0);
218
219 QCOMPARE(c.radius(), radius);
220 QCOMPARE(d.center(), center);
221 QCOMPARE(c.center(), newCenter);
222}
223
224void tst_QGeoCircle::valid_data()
225{
226 QTest::addColumn<QGeoCoordinate>(name: "center");
227 QTest::addColumn<qreal>(name: "radius");
228 QTest::addColumn<bool>(name: "valid");
229
230 QTest::newRow(dataTag: "default") << QGeoCoordinate() << qreal(-1.0) << false;
231 QTest::newRow(dataTag: "empty coord") << QGeoCoordinate() << qreal(5.0) << false;
232 QTest::newRow(dataTag: "NaN coord") << QGeoCoordinate(500, 500) << qreal(5.0) << false;
233 QTest::newRow(dataTag: "bad radius") << QGeoCoordinate(10, 10) << qreal(-5.0) << false;
234 QTest::newRow(dataTag: "NaN radius") << QGeoCoordinate(10, 10) << qreal(qQNaN()) << false;
235 QTest::newRow(dataTag: "zero radius") << QGeoCoordinate(10, 10) << qreal(0.0) << true;
236 QTest::newRow(dataTag: "good") << QGeoCoordinate(10, 10) << qreal(5.0) << true;
237}
238
239void tst_QGeoCircle::valid()
240{
241 QFETCH(QGeoCoordinate, center);
242 QFETCH(qreal, radius);
243 QFETCH(bool, valid);
244
245 QGeoCircle c(center, radius);
246 QCOMPARE(c.isValid(), valid);
247
248 QGeoShape area = c;
249 QCOMPARE(area.isValid(), valid);
250}
251
252void tst_QGeoCircle::empty_data()
253{
254 QTest::addColumn<QGeoCoordinate>(name: "center");
255 QTest::addColumn<qreal>(name: "radius");
256 QTest::addColumn<bool>(name: "empty");
257
258 QTest::newRow(dataTag: "default") << QGeoCoordinate() << qreal(-1.0) << true;
259 QTest::newRow(dataTag: "empty coord") << QGeoCoordinate() << qreal(5.0) << true;
260 QTest::newRow(dataTag: "NaN coord") << QGeoCoordinate(500, 500) << qreal(5.0) << true;
261 QTest::newRow(dataTag: "bad radius") << QGeoCoordinate(10, 10) << qreal(-5.0) << true;
262 QTest::newRow(dataTag: "NaN radius") << QGeoCoordinate(10, 10) << qreal(qQNaN()) << true;
263 QTest::newRow(dataTag: "zero radius") << QGeoCoordinate(10, 10) << qreal(0.0) << true;
264 QTest::newRow(dataTag: "good") << QGeoCoordinate(10, 10) << qreal(5.0) << false;
265}
266
267void tst_QGeoCircle::empty()
268{
269 QFETCH(QGeoCoordinate, center);
270 QFETCH(qreal, radius);
271 QFETCH(bool, empty);
272
273 QGeoCircle c(center, radius);
274 QCOMPARE(c.isEmpty(), empty);
275
276 QGeoShape area = c;
277 QCOMPARE(area.isEmpty(), empty);
278}
279
280void tst_QGeoCircle::contains_data()
281{
282 QTest::addColumn<QGeoCoordinate>(name: "center");
283 QTest::addColumn<qreal>(name: "radius");
284 QTest::addColumn<QGeoCoordinate>(name: "probe");
285 QTest::addColumn<bool>(name: "result");
286
287 QTest::newRow(dataTag: "own center") << QGeoCoordinate(1,1) << qreal(100.0) <<
288 QGeoCoordinate(1,1) << true;
289 QTest::newRow(dataTag: "over the hills") << QGeoCoordinate(1,1) << qreal(100.0) <<
290 QGeoCoordinate(30, 40) << false;
291 QTest::newRow(dataTag: "at 0.5*radius") << QGeoCoordinate(1,1) << qreal(100.0) <<
292 QGeoCoordinate(1.00015374,1.00015274) << true;
293 QTest::newRow(dataTag: "at 0.99*radius") << QGeoCoordinate(1,1) << qreal(100.0) <<
294 QGeoCoordinate(1.00077538, 0.99955527) << true;
295 QTest::newRow(dataTag: "at 1.01*radius") << QGeoCoordinate(1,1) << qreal(100.0) <<
296 QGeoCoordinate(1.00071413, 0.99943423) << false;
297 // TODO: add tests for edge circle cases: cross 1 pole, cross both poles
298}
299
300void tst_QGeoCircle::contains()
301{
302 QFETCH(QGeoCoordinate, center);
303 QFETCH(qreal, radius);
304 QFETCH(QGeoCoordinate, probe);
305 QFETCH(bool, result);
306
307 QGeoCircle c(center, radius);
308 QCOMPARE(c.contains(probe), result);
309
310 QGeoShape area = c;
311 QCOMPARE(area.contains(probe), result);
312}
313
314void tst_QGeoCircle::boundingGeoRectangle_data()
315{
316 QTest::addColumn<QGeoCoordinate>(name: "center");
317 QTest::addColumn<qreal>(name: "radius");
318 QTest::addColumn<QGeoCoordinate>(name: "probe");
319 QTest::addColumn<bool>(name: "result");
320
321 QTest::newRow(dataTag: "own center") << QGeoCoordinate(1,1) << qreal(100.0) <<
322 QGeoCoordinate(1,1) << true;
323 QTest::newRow(dataTag: "over the hills") << QGeoCoordinate(1,1) << qreal(100.0) <<
324 QGeoCoordinate(30, 40) << false;
325 QTest::newRow(dataTag: "at 0.5*radius") << QGeoCoordinate(1,1) << qreal(100.0) <<
326 QGeoCoordinate(1.00015374,1.00015274) << true;
327 QTest::newRow(dataTag: "at 0.99*radius") << QGeoCoordinate(1,1) << qreal(100.0) <<
328 QGeoCoordinate(1.00077538, 0.99955527) << true;
329 QTest::newRow(dataTag: "Outside the box") << QGeoCoordinate(1,1) << qreal(100.0) <<
330 QGeoCoordinate(1.00071413, 0.99903423) << false;
331 // TODO: add tests for edge circle cases: cross 1 pole, cross both poles
332}
333
334void tst_QGeoCircle::boundingGeoRectangle()
335{
336 QFETCH(QGeoCoordinate, center);
337 QFETCH(qreal, radius);
338 QFETCH(QGeoCoordinate, probe);
339 QFETCH(bool, result);
340
341 QGeoCircle c(center, radius);
342 QGeoRectangle box = c.boundingGeoRectangle();
343 QCOMPARE(box.contains(probe), result);
344}
345
346void tst_QGeoCircle::extendCircle()
347{
348 QFETCH(QGeoCircle, circle);
349 QFETCH(QGeoCoordinate, coord);
350 QFETCH(bool, containsFirst);
351 QFETCH(bool, containsExtended);
352
353 QCOMPARE(circle.contains(coord), containsFirst);
354 circle.extendCircle(coordinate: coord);
355 QCOMPARE(circle.contains(coord), containsExtended);
356
357}
358
359void tst_QGeoCircle::extendCircle_data()
360{
361 QTest::addColumn<QGeoCircle>(name: "circle");
362 QTest::addColumn<QGeoCoordinate>(name: "coord");
363 QTest::addColumn<bool>(name: "containsFirst");
364 QTest::addColumn<bool>(name: "containsExtended");
365
366 QGeoCoordinate co1(20.0, 20.0);
367
368 QTest::newRow(dataTag: "own center")
369 << QGeoCircle(co1, 100)
370 << QGeoCoordinate(20.0, 20.0)
371 << true
372 << true;
373 QTest::newRow(dataTag: "inside")
374 << QGeoCircle(co1, 100)
375 << QGeoCoordinate(20.0001, 20.0001)
376 << true
377 << true;
378 QTest::newRow(dataTag: "far away")
379 << QGeoCircle(co1, 100)
380 << QGeoCoordinate(50.0001, 50.0001)
381 << false
382 << true;
383 QTest::newRow(dataTag: "invalid circle")
384 << QGeoCircle()
385 << QGeoCoordinate(20.0, 20.0)
386 << false
387 << false;
388 QTest::newRow(dataTag: "invalid coordinate")
389 << QGeoCircle(co1, 100)
390 << QGeoCoordinate(99.0, 190.0)
391 << false
392 << false;
393}
394
395void tst_QGeoCircle::areaComparison_data()
396{
397 QTest::addColumn<QGeoShape>(name: "area");
398 QTest::addColumn<QGeoCircle>(name: "circle");
399 QTest::addColumn<bool>(name: "equal");
400
401 QGeoCircle c1(QGeoCoordinate(10.0, 0.0), 10.0);
402 QGeoCircle c2(QGeoCoordinate(20.0, 10.0), 20.0);
403 QGeoRectangle b(QGeoCoordinate(10.0, 0.0), QGeoCoordinate(0.0, 10.0));
404
405 QTest::newRow(dataTag: "default constructed") << QGeoShape() << QGeoCircle() << false;
406 QTest::newRow(dataTag: "c1 c1") << QGeoShape(c1) << c1 << true;
407 QTest::newRow(dataTag: "c1 c2") << QGeoShape(c1) << c2 << false;
408 QTest::newRow(dataTag: "c2 c1") << QGeoShape(c2) << c1 << false;
409 QTest::newRow(dataTag: "c2 c2") << QGeoShape(c2) << c2 << true;
410 QTest::newRow(dataTag: "b c1") << QGeoShape(b) << c1 << false;
411}
412
413void tst_QGeoCircle::areaComparison()
414{
415 QFETCH(QGeoShape, area);
416 QFETCH(QGeoCircle, circle);
417 QFETCH(bool, equal);
418
419 QCOMPARE((area == circle), equal);
420 QCOMPARE((area != circle), !equal);
421
422 QCOMPARE((circle == area), equal);
423 QCOMPARE((circle != area), !equal);
424}
425
426void tst_QGeoCircle::boxComparison_data()
427{
428 QTest::addColumn<QGeoRectangle>(name: "box");
429 QTest::addColumn<QGeoCircle>(name: "circle");
430 QTest::addColumn<bool>(name: "equal");
431
432 QGeoCircle c(QGeoCoordinate(10.0, 0.0), 10.0);
433 QGeoRectangle b(QGeoCoordinate(10.0, 0.0), QGeoCoordinate(0.0, 10.0));
434
435 QTest::newRow(dataTag: "default constructed") << QGeoRectangle() << QGeoCircle() << false;
436 QTest::newRow(dataTag: "b c") << b << c << false;
437}
438
439void tst_QGeoCircle::boxComparison()
440{
441 QFETCH(QGeoRectangle, box);
442 QFETCH(QGeoCircle, circle);
443 QFETCH(bool, equal);
444
445 QCOMPARE((box == circle), equal);
446 QCOMPARE((box != circle), !equal);
447
448 QCOMPARE((circle == box), equal);
449 QCOMPARE((circle != box), !equal);
450}
451
452QTEST_MAIN(tst_QGeoCircle)
453#include "tst_qgeocircle.moc"
454

source code of qtlocation/tests/auto/qgeocircle/tst_qgeocircle.cpp