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