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/QGeoRectangle>
32 #include <QtPositioning/QGeoPath>
33 
34 QT_USE_NAMESPACE
35 
36 class tst_QGeoPath : public QObject
37 {
38     Q_OBJECT
39 
40 private slots:
41     void defaultConstructor();
42     void listConstructor();
43     void assignment();
44 
45     void comparison();
46     void type();
47 
48     void path();
49     void width();
50     void size();
51 
52     void translate_data();
53     void translate();
54 
55     void valid_data();
56     void valid();
57 
58     void contains_data();
59     void contains();
60 
61     void boundingGeoRectangle_data();
62     void boundingGeoRectangle();
63 
64     void extendShape();
65     void extendShape_data();
66 };
67 
defaultConstructor()68 void tst_QGeoPath::defaultConstructor()
69 {
70     QGeoPath p;
71     QVERIFY(!p.path().size());
72     QCOMPARE(p.width(), qreal(0.0));
73     QCOMPARE(p.length(), double(0.0));
74 }
75 
listConstructor()76 void tst_QGeoPath::listConstructor()
77 {
78     QList<QGeoCoordinate> coords;
79     coords.append(QGeoCoordinate(1,1));
80     coords.append(QGeoCoordinate(2,2));
81     coords.append(QGeoCoordinate(3,0));
82 
83     QGeoPath p(coords, 1.0);
84     QCOMPARE(p.width(), qreal(1.0));
85     QCOMPARE(p.path().size(), 3);
86 
87     for (const QGeoCoordinate &c : coords) {
88         QCOMPARE(p.path().contains(c), true);
89     }
90 }
91 
assignment()92 void tst_QGeoPath::assignment()
93 {
94     QGeoPath p1;
95     QList<QGeoCoordinate> coords;
96     coords.append(QGeoCoordinate(1,1));
97     coords.append(QGeoCoordinate(2,2));
98     coords.append(QGeoCoordinate(3,0));
99     QGeoPath p2(coords, 1.0);
100 
101     QVERIFY(p1 != p2);
102 
103     p1 = p2;
104     QCOMPARE(p1.path(), coords);
105     QCOMPARE(p1.width(), 1.0);
106     QCOMPARE(p1, p2);
107 
108     // Assign c1 to an area
109     QGeoShape area = p1;
110     QCOMPARE(area.type(), p1.type());
111     QVERIFY(area == p1);
112 
113     // Assign the area back to a bounding circle
114     QGeoPath p3 = area;
115     QCOMPARE(p3.path(), coords);
116     QCOMPARE(p3.width(), 1.0);
117 
118     // Check that the copy is not modified when modifying the original.
119     p1.setWidth(2.0);
120     QVERIFY(p3.width() != p1.width());
121     QVERIFY(p3 != p1);
122 }
123 
comparison()124 void tst_QGeoPath::comparison()
125 {
126     QList<QGeoCoordinate> coords;
127     coords.append(QGeoCoordinate(1,1));
128     coords.append(QGeoCoordinate(2,2));
129     coords.append(QGeoCoordinate(3,0));
130     QList<QGeoCoordinate> coords2;
131     coords2.append(QGeoCoordinate(3,1));
132     coords2.append(QGeoCoordinate(4,2));
133     coords2.append(QGeoCoordinate(3,0));
134     QGeoPath c1(coords, qreal(50.0));
135     QGeoPath c2(coords, qreal(50.0));
136     QGeoPath c3(coords, qreal(35.0));
137     QGeoPath c4(coords2, qreal(50.0));
138 
139     QVERIFY(c1 == c2);
140     QVERIFY(!(c1 != c2));
141 
142     QVERIFY(!(c1 == c3));
143     QVERIFY(c1 != c3);
144 
145     QVERIFY(!(c1 == c4));
146     QVERIFY(c1 != c4);
147 
148     QVERIFY(!(c2 == c3));
149     QVERIFY(c2 != c3);
150 
151     QGeoRectangle b1(QGeoCoordinate(20,20),QGeoCoordinate(10,30));
152     QVERIFY(!(c1 == b1));
153     QVERIFY(c1 != b1);
154 
155     QGeoShape *c2Ptr = &c2;
156     QVERIFY(c1 == *c2Ptr);
157     QVERIFY(!(c1 != *c2Ptr));
158 
159     QGeoShape *c3Ptr = &c3;
160     QVERIFY(!(c1 == *c3Ptr));
161     QVERIFY(c1 != *c3Ptr);
162 }
163 
type()164 void tst_QGeoPath::type()
165 {
166     QGeoPath c;
167     QCOMPARE(c.type(), QGeoShape::PathType);
168 }
169 
path()170 void tst_QGeoPath::path()
171 {
172     QList<QGeoCoordinate> coords;
173     coords.append(QGeoCoordinate(1,1));
174     coords.append(QGeoCoordinate(2,2));
175     coords.append(QGeoCoordinate(3,0));
176 
177     QGeoPath p;
178     p.setPath(coords);
179     QCOMPARE(p.path().size(), 3);
180 
181     for (const QGeoCoordinate &c : coords) {
182         QCOMPARE(p.path().contains(c), true);
183     }
184 
185     p.clearPath();
186     QCOMPARE(p.path().size(), 0);
187     QVERIFY(p.boundingGeoRectangle().isEmpty());
188 }
189 
width()190 void tst_QGeoPath::width()
191 {
192     QGeoPath p;
193     p.setWidth(10.0);
194     QCOMPARE(p.width(), qreal(10.0));
195 }
196 
size()197 void tst_QGeoPath::size()
198 {
199     QList<QGeoCoordinate> coords;
200 
201     QGeoPath p1(coords, 3);
202     QCOMPARE(p1.size(), coords.size());
203 
204     coords.append(QGeoCoordinate(1,1));
205     QGeoPath p2(coords, 3);
206     QCOMPARE(p2.size(), coords.size());
207 
208     coords.append(QGeoCoordinate(2,2));
209     QGeoPath p3(coords, 3);
210     QCOMPARE(p3.size(), coords.size());
211 
212     coords.append(QGeoCoordinate(3,0));
213     QGeoPath p4(coords, 3);
214     QCOMPARE(p4.size(), coords.size());
215 
216     p4.removeCoordinate(2);
217     QCOMPARE(p4.size(), coords.size() - 1);
218 
219     p4.removeCoordinate(coords.first());
220     QCOMPARE(p4.size(), coords.size() - 2);
221 }
222 
translate_data()223 void tst_QGeoPath::translate_data()
224 {
225     QTest::addColumn<QGeoCoordinate>("c1");
226     QTest::addColumn<QGeoCoordinate>("c2");
227     QTest::addColumn<QGeoCoordinate>("c3");
228     QTest::addColumn<double>("lat");
229     QTest::addColumn<double>("lon");
230 
231     QTest::newRow("Simple") << QGeoCoordinate(1,1) << QGeoCoordinate(2,2) <<
232                                  QGeoCoordinate(3,0) << 5.0 << 4.0;
233     QTest::newRow("Backward") << QGeoCoordinate(1,1) << QGeoCoordinate(2,2) <<
234                                  QGeoCoordinate(3,0) << -5.0 << -4.0;
235 }
236 
translate()237 void tst_QGeoPath::translate()
238 {
239     QFETCH(QGeoCoordinate, c1);
240     QFETCH(QGeoCoordinate, c2);
241     QFETCH(QGeoCoordinate, c3);
242     QFETCH(double, lat);
243     QFETCH(double, lon);
244 
245     QList<QGeoCoordinate> coords;
246     coords.append(c1);
247     coords.append(c2);
248     coords.append(c3);
249     QGeoPath p(coords);
250 
251     p.translate(lat, lon);
252 
253     for (int i = 0; i < p.path().size(); i++) {
254         QCOMPARE(coords[i].latitude(), p.path()[i].latitude() - lat );
255         QCOMPARE(coords[i].longitude(), p.path()[i].longitude() - lon );
256     }
257 }
258 
valid_data()259 void tst_QGeoPath::valid_data()
260 {
261     QTest::addColumn<QGeoCoordinate>("c1");
262     QTest::addColumn<QGeoCoordinate>("c2");
263     QTest::addColumn<QGeoCoordinate>("c3");
264     QTest::addColumn<qreal>("width");
265     QTest::addColumn<bool>("valid");
266 
267     QTest::newRow("empty coords") << QGeoCoordinate() << QGeoCoordinate() << QGeoCoordinate() << qreal(5.0) << false;
268     QTest::newRow("invalid coord") << QGeoCoordinate(50, 50) << QGeoCoordinate(60, 60) << QGeoCoordinate(700, 700) << qreal(5.0) << false;
269     QTest::newRow("bad width") << QGeoCoordinate(10, 10) << QGeoCoordinate(11, 11) << QGeoCoordinate(10, 12) << qreal(-5.0) << true;
270     QTest::newRow("NaN width") << QGeoCoordinate(10, 10) << QGeoCoordinate(11, 11) << QGeoCoordinate(10, 12) << qreal(qQNaN()) << true;
271     QTest::newRow("zero width") << QGeoCoordinate(10, 10) << QGeoCoordinate(11, 11) << QGeoCoordinate(10, 12) << qreal(0) << true;
272     QTest::newRow("good") << QGeoCoordinate(10, 10) << QGeoCoordinate(11, 11) << QGeoCoordinate(10, 12) << qreal(5) << true;
273 }
274 
valid()275 void tst_QGeoPath::valid()
276 {
277     QFETCH(QGeoCoordinate, c1);
278     QFETCH(QGeoCoordinate, c2);
279     QFETCH(QGeoCoordinate, c3);
280     QFETCH(qreal, width);
281     QFETCH(bool, valid);
282 
283     QList<QGeoCoordinate> coords;
284     coords.append(c1);
285     coords.append(c2);
286     coords.append(c3);
287     QGeoPath p(coords, width);
288 
289     QCOMPARE(p.isValid(), valid);
290 
291     QGeoShape area = p;
292     QCOMPARE(area.isValid(), valid);
293 }
294 
contains_data()295 void tst_QGeoPath::contains_data()
296 {
297     QTest::addColumn<QGeoCoordinate>("c1");
298     QTest::addColumn<QGeoCoordinate>("c2");
299     QTest::addColumn<QGeoCoordinate>("c3");
300     QTest::addColumn<qreal>("width");
301     QTest::addColumn<QGeoCoordinate>("probe");
302     QTest::addColumn<bool>("result");
303 
304     QList<QGeoCoordinate> c;
305     c.append(QGeoCoordinate(1,1));
306     c.append(QGeoCoordinate(2,2));
307     c.append(QGeoCoordinate(3,0));
308 
309     QTest::newRow("One of the points") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(2, 2) << true;
310     QTest::newRow("Not so far away") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(0.8, 0.8) << false;
311     QTest::newRow("Not so far away and large line") << c[0] << c[1] << c[2] << 100000.0 << QGeoCoordinate(0.8, 0.8) << true;
312 }
313 
contains()314 void tst_QGeoPath::contains()
315 {
316     QFETCH(QGeoCoordinate, c1);
317     QFETCH(QGeoCoordinate, c2);
318     QFETCH(QGeoCoordinate, c3);
319     QFETCH(qreal, width);
320     QFETCH(QGeoCoordinate, probe);
321     QFETCH(bool, result);
322 
323     QList<QGeoCoordinate> coords;
324     coords.append(c1);
325     coords.append(c2);
326     coords.append(c3);
327     QGeoPath p(coords, width);
328 
329     QCOMPARE(p.contains(probe), result);
330 
331     QGeoShape area = p;
332     QCOMPARE(area.contains(probe), result);
333 }
334 
boundingGeoRectangle_data()335 void tst_QGeoPath::boundingGeoRectangle_data()
336 {
337     QTest::addColumn<QGeoCoordinate>("c1");
338     QTest::addColumn<QGeoCoordinate>("c2");
339     QTest::addColumn<QGeoCoordinate>("c3");
340     QTest::addColumn<qreal>("width");
341     QTest::addColumn<QGeoCoordinate>("probe");
342     QTest::addColumn<bool>("result");
343 
344     QList<QGeoCoordinate> c;
345     c.append(QGeoCoordinate(1,1));
346     c.append(QGeoCoordinate(2,2));
347     c.append(QGeoCoordinate(3,0));
348 
349     QTest::newRow("One of the points") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(2, 2) << true;
350     QTest::newRow("Not so far away") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(0, 0) << false;
351     QTest::newRow("Inside the bounds") << c[0] << c[1] << c[2] << 100.0 << QGeoCoordinate(1, 0) << true;
352     QTest::newRow("Inside the bounds") << c[0] << c[1] << c[2] << 100.0 << QGeoCoordinate(1.1, 0.1) << true;
353 }
354 
boundingGeoRectangle()355 void tst_QGeoPath::boundingGeoRectangle()
356 {
357     QFETCH(QGeoCoordinate, c1);
358     QFETCH(QGeoCoordinate, c2);
359     QFETCH(QGeoCoordinate, c3);
360     QFETCH(qreal, width);
361     QFETCH(QGeoCoordinate, probe);
362     QFETCH(bool, result);
363 
364     QList<QGeoCoordinate> coords;
365     coords.append(c1);
366     coords.append(c2);
367     coords.append(c3);
368     QGeoPath p(coords, width);
369 
370     QGeoRectangle box = p.boundingGeoRectangle();
371     QCOMPARE(box.contains(probe), result);
372 }
373 
extendShape()374 void tst_QGeoPath::extendShape()
375 {
376     QFETCH(QGeoCoordinate, c1);
377     QFETCH(QGeoCoordinate, c2);
378     QFETCH(QGeoCoordinate, c3);
379     QFETCH(qreal, width);
380     QFETCH(QGeoCoordinate, probe);
381     QFETCH(bool, before);
382     QFETCH(bool, after);
383 
384     QList<QGeoCoordinate> coords;
385     coords.append(c1);
386     coords.append(c2);
387     coords.append(c3);
388     QGeoPath p(coords, width);
389 
390 
391     QCOMPARE(p.contains(probe), before);
392     p.extendShape(probe);
393     QCOMPARE(p.contains(probe), after);
394 }
395 
extendShape_data()396 void tst_QGeoPath::extendShape_data()
397 {
398     QTest::addColumn<QGeoCoordinate>("c1");
399     QTest::addColumn<QGeoCoordinate>("c2");
400     QTest::addColumn<QGeoCoordinate>("c3");
401     QTest::addColumn<qreal>("width");
402     QTest::addColumn<QGeoCoordinate>("probe");
403     QTest::addColumn<bool>("before");
404     QTest::addColumn<bool>("after");
405 
406     QList<QGeoCoordinate> c;
407     c.append(QGeoCoordinate(1,1));
408     c.append(QGeoCoordinate(2,2));
409     c.append(QGeoCoordinate(3,0));
410 
411     QTest::newRow("One of the points") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(2, 2) << true << true;
412     QTest::newRow("Not so far away") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(0, 0) << false << true;
413     QTest::newRow("Not so far away and large line") << c[0] << c[1] << c[2] << 100000.0 << QGeoCoordinate(0.8, 0.8) << true << true;
414 }
415 
416 QTEST_MAIN(tst_QGeoPath)
417 #include "tst_qgeopath.moc"
418