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

source code of qtlocation/tests/auto/qgeopolygon/tst_qgeopolygon.cpp