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 
34 QT_USE_NAMESPACE
35 
36 class tst_QGeoCircle : public QObject
37 {
38     Q_OBJECT
39 
40 private 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 
defaultConstructor()76 void tst_QGeoCircle::defaultConstructor()
77 {
78     QGeoCircle c;
79     QVERIFY(!c.center().isValid());
80     QCOMPARE(c.radius(), qreal(-1.0));
81 }
82 
centerRadiusConstructor()83 void 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 
assignment()90 void 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 
comparison()123 void 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 
type()155 void tst_QGeoCircle::type()
156 {
157     QGeoCircle c;
158     QCOMPARE(c.type(), QGeoShape::CircleType);
159 }
160 
radius()161 void 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 
center()170 void 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 
translate_data()183 void tst_QGeoCircle::translate_data()
184 {
185     QTest::addColumn<QGeoCoordinate>("center");
186     QTest::addColumn<qreal>("radius");
187     QTest::addColumn<double>("lat");
188     QTest::addColumn<double>("lon");
189     QTest::addColumn<QGeoCoordinate>("newCenter");
190 
191     QTest::newRow("from 0,0") << QGeoCoordinate(0,0) << qreal(10.0) <<
192                                  5.0 << 5.0 << QGeoCoordinate(5.0, 5.0);
193     QTest::newRow("across 0,0") << QGeoCoordinate(-2, -2) << qreal(20.0) <<
194                                    5.0 << 5.0 << QGeoCoordinate(3.0, 3.0);
195     QTest::newRow("backwards across 0,0") << QGeoCoordinate(5,5) << qreal(50.0)
196                                               << -13.0 << 5.0
197                                               << QGeoCoordinate(-8.0, 10.0);
198 }
199 
translate()200 void 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(lat, lon);
212 
213     QCOMPARE(c.radius(), radius);
214     QCOMPARE(c.center(), newCenter);
215 
216     c = d.translated(lat, lon);
217     d.setRadius(1.0);
218 
219     QCOMPARE(c.radius(), radius);
220     QCOMPARE(d.center(), center);
221     QCOMPARE(c.center(), newCenter);
222 }
223 
valid_data()224 void tst_QGeoCircle::valid_data()
225 {
226     QTest::addColumn<QGeoCoordinate>("center");
227     QTest::addColumn<qreal>("radius");
228     QTest::addColumn<bool>("valid");
229 
230     QTest::newRow("default") << QGeoCoordinate() << qreal(-1.0) << false;
231     QTest::newRow("empty coord") << QGeoCoordinate() << qreal(5.0) << false;
232     QTest::newRow("NaN coord") << QGeoCoordinate(500, 500) << qreal(5.0) << false;
233     QTest::newRow("bad radius") << QGeoCoordinate(10, 10) << qreal(-5.0) << false;
234     QTest::newRow("NaN radius") << QGeoCoordinate(10, 10) << qreal(qQNaN()) << false;
235     QTest::newRow("zero radius") << QGeoCoordinate(10, 10) << qreal(0.0) << true;
236     QTest::newRow("good") << QGeoCoordinate(10, 10) << qreal(5.0) << true;
237 }
238 
valid()239 void 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 
empty_data()252 void tst_QGeoCircle::empty_data()
253 {
254     QTest::addColumn<QGeoCoordinate>("center");
255     QTest::addColumn<qreal>("radius");
256     QTest::addColumn<bool>("empty");
257 
258     QTest::newRow("default") << QGeoCoordinate() << qreal(-1.0) << true;
259     QTest::newRow("empty coord") << QGeoCoordinate() << qreal(5.0) << true;
260     QTest::newRow("NaN coord") << QGeoCoordinate(500, 500) << qreal(5.0) << true;
261     QTest::newRow("bad radius") << QGeoCoordinate(10, 10) << qreal(-5.0) << true;
262     QTest::newRow("NaN radius") << QGeoCoordinate(10, 10) << qreal(qQNaN()) << true;
263     QTest::newRow("zero radius") << QGeoCoordinate(10, 10) << qreal(0.0) << true;
264     QTest::newRow("good") << QGeoCoordinate(10, 10) << qreal(5.0) << false;
265 }
266 
empty()267 void 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 
contains_data()280 void tst_QGeoCircle::contains_data()
281 {
282     QTest::addColumn<QGeoCoordinate>("center");
283     QTest::addColumn<qreal>("radius");
284     QTest::addColumn<QGeoCoordinate>("probe");
285     QTest::addColumn<bool>("result");
286 
287     QTest::newRow("own center") << QGeoCoordinate(1,1) << qreal(100.0) <<
288                                    QGeoCoordinate(1,1) << true;
289     QTest::newRow("over the hills") << QGeoCoordinate(1,1) << qreal(100.0) <<
290                                        QGeoCoordinate(30, 40) << false;
291     QTest::newRow("at 0.5*radius") << QGeoCoordinate(1,1) << qreal(100.0) <<
292                                       QGeoCoordinate(1.00015374,1.00015274) << true;
293     QTest::newRow("at 0.99*radius") << QGeoCoordinate(1,1) << qreal(100.0) <<
294                                        QGeoCoordinate(1.00077538, 0.99955527) << true;
295     QTest::newRow("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 
contains()300 void 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 
boundingGeoRectangle_data()314 void tst_QGeoCircle::boundingGeoRectangle_data()
315 {
316     QTest::addColumn<QGeoCoordinate>("center");
317     QTest::addColumn<qreal>("radius");
318     QTest::addColumn<QGeoCoordinate>("probe");
319     QTest::addColumn<bool>("result");
320 
321     QTest::newRow("own center") << QGeoCoordinate(1,1) << qreal(100.0) <<
322                                    QGeoCoordinate(1,1) << true;
323     QTest::newRow("over the hills") << QGeoCoordinate(1,1) << qreal(100.0) <<
324                                        QGeoCoordinate(30, 40) << false;
325     QTest::newRow("at 0.5*radius") << QGeoCoordinate(1,1) << qreal(100.0) <<
326                                       QGeoCoordinate(1.00015374,1.00015274) << true;
327     QTest::newRow("at 0.99*radius") << QGeoCoordinate(1,1) << qreal(100.0) <<
328                                        QGeoCoordinate(1.00077538, 0.99955527) << true;
329     QTest::newRow("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 
boundingGeoRectangle()334 void 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 
extendCircle()346 void 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(coord);
355     QCOMPARE(circle.contains(coord), containsExtended);
356 
357 }
358 
extendCircle_data()359 void tst_QGeoCircle::extendCircle_data()
360 {
361     QTest::addColumn<QGeoCircle>("circle");
362     QTest::addColumn<QGeoCoordinate>("coord");
363     QTest::addColumn<bool>("containsFirst");
364     QTest::addColumn<bool>("containsExtended");
365 
366     QGeoCoordinate co1(20.0, 20.0);
367 
368     QTest::newRow("own center")
369             << QGeoCircle(co1, 100)
370             << QGeoCoordinate(20.0, 20.0)
371             << true
372             << true;
373     QTest::newRow("inside")
374             << QGeoCircle(co1, 100)
375             << QGeoCoordinate(20.0001, 20.0001)
376             << true
377             << true;
378     QTest::newRow("far away")
379             << QGeoCircle(co1, 100)
380             << QGeoCoordinate(50.0001, 50.0001)
381             << false
382             << true;
383     QTest::newRow("invalid circle")
384             << QGeoCircle()
385             << QGeoCoordinate(20.0, 20.0)
386             << false
387             << false;
388     QTest::newRow("invalid coordinate")
389             << QGeoCircle(co1, 100)
390             << QGeoCoordinate(99.0, 190.0)
391             << false
392             << false;
393 }
394 
areaComparison_data()395 void tst_QGeoCircle::areaComparison_data()
396 {
397     QTest::addColumn<QGeoShape>("area");
398     QTest::addColumn<QGeoCircle>("circle");
399     QTest::addColumn<bool>("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("default constructed") << QGeoShape() << QGeoCircle() << false;
406     QTest::newRow("c1 c1") << QGeoShape(c1) << c1 << true;
407     QTest::newRow("c1 c2") << QGeoShape(c1) << c2 << false;
408     QTest::newRow("c2 c1") << QGeoShape(c2) << c1 << false;
409     QTest::newRow("c2 c2") << QGeoShape(c2) << c2 << true;
410     QTest::newRow("b c1") << QGeoShape(b) << c1 << false;
411 }
412 
areaComparison()413 void 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 
boxComparison_data()426 void tst_QGeoCircle::boxComparison_data()
427 {
428     QTest::addColumn<QGeoRectangle>("box");
429     QTest::addColumn<QGeoCircle>("circle");
430     QTest::addColumn<bool>("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("default constructed") << QGeoRectangle() << QGeoCircle() << false;
436     QTest::newRow("b c") << b << c << false;
437 }
438 
boxComparison()439 void 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 
452 QTEST_MAIN(tst_QGeoCircle)
453 #include "tst_qgeocircle.moc"
454