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 QtPositioning module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
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 Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "locationsingleton.h" |
41 | #include <QtPositioning/private/qwebmercator_p.h> |
42 | #include <QtPositioning/private/qdoublevector2d_p.h> |
43 | #include <QDebug> |
44 | |
45 | static QGeoCoordinate parseCoordinate(const QJSValue &value, bool *ok) |
46 | { |
47 | QGeoCoordinate c; |
48 | |
49 | if (value.isObject()) { |
50 | if (value.hasProperty(QStringLiteral("latitude" ))) |
51 | c.setLatitude(value.property(QStringLiteral("latitude" )).toNumber()); |
52 | if (value.hasProperty(QStringLiteral("longitude" ))) |
53 | c.setLongitude(value.property(QStringLiteral("longitude" )).toNumber()); |
54 | if (value.hasProperty(QStringLiteral("altitude" ))) |
55 | c.setAltitude(value.property(QStringLiteral("altitude" )).toNumber()); |
56 | |
57 | if (ok) |
58 | *ok = true; |
59 | } |
60 | |
61 | return c; |
62 | } |
63 | |
64 | |
65 | /*! |
66 | \qmltype QtPositioning |
67 | \instantiates LocationSingleton |
68 | \inqmlmodule QtPositioning |
69 | \since 5.2 |
70 | |
71 | \brief The QtPositioning global object provides useful functions for working with location-based |
72 | types in QML. |
73 | |
74 | \qml |
75 | import QtPositioning 5.2 |
76 | |
77 | Item { |
78 | property variant coordinate: QtPositioning.coordinate(-27.5, 153.1) |
79 | } |
80 | \endqml |
81 | */ |
82 | |
83 | LocationSingleton::LocationSingleton(QObject *parent) |
84 | : QObject(parent) |
85 | { |
86 | } |
87 | |
88 | /*! |
89 | \qmlmethod coordinate ::QtPositioning::coordinate() |
90 | |
91 | Constructs an invalid coordinate. |
92 | |
93 | */ |
94 | QGeoCoordinate LocationSingleton::coordinate() const |
95 | { |
96 | return QGeoCoordinate(); |
97 | } |
98 | |
99 | /*! |
100 | \qmlmethod coordinate QtPositioning::coordinate(real latitude, real longitude, real altitude) const |
101 | |
102 | Constructs a coordinate with the specified \a latitude, \a longitude and optional \a altitude. |
103 | Both \a latitude and \a longitude must be valid, otherwise an invalid coordinate is returned. |
104 | |
105 | \sa {coordinate} |
106 | */ |
107 | QGeoCoordinate LocationSingleton::coordinate(double latitude, double longitude, double altitude) const |
108 | { |
109 | return QGeoCoordinate(latitude, longitude, altitude); |
110 | } |
111 | |
112 | /*! |
113 | \qmlmethod geoshape QtPositioning::shape() const |
114 | |
115 | Constructs an invalid geoshape. |
116 | |
117 | \sa {geoshape} |
118 | */ |
119 | QGeoShape LocationSingleton::shape() const |
120 | { |
121 | return QGeoShape(); |
122 | } |
123 | |
124 | /*! |
125 | \qmlmethod georectangle QtPositioning::rectangle() const |
126 | |
127 | Constructs an invalid georectangle. |
128 | |
129 | \sa {georectangle} |
130 | */ |
131 | QGeoRectangle LocationSingleton::rectangle() const |
132 | { |
133 | return QGeoRectangle(); |
134 | } |
135 | |
136 | /*! |
137 | \qmlmethod georectangle QtPositioning::rectangle(coordinate center, real width, real height) const |
138 | |
139 | Constructs a georectangle centered at \a center with a width of \a width degrees and a hight of |
140 | \a height degrees. |
141 | |
142 | \sa {georectangle} |
143 | */ |
144 | QGeoRectangle LocationSingleton::rectangle(const QGeoCoordinate ¢er, |
145 | double width, double height) const |
146 | { |
147 | return QGeoRectangle(center, width, height); |
148 | } |
149 | |
150 | /*! |
151 | \qmlmethod georectangle QtPositioning::rectangle(coordinate topLeft, coordinate bottomRight) const |
152 | |
153 | Constructs a georectangle with its top left corner positioned at \a topLeft and its bottom |
154 | right corner positioned at \a {bottomRight}. |
155 | |
156 | \sa {georectangle} |
157 | */ |
158 | QGeoRectangle LocationSingleton::rectangle(const QGeoCoordinate &topLeft, |
159 | const QGeoCoordinate &bottomRight) const |
160 | { |
161 | return QGeoRectangle(topLeft, bottomRight); |
162 | } |
163 | |
164 | /*! |
165 | \qmlmethod georectangle QtLocation5::QtLocation::rectangle(list<coordinate> coordinates) const |
166 | |
167 | Constructs a georectangle from the list of coordinates, the returned list is the smallest possible |
168 | containing all the coordinates. |
169 | |
170 | \sa {georectangle} |
171 | */ |
172 | QGeoRectangle LocationSingleton::rectangle(const QVariantList &coordinates) const |
173 | { |
174 | QList<QGeoCoordinate> internalCoordinates; |
175 | for (int i = 0; i < coordinates.size(); i++) { |
176 | if (coordinates.at(i).canConvert<QGeoCoordinate>()) |
177 | internalCoordinates << coordinates.at(i).value<QGeoCoordinate>(); |
178 | } |
179 | return QGeoRectangle(internalCoordinates); |
180 | } |
181 | |
182 | /*! |
183 | \qmlmethod geocircle QtPositioning::circle() const |
184 | |
185 | Constructs an invalid geocircle. |
186 | |
187 | \sa {geocircle} |
188 | */ |
189 | QGeoCircle LocationSingleton::circle() const |
190 | { |
191 | return QGeoCircle(); |
192 | } |
193 | |
194 | /*! |
195 | \qmlmethod geocircle QtPositioning::circle(coordinate center, real radius) const |
196 | |
197 | Constructs a geocircle centered at \a center with a radius of \a radius meters. |
198 | */ |
199 | QGeoCircle LocationSingleton::circle(const QGeoCoordinate ¢er, qreal radius) const |
200 | { |
201 | return QGeoCircle(center, radius); |
202 | } |
203 | |
204 | /*! |
205 | \qmlmethod geopath QtPositioning::path() const |
206 | |
207 | Constructs an empty geopath. |
208 | |
209 | \sa {geopath} |
210 | \since 5.9 |
211 | */ |
212 | QGeoPath LocationSingleton::path() const |
213 | { |
214 | return QGeoPath(); |
215 | } |
216 | |
217 | /*! |
218 | \qmlmethod geopath QtPositioning::path(list<coordinate> coordinates, real width) const |
219 | |
220 | Constructs a geopath from coordinates and width. |
221 | |
222 | \sa {geopath} |
223 | \since 5.9 |
224 | */ |
225 | QGeoPath LocationSingleton::path(const QJSValue &value, qreal width) const |
226 | { |
227 | QList<QGeoCoordinate> pathList; |
228 | |
229 | if (value.isArray()) { |
230 | quint32 length = value.property(QStringLiteral("length" )).toUInt(); |
231 | for (quint32 i = 0; i < length; ++i) { |
232 | bool ok; |
233 | QGeoCoordinate c = parseCoordinate(value: value.property(arrayIndex: i), ok: &ok); |
234 | |
235 | if (!ok || !c.isValid()) { |
236 | pathList.clear(); // aborting |
237 | break; |
238 | } |
239 | |
240 | pathList.append(t: c); |
241 | } |
242 | } |
243 | |
244 | return QGeoPath(pathList, width); |
245 | } |
246 | |
247 | /*! |
248 | \qmlmethod geopolygon QtPositioning::polygon() const |
249 | |
250 | Constructs an empty polygon. |
251 | |
252 | \sa {geopolygon} |
253 | \since 5.10 |
254 | */ |
255 | QGeoPolygon LocationSingleton::polygon() const |
256 | { |
257 | return QGeoPolygon(); |
258 | } |
259 | |
260 | /*! |
261 | \qmlmethod geopolygon QtPositioning::polygon(list<coordinate> coordinates) const |
262 | |
263 | Constructs a polygon from coordinates. |
264 | |
265 | \sa {geopolygon} |
266 | \since 5.10 |
267 | */ |
268 | QGeoPolygon LocationSingleton::polygon(const QVariantList &coordinates) const |
269 | { |
270 | QList<QGeoCoordinate> internalCoordinates; |
271 | for (int i = 0; i < coordinates.size(); i++) { |
272 | if (coordinates.at(i).canConvert<QGeoCoordinate>()) |
273 | internalCoordinates << coordinates.at(i).value<QGeoCoordinate>(); |
274 | } |
275 | return QGeoPolygon(internalCoordinates); |
276 | } |
277 | |
278 | /*! |
279 | \qmlmethod geopolygon QtPositioning::polygon(list<coordinate> perimeter, list<list<coordinate>> holes) const |
280 | |
281 | Constructs a polygon from coordinates for perimeter and inner holes. |
282 | |
283 | \sa {geopolygon} |
284 | \since 5.12 |
285 | */ |
286 | QGeoPolygon LocationSingleton::polygon(const QVariantList &perimeter, const QVariantList &holes) const |
287 | { |
288 | QList<QGeoCoordinate> internalCoordinates; |
289 | for (int i = 0; i < perimeter.size(); i++) { |
290 | if (perimeter.at(i).canConvert<QGeoCoordinate>()) |
291 | internalCoordinates << perimeter.at(i).value<QGeoCoordinate>(); |
292 | } |
293 | QGeoPolygon poly(internalCoordinates); |
294 | |
295 | for (int i = 0; i < holes.size(); i++) { |
296 | if (holes.at(i).type() == QVariant::List) { |
297 | QList<QGeoCoordinate> hole; |
298 | const QVariantList &holeData = holes.at(i).toList(); |
299 | for (int j = 0; j < holeData.size(); j++) { |
300 | if (holeData.at(i: j).canConvert<QGeoCoordinate>()) |
301 | hole << holeData.at(i: j).value<QGeoCoordinate>(); |
302 | } |
303 | if (hole.size()) |
304 | poly.addHole(holePath: hole); |
305 | } |
306 | } |
307 | |
308 | return poly; |
309 | } |
310 | |
311 | /*! |
312 | \qmlmethod geocircle QtPositioning::shapeToCircle(geoshape shape) const |
313 | |
314 | Converts \a shape to a geocircle. |
315 | |
316 | \sa {geocircle} |
317 | \since 5.5 |
318 | */ |
319 | QGeoCircle LocationSingleton::shapeToCircle(const QGeoShape &shape) const |
320 | { |
321 | return QGeoCircle(shape); |
322 | } |
323 | |
324 | /*! |
325 | \qmlmethod georectangle QtPositioning::shapeToRectangle(geoshape shape) const |
326 | |
327 | Converts \a shape to a georectangle. |
328 | |
329 | \sa {georectangle} |
330 | \since 5.5 |
331 | */ |
332 | QGeoRectangle LocationSingleton::shapeToRectangle(const QGeoShape &shape) const |
333 | { |
334 | return QGeoRectangle(shape); |
335 | } |
336 | |
337 | /*! |
338 | \qmlmethod geopath QtPositioning::shapeToPath(geoshape shape) const |
339 | |
340 | Converts \a shape to a geopath. |
341 | |
342 | \sa {geopath} |
343 | \since 5.9 |
344 | */ |
345 | QGeoPath LocationSingleton::shapeToPath(const QGeoShape &shape) const |
346 | { |
347 | return QGeoPath(shape); |
348 | } |
349 | |
350 | /*! |
351 | \qmlmethod geopolygon QtPositioning::shapeToPolygon(geoshape shape) const |
352 | |
353 | Converts \a shape to a polygon. |
354 | |
355 | \sa {geopolygon} |
356 | \since 5.10 |
357 | */ |
358 | QGeoPolygon LocationSingleton::shapeToPolygon(const QGeoShape &shape) const |
359 | { |
360 | return QGeoPolygon(shape); |
361 | } |
362 | |
363 | /*! |
364 | \qmlmethod coordinate QtPositioning::mercatorToCoord(point mercator) const |
365 | |
366 | Converts a \a mercator coordinate into a latitude-longitude coordinate. |
367 | |
368 | \sa {coordToMercator} |
369 | \since 5.12 |
370 | */ |
371 | QGeoCoordinate LocationSingleton::mercatorToCoord(const QPointF &mercator) const |
372 | { |
373 | return QWebMercator::mercatorToCoord(mercator: QDoubleVector2D(mercator.x(), mercator.y())); |
374 | } |
375 | |
376 | /*! |
377 | \qmlmethod point QtPositioning::coordToMercator(coordinate coord) const |
378 | |
379 | Converts a coordinate \a coord into a mercator coordinate and returns it. |
380 | \sa {mercatorToCoord} |
381 | \since 5.12 |
382 | */ |
383 | QPointF LocationSingleton::coordToMercator(const QGeoCoordinate &coord) const |
384 | { |
385 | return QWebMercator::coordToMercator(coord).toPointF(); |
386 | } |
387 | |