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