Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
positioningplugin.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <private/qpositioningquickglobal_p.h>
6#include <QGeoCircle>
7#include <QGeoCoordinate>
8#include <QGeoPath>
9#include <QGeoPolygon>
10#include <QGeoRectangle>
11#include <QtPositioningQuick/private/qquickgeocoordinateanimation_p.h>
12#include <QtCore/QVariantAnimation>
13#include <QtQml/QQmlEngineExtensionPlugin>
14
15QT_BEGIN_NAMESPACE
16
17/*!
18 \qmlvaluetype geoCoordinate
19 \ingroup qmlvaluetypes
20 \inqmlmodule QtPositioning
21 \since 5.2
22
23 \brief The geoCoordinate type represents and stores a geographic position.
24
25 This type is a QML representation of \l QGeoCoordinate and represents a geographic
26 position in the form of \l {latitude}, \l longitude and \l altitude attributes.
27 The \l latitude attribute specifies the number of
28 decimal degrees above and below the equator. A positive latitude indicates the Northern
29 Hemisphere and a negative latitude indicates the Southern Hemisphere. The \l longitude
30 attribute specifies the number of decimal degrees east and west. A positive longitude
31 indicates the Eastern Hemisphere and a negative longitude indicates the Western Hemisphere.
32 The \l altitude attribute specifies the number of meters above sea level. Together, these
33 attributes specify a 3-dimensional position anywhere on or near the Earth's surface.
34
35 The \l isValid attribute can be used to test if a coordinate is valid. A coordinate is
36 considered valid if it has a valid latitude and longitude. A valid altitude is not required.
37 The latitude must be between -90 and 90 inclusive and the longitude must be between -180 and
38 180 inclusive.
39
40 The geoCoordinate type is used by many other types in the Qt Location module, for specifying
41 the position of an object on a Map, the current position of a device and many other tasks.
42 They also feature a number of important utility methods that make otherwise complex
43 calculations simple to use, such as \l {atDistanceAndAzimuth}().
44
45 \section1 Accuracy
46
47 The latitude, longitude and altitude attributes stored in the geoCoordinate type are represented
48 as doubles, giving them approximately 16 decimal digits of precision -- enough to specify
49 micrometers. The calculations performed in geoCoordinate's methods such as \l {azimuthTo}() and
50 \l {distanceTo}() also use doubles for all intermediate values, but the inherent inaccuracies in
51 their spherical Earth model dominate the amount of error in their output.
52
53 \section1 Example Usage
54
55 To create a geoCoordinate use one of the methods described below. In all cases, specifying the
56 \l altitude attribute is optional.
57
58 To create a geoCoordinate value, use the \l{QtPositioning::coordinate}{QtPositioning.coordinate()}
59 function:
60
61 \qml
62 import QtPositioning
63
64 Location { coordinate: QtPositioning.coordinate(-27.5, 153.1) }
65 \endqml
66
67 or as separate \l latitude, \l longitude and \l altitude components:
68
69 \qml
70 Location {
71 coordinate {
72 latitude: -27.5
73 longitude: 153.1
74 }
75 }
76 \endqml
77
78 When integrating with C++, note that any QGeoCoordinate value passed into QML from C++ is
79 automatically converted into a geoCoordinate value, and vice-versa.
80*/
81
82/*!
83 \qmlproperty real geoCoordinate::latitude
84
85 This property holds the latitude value of the geographical position
86 (decimal degrees). A positive latitude indicates the Northern Hemisphere,
87 and a negative latitude indicates the Southern Hemisphere.
88 If the property has not been set, its default value is NaN.
89
90 For more details see the \l {QGeoCoordinate::latitude} property
91*/
92
93/*!
94 \qmlproperty real geoCoordinate::longitude
95
96 This property holds the longitude value of the geographical position
97 (decimal degrees). A positive longitude indicates the Eastern Hemisphere,
98 and a negative longitude indicates the Western Hemisphere
99 If the property has not been set, its default value is NaN.
100
101 For more details see the \l {QGeoCoordinate::longitude} property
102*/
103
104/*!
105 \qmlproperty real geoCoordinate::altitude
106
107 This property holds the altitude value (meters above sea level).
108 If the property has not been set, its default value is NaN.
109
110 For more details see the \l {QGeoCoordinate::altitude} property
111*/
112
113/*!
114 \qmlproperty bool geoCoordinate::isValid
115
116 This property holds the current validity of the coordinate. Coordinates
117 are considered valid if they have been set with a valid latitude and
118 longitude (altitude is not required).
119
120 The latitude must be between -90 to 90 inclusive to be considered valid,
121 and the longitude must be between -180 to 180 inclusive to be considered
122 valid.
123
124 This is a read-only property.
125*/
126
127/*!
128 \qmlmethod real geoCoordinate::distanceTo(geoCoordinate other)
129
130 Returns the distance (in meters) from this coordinate to the coordinate specified by \a other.
131 Altitude is not used in the calculation.
132
133 This calculation returns the great-circle distance between the two coordinates, with an
134 assumption that the Earth is spherical for the purpose of this calculation.
135*/
136
137/*!
138 \qmlmethod real geoCoordinate::azimuthTo(geoCoordinate other)
139
140 Returns the azimuth (or bearing) in degrees from this coordinate to the coordinate specified by
141 \a other. Altitude is not used in the calculation.
142
143 There is an assumption that the Earth is spherical for the purpose of this calculation.
144*/
145
146/*!
147 \qmlmethod geoCoordinate geoCoordinate::atDistanceAndAzimuth(real distance, real azimuth)
148
149 Returns the coordinate that is reached by traveling \a distance metres from this coordinate at
150 \a azimuth degrees along a great-circle.
151
152 There is an assumption that the Earth is spherical for the purpose of this calculation.
153*/
154
155/*!
156 \qmlvaluetype geoShape
157 \ingroup qmlvaluetypes
158 \inqmlmodule QtPositioning
159 \since 5.2
160
161 \brief A geoShape type represents an abstract geographic area.
162
163 This type is a QML representation of \l QGeoShape which is an abstract geographic area.
164 It includes attributes and methods common to all geographic areas. To create objects
165 that represent a valid geographic area use \l {geoRectangle} or \l {geoCircle}.
166
167 The \l isValid attribute can be used to test if the shape represents a valid geographic
168 area.
169
170 The \l isEmpty attribute can be used to test if the shape represents a region with a
171 geometrical area of 0.
172
173 The \l {contains}() method can be used to test if a \l geoCoordinate is
174 within the shape.
175
176 \section1 Example Usage
177
178 To create a geoShape value, use the
179 \l {QtPositioning::shape}{QtPositioning.shape()} function:
180
181 \qml
182 import QtPositioning
183
184 Item {
185 property geoShape region: QtPositioning.shape()
186 }
187 \endqml
188
189 When integrating with C++, note that any QGeoShape value passed into QML from C++ is
190 automatically converted into a geoShape value, and vice-versa.
191*/
192
193/*!
194 \qmlproperty bool geoShape::isEmpty
195
196 Returns whether this shape is empty. An empty shape is a region which has
197 a geometrical area of 0.
198*/
199
200/*!
201 \qmlproperty bool geoShape::isValid
202
203 Returns whether this shape is valid.
204
205 A shape is considered to be invalid if some of the data that is required to
206 unambiguously describe the shape has not been set or has been set to an
207 unsuitable value.
208*/
209
210/*!
211 \qmlproperty ShapeType geoShape::type
212
213 Returns the current type of the shape.
214
215 \list
216 \li \c GeoShape.UnknownType - The shape's type is not known.
217 \li \c GeoShape.RectangleType - The shape is a \l geoRectangle.
218 \li \c GeoShape.CircleType - The shape is a \l geoCircle.
219 \li \c GeoShape.PathType - The shape is a \l geoPath. (Since Qt 5.9)
220 \li \c GeoShape.PolygonType - The shape is a \l geoPolygon. (Since Qt 5.10)
221 \endlist
222
223 This QML property was introduced by Qt 5.5.
224*/
225
226/*!
227 \qmlmethod bool geoShape::contains(geoCoordinate coord)
228
229 Returns true if the \l {QtPositioning::geoCoordinate}{coordinate} specified by \a coord is within
230 this shape; otherwise returns false.
231*/
232
233/*!
234 \qmlvaluetype geoRectangle
235 \ingroup qmlvaluetypes
236 \inqmlmodule QtPositioning
237 \since 5.2
238
239 \brief The geoRectangle type represents a rectangular geographic area.
240
241 The geoRectangle type is a \l {geoShape} that represents a
242 rectangular geographic area. The type is direct representation of a \l QGeoRectangle.
243 It is defined by a pair of \l {geoCoordinate}{coordinates} which represent the top-left
244 and bottom-right corners of the rectangle. The coordinates are accessible
245 from the \l topLeft and \l bottomRight attributes.
246
247 A rectangle is considered invalid if the top-left or bottom-right coordinates are invalid
248 or if the top-left coordinate is south of the bottom-right coordinate.
249
250 The coordinates of the four corners of the rectangle can be accessed with the
251 \l {topLeft}, \l {topRight}, \l {bottomLeft} and \l {bottomRight} attributes. The \l center
252 attribute can be used to get the coordinate of the center of the rectangle. The \l width
253 and \l height attributes can be used to get the width and height of the rectangle in
254 degrees. Setting one of these attributes will cause the other attributes to be adjusted
255 accordingly.
256
257 \section1 Limitations
258
259 A geoRectangle can never cross the poles.
260
261 If the height or center of a geoRectangle is adjusted such that it would cross one of the
262 poles the height is modified such that the rectangle touches but does not cross the pole
263 and that the center coordinate is still in the center of the rectangle.
264
265 \section1 Example Usage
266
267 To create a geoRectangle value, use the \l {QtPositioning::rectangle}{QtPositioning.rectangle()}
268 function:
269
270 \qml
271 import QtPositioning
272
273 Item {
274 property geoRectangle region: QtPositioning.rectangle(QtPositioning.coordinate(-27.5, 153.1),
275 QtPositioning.coordinate(-27.6, 153.2))
276 }
277 \endqml
278
279 When integrating with C++, note that any QGeoRectangle value passed into QML from C++ is
280 automatically converted into a geoRectangle value, and vice-versa.
281*/
282
283/*!
284 \qmlproperty geoCoordinate geoRectangle::bottomLeft
285
286 This property holds the bottom left coordinate of this geoRectangle.
287*/
288
289/*!
290 \qmlproperty geoCoordinate geoRectangle::bottomRight
291
292 This property holds the bottom right coordinate of this geoRectangle.
293*/
294
295/*!
296 \qmlproperty geoCoordinate geoRectangle::center
297
298 This property holds the center coordinate of this geoRectangle. For more details
299 see \l {QGeoRectangle::setCenter()}.
300*/
301
302/*!
303 \qmlproperty double geoRectangle::height
304
305 This property holds the height of this geoRectangle (in degrees). For more details
306 see \l {QGeoRectangle::setHeight()}.
307
308 \note If the geoRectangle is invalid, it is not possible to set the height. QtPositioning
309 releases prior to Qt 5.5 permitted the setting of the height even on invalid geoRectangles.
310*/
311
312/*!
313 \qmlproperty geoCoordinate geoRectangle::topLeft
314
315 This property holds the top left coordinate of this geoRectangle.
316*/
317
318/*!
319 \qmlproperty geoCoordinate geoRectangle::topRight
320
321 This property holds the top right coordinate of this geoRectangle.
322*/
323
324/*!
325 \qmlproperty double geoRectangle::width
326
327 This property holds the width of this geoRectangle (in degrees). For more details
328 see \l {QGeoRectangle::setWidth()}.
329
330 \note If the geoRectangle is invalid, it is not possible to set the width. QtPositioning
331 releases prior to Qt 5.5 permitted the setting of the width even on invalid geoRectangles.
332*/
333
334/*!
335 \qmlvaluetype geoCircle
336 \ingroup qmlvaluetypes
337 \inqmlmodule QtPositioning
338 \since 5.2
339
340 \brief The geoCircle type represents a circular geographic area.
341
342 The geoCircle type is a \l {geoShape} that represents a circular
343 geographic area. It is a direct representation of a \l QGeoCircle and is defined
344 in terms of a \l {geoCoordinate}{coordinate} which specifies the \l center of the circle and
345 a qreal which specifies the \l radius of the circle in meters.
346
347 The circle is considered invalid if the \l center coordinate is invalid or if
348 the \l radius is less than zero.
349
350 \section1 Example Usage
351
352 To create a geoCircle value, use the \l {QtPositioning::circle}{QtPositioning.circle()}
353 function:
354
355 \qml
356 import QtPositioning
357
358 Item {
359 property geoCircle region: QtPositioning.circle(QtPositioning.coordinate(-27.5, 153.1), 1000)
360 }
361 \endqml
362
363 When integrating with C++, any QGeoCircle value passed into QML from C++ is
364 automatically converted into a geoCircle value. Similarly, geoCircle
365 values are converted to QGeoCircle values when passed from QML to C++.
366*/
367
368/*!
369 \qmlproperty geoCoordinate geoCircle::center
370
371 This property holds the coordinate of the center of the geoCircle.
372*/
373
374/*!
375 \qmlproperty real geoCircle::radius
376
377 This property holds the radius of the geoCircle in meters.
378
379 The default value for the radius is -1 indicating an invalid geoCircle area.
380*/
381
382/*!
383 \qmlvaluetype geoPath
384 \ingroup qmlvaluetypes
385 \inqmlmodule QtPositioning
386 \since 5.9
387
388 \brief The geoPath type represents a geographic path.
389
390 The geoPath type is a \l {geoShape} that represents a geographic
391 path. It is a direct representation of a \l QGeoPath and is defined
392 in terms of a \l {path} which holds the list of geoCoordinates in the
393 path.
394
395 The path is considered invalid if it is empty.
396
397 When integrating with C++, note that any QGeoPath value passed into QML from C++ is
398 automatically converted into a geoPath value, and vice versa.
399*/
400
401/*!
402 \qmlproperty list<geoCoordinate> geoPath::path
403
404 This property holds the list of coordinates defining the path.
405*/
406
407/*!
408 \qmlproperty real geoPath::width
409
410 This property holds the width of the path in meters. This is currently only used
411 when calling the \l {geoShape::}{contains()} method.
412
413 The default value for the width is 0.
414*/
415
416/*!
417 \qmlvaluetype geoPolygon
418 \ingroup qmlvaluetypes
419 \inqmlmodule QtPositioning
420 \since 5.10
421
422 \brief The geoPolygon type represents a geographic polygon.
423
424 The geoPolygon type is a \l [QML] geoShape that represents a geographic
425 polygon. It is a direct representation of QGeoPolygon and is defined in
426 terms of a \l path which holds a list of geoCoordinates in the polygon.
427
428 The polygon is considered invalid if its path holds less than three
429 coordinates.
430
431 When integrating with C++, note that any QGeoPolygon value passed into QML
432 is automatically converted into a geoPolygon, and vice versa.
433*/
434
435/*!
436 \qmlproperty list<geoCoordinate> geoPolygon::path
437
438 This property holds the list of coordinates defining the polygon.
439*/
440
441class QtPositioningDeclarativeModule: public QQmlEngineExtensionPlugin
442{
443 Q_OBJECT
444
445 Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
446
447public:
448 QtPositioningDeclarativeModule(QObject *parent = 0) : QQmlEngineExtensionPlugin(parent)
449 {
450 volatile auto registration = &qml_register_types_QtPositioning;
451 Q_UNUSED(registration)
452 }
453};
454
455namespace {
456
457bool parseCoordinate(const QVariantMap &map, QGeoCoordinate &c)
458{
459 if (const auto it = map.find(QStringLiteral("latitude")); it != map.end())
460 c.setLatitude(it.value().toDouble());
461 else
462 c.setLatitude(qQNaN());
463 if (const auto it = map.find(QStringLiteral("longitude")); it != map.end())
464 c.setLongitude(it.value().toDouble());
465 else
466 c.setLongitude(qQNaN());
467 if (const auto it = map.find(QStringLiteral("altitude")); it != map.end())
468 c.setAltitude(it.value().toDouble());
469 else
470 c.setAltitude(qQNaN());
471
472 // Not considering the case where the map is valid but containing NaNs.
473 return c.isValid();
474}
475
476bool parseRectangle(const QVariantMap &map, QGeoRectangle &rect)
477{
478 if (const auto it = map.find(QStringLiteral("topLeft")); it != map.end())
479 rect.setTopLeft(it.value().value<QGeoCoordinate>());
480 if (const auto it = map.find(QStringLiteral("bottomLeft")); it != map.end())
481 rect.setBottomLeft(it.value().value<QGeoCoordinate>());
482 if (const auto it = map.find(QStringLiteral("topRight")); it != map.end())
483 rect.setTopRight(it.value().value<QGeoCoordinate>());
484 if (const auto it = map.find(QStringLiteral("bottomRight")); it != map.end())
485 rect.setBottomRight(it.value().value<QGeoCoordinate>());
486 if (const auto it = map.find(QStringLiteral("center")); it != map.end())
487 rect.setCenter(it.value().value<QGeoCoordinate>());
488 if (const auto it = map.find(QStringLiteral("width")); it != map.end())
489 rect.setWidth(it.value().toDouble());
490 if (const auto it = map.find(QStringLiteral("height")); it != map.end())
491 rect.setHeight(it.value().toDouble());
492
493 // Not considering the case where the map is valid but containing NaNs.
494 return rect.isValid();
495}
496}
497
499{
500 QMetaType::registerConverter<QGeoRectangle, QGeoShape>();
501 QMetaType::registerConverter<QGeoShape, QGeoRectangle>();
502 QMetaType::registerConverter<QGeoShape, QGeoCircle>();
503 QMetaType::registerConverter<QGeoCircle, QGeoShape>();
504 QMetaType::registerConverter<QGeoShape, QGeoPath>();
505 QMetaType::registerConverter<QGeoPath, QGeoShape>();
506 QMetaType::registerConverter<QGeoShape, QGeoPolygon>();
507 QMetaType::registerConverter<QGeoPolygon, QGeoShape>();
508
509 if (!QMetaType::registerConverterFunction([](const void *src, void *target) -> bool {
510 const QVariantMap &map = *static_cast<const QVariantMap *>(src);
511 QGeoCoordinate &coord = *static_cast<QGeoCoordinate *>(target);
512 return parseCoordinate(map, coord);
513 }, QMetaType::fromType<QVariantMap>(), QMetaType::fromType<QGeoCoordinate>())) {
514 qWarning("Failed to register conversion function from QVariantMap to QGeoCoordinate");
515 }
516
517 if (!QMetaType::registerConverterFunction([](const void *src, void *target) -> bool {
518 const QVariantMap &map = *static_cast<const QVariantMap *>(src);
519 QGeoRectangle &rect = *static_cast<QGeoRectangle *>(target);
520 return parseRectangle(map, rect);
521 }, QMetaType::fromType<QVariantMap>(), QMetaType::fromType<QGeoRectangle>())) {
522 qWarning("Failed to register conversion function from QVariantMap to QGeoRectangle");
523 }
524
525 qRegisterAnimationInterpolator<QGeoCoordinate>(q_coordinateInterpolator);
526}
527
528Q_CONSTRUCTOR_FUNCTION(QtPositioningDeclarative_initializeModule)
529
530QT_END_NAMESPACE
531
532#include "positioningplugin.moc"
void QtPositioningDeclarative_initializeModule()