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
qgeopositioninfo.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
4#include "private/qgeopositioninfo_p.h"
5#include <QHash>
6#include <QDebug>
7#include <QDataStream>
8#include <QtCore/QtNumeric>
9
10#include <algorithm>
11
12QT_BEGIN_NAMESPACE
13
14QT_IMPL_METATYPE_EXTERN(QGeoPositionInfo)
15
16/*!
17 \class QGeoPositionInfo
18 \inmodule QtPositioning
19 \ingroup QtPositioning-positioning
20 \ingroup shared
21 \since 5.2
22
23 \brief The QGeoPositionInfo class contains information gathered on a global position, direction and velocity at a particular point in time.
24
25 A QGeoPositionInfo contains, at a minimum, a geographical coordinate and
26 a timestamp. It may also have heading and speed measurements as well as
27 estimates of the accuracy of the provided data.
28
29 \sa QGeoPositionInfoSource
30*/
31
32/*!
33 \enum QGeoPositionInfo::Attribute
34 Defines the attributes for positional information.
35
36 \value Direction The bearing measured in degrees clockwise from true north to the direction of travel.
37 \value GroundSpeed The ground speed, in meters/sec.
38 \value VerticalSpeed The vertical speed, in meters/sec.
39 \value MagneticVariation The angle between the horizontal component of the magnetic field and true north, in degrees. Also known as magnetic declination. A positive value indicates a clockwise direction from true north and a negative value indicates a counter-clockwise direction.
40 \value HorizontalAccuracy The accuracy of the provided latitude-longitude value, in meters.
41 \value VerticalAccuracy The accuracy of the provided altitude value, in meters.
42 \value DirectionAccuracy The accuracy of the provided bearing, in degrees.
43 This attribute is available only on Android (API level 26 or above) and
44 macOS/iOS. See corresponding \l {Android getBearingAccuracyDegrees}
45 {Android} and \l {iOS courseAccuracy}{Apple} documentation for more details.
46
47 NMEA protocol also suggests another type of accuracy - PositionAccuracy,
48 which is a 3D accuracy value. Qt does not provide a separate attribute for
49 it. If you need this value, you can calculate it based on the following
50 formula:
51
52 \c {PositionAccuracy} \sup 2 \c {= HorizontalAccuracy} \sup 2 \c { +
53 VerticalAccuracy} \sup 2
54*/
55
56/*!
57 Creates an invalid QGeoPositionInfo object.
58
59 \sa isValid()
60*/
61QGeoPositionInfo::QGeoPositionInfo()
62 : d(new QGeoPositionInfoPrivate)
63{
64}
65
66/*!
67 Creates a QGeoPositionInfo for the given \a coordinate and \a timestamp.
68*/
69QGeoPositionInfo::QGeoPositionInfo(const QGeoCoordinate &coordinate, const QDateTime &timestamp)
70 : d(new QGeoPositionInfoPrivate)
71{
72 d->timestamp = timestamp;
73 d->coord = coordinate;
74}
75
76/*!
77 Creates a QGeoPositionInfo with the values of \a other.
78*/
79QGeoPositionInfo::QGeoPositionInfo(const QGeoPositionInfo &other)
80 : d(other.d)
81{
82}
83
84/*!
85 \fn QGeoPositionInfo::QGeoPositionInfo(QGeoPositionInfo &&other) noexcept
86 \since 6.2
87
88 Creates a QGeoPositionInfo object by moving from \a other.
89
90 Note that a moved-from QGeoPositionInfo can only be destroyed or
91 assigned to. The effect of calling other functions than the destructor
92 or one of the assignment operators is undefined.
93*/
94
95QGeoPositionInfo::QGeoPositionInfo(QGeoPositionInfoPrivate &dd) : d(&dd)
96{
97}
98
99/*!
100 Destroys a QGeoPositionInfo object.
101*/
102QGeoPositionInfo::~QGeoPositionInfo()
103{
104}
105
106QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QGeoPositionInfoPrivate)
107
108/*!
109 Assigns the values from \a other to this QGeoPositionInfo.
110*/
111QGeoPositionInfo &QGeoPositionInfo::operator=(const QGeoPositionInfo & other)
113 if (this == &other)
114 return *this;
115
116 d = other.d;
117 return *this;
118}
119
120/*!
121 \fn QGeoPositionInfo &QGeoPositionInfo::operator=(QGeoPositionInfo &&other) noexcept
122 \since 6.2
123
124 Move-assigns the values from \a other to this object.
125
126 Note that a moved-from QGeoPositionInfo can only be destroyed or
127 assigned to. The effect of calling other functions than the destructor
128 or one of the assignment operators is undefined.
129*/
130
131/*!
132 \fn bool QGeoPositionInfo::operator==(const QGeoPositionInfo &lhs, const QGeoPositionInfo &rhs)
133
134 Returns \c true if all of the \a lhs object's values are the same as those
135 of \a rhs. Otherwise returns \c false.
136*/
137
138/*!
139 \fn bool QGeoPositionInfo::operator!=(const QGeoPositionInfo &lhs, const QGeoPositionInfo &rhs)
140
141 Returns \c true if any of the \a lhs object's values are not the same as
142 those of \a rhs. Otherwise returns \c false.
143*/
144
145/*!
146 \fn void QGeoPositionInfo::swap(QGeoPositionInfo &other)
147 \since 6.2
148 \memberswap{position information}
149*/
150
151/*!
152 Returns true if the timestamp() and coordinate() values are both valid.
153
154 \sa QGeoCoordinate::isValid(), QDateTime::isValid()
155*/
156bool QGeoPositionInfo::isValid() const
157{
158 return d->timestamp.isValid() && d->coord.isValid();
159}
160
161/*!
162 Sets the date and time at which this position was reported to \a timestamp.
163
164 The \a timestamp must be in UTC time.
165
166 \sa timestamp()
167*/
168void QGeoPositionInfo::setTimestamp(const QDateTime &timestamp)
169{
170 d.detach();
171 d->timestamp = timestamp;
172}
173
174/*!
175 Returns the date and time at which this position was reported, in UTC time.
176
177 Returns an invalid QDateTime if no date/time value has been set.
178
179 \sa setTimestamp()
180*/
181QDateTime QGeoPositionInfo::timestamp() const
182{
183 return d->timestamp;
184}
185
186/*!
187 Sets the coordinate for this position to \a coordinate.
188
189 \sa coordinate()
190*/
191void QGeoPositionInfo::setCoordinate(const QGeoCoordinate &coordinate)
192{
193 d.detach();
194 d->coord = coordinate;
195}
196
197/*!
198 Returns the coordinate for this position.
199
200 Returns an invalid coordinate if no coordinate has been set.
201
202 \sa setCoordinate()
203*/
204QGeoCoordinate QGeoPositionInfo::coordinate() const
205{
206 return d->coord;
207}
208
209/*!
210 Sets the value for \a attribute to \a value.
211
212 \sa attribute()
213*/
214void QGeoPositionInfo::setAttribute(Attribute attribute, qreal value)
215{
216 d.detach();
217 d->doubleAttribs[attribute] = value;
218}
219
220/*!
221 Returns the value of the specified \a attribute as a qreal value.
222
223 Returns NaN if the value has not been set.
224
225 The function hasAttribute() should be used to determine whether or
226 not a value has been set for an attribute.
227
228 \sa hasAttribute(), setAttribute()
229*/
230qreal QGeoPositionInfo::attribute(Attribute attribute) const
231{
232 if (d->doubleAttribs.contains(attribute))
233 return d->doubleAttribs[attribute];
234 return qQNaN();
235}
236
237/*!
238 Removes the specified \a attribute and its value.
239*/
240void QGeoPositionInfo::removeAttribute(Attribute attribute)
241{
242 d.detach();
243 d->doubleAttribs.remove(attribute);
244}
245
246/*!
247 Returns true if the specified \a attribute is present for this
248 QGeoPositionInfo object.
249*/
250bool QGeoPositionInfo::hasAttribute(Attribute attribute) const
251{
252 return d->doubleAttribs.contains(attribute);
253}
254
255/*!
256 \internal
257*/
258void QGeoPositionInfo::detach()
259{
260 if (d)
261 d.detach();
262 else
263 d = new QGeoPositionInfoPrivate;
264}
265
266bool QGeoPositionInfo::equals(const QGeoPositionInfo &lhs, const QGeoPositionInfo &rhs)
267{
268 return *lhs.d == *rhs.d;
269}
270
271#ifndef QT_NO_DEBUG_STREAM
272QDebug QGeoPositionInfo::debugStreaming(QDebug dbg, const QGeoPositionInfo &info)
273{
274 QDebugStateSaver saver(dbg);
275 dbg.nospace() << "QGeoPositionInfo(" << info.d->timestamp;
276 dbg.nospace() << ", "; // timestamp force dbg.space() -> reverting here
277 dbg << info.d->coord;
278
279 QList<QGeoPositionInfo::Attribute> attribs = info.d->doubleAttribs.keys();
280 std::stable_sort(attribs.begin(), attribs.end()); // Output a sorted list from an unsorted hash.
281 for (int i = 0; i < attribs.size(); ++i) {
282 dbg << ", ";
283 switch (attribs[i]) {
284 case QGeoPositionInfo::Direction:
285 dbg << "Direction=";
286 break;
287 case QGeoPositionInfo::GroundSpeed:
288 dbg << "GroundSpeed=";
289 break;
290 case QGeoPositionInfo::VerticalSpeed:
291 dbg << "VerticalSpeed=";
292 break;
293 case QGeoPositionInfo::MagneticVariation:
294 dbg << "MagneticVariation=";
295 break;
296 case QGeoPositionInfo::HorizontalAccuracy:
297 dbg << "HorizontalAccuracy=";
298 break;
299 case QGeoPositionInfo::VerticalAccuracy:
300 dbg << "VerticalAccuracy=";
301 break;
302 case QGeoPositionInfo::DirectionAccuracy:
303 dbg << "DirectionAccuracy=";
304 break;
305 }
306 dbg << info.d->doubleAttribs[attribs[i]];
307 }
308 dbg << ')';
309 return dbg;
310}
311#endif
312
313
314#ifndef QT_NO_DATASTREAM
315/*!
316 \fn QDataStream &QGeoPositionInfo::operator<<(QDataStream &stream, QGeoPositionInfo::Attribute attr)
317
318 Writes the given \a attr enumeration to the specified \a stream.
319
320 \sa {Serializing Qt Data Types}
321*/
322QDataStream &QGeoPositionInfo::dataStreamOut(QDataStream &stream, QGeoPositionInfo::Attribute attr)
323{
324 return stream << qint32(attr);
325}
326
327/*!
328 \fn QDataStream &QGeoPositionInfo::operator>>(QDataStream &stream, QGeoPositionInfo::Attribute &attr)
329
330 Reads an attribute enumeration from the specified \a stream info the given \a attr.
331
332 \sa {Serializing Qt Data Types}
333*/
334QDataStream &QGeoPositionInfo::dataStreamIn(QDataStream &stream, QGeoPositionInfo::Attribute &attr)
335{
336 qint32 a;
337 stream >> a;
338 attr = static_cast<QGeoPositionInfo::Attribute>(a);
339 return stream;
340}
341
342/*!
343 \fn QDataStream &QGeoPositionInfo::operator<<(QDataStream &stream, const QGeoPositionInfo &info)
344
345 Writes the given \a info to the specified \a stream.
346
347 \sa {Serializing Qt Data Types}
348*/
349
350QDataStream &QGeoPositionInfo::dataStreamOut(QDataStream &stream, const QGeoPositionInfo &info)
351{
352 stream << info.d->timestamp;
353 stream << info.d->coord;
354 stream << info.d->doubleAttribs;
355 return stream;
356}
357
358/*!
359 \fn QDataStream &QGeoPositionInfo::operator>>(QDataStream &stream, QGeoPositionInfo &info)
360
361 Reads a coordinate from the specified \a stream into the given
362 \a info.
363
364 \sa {Serializing Qt Data Types}
365*/
366
367QDataStream &QGeoPositionInfo::dataStreamIn(QDataStream &stream, QGeoPositionInfo &info)
368{
369 stream >> info.d->timestamp;
370 stream >> info.d->coord;
371 stream >> info.d->doubleAttribs;
372 return stream;
373}
374#endif
375
376QGeoPositionInfoPrivate::QGeoPositionInfoPrivate() : QSharedData()
377{
378}
379
380QGeoPositionInfoPrivate::QGeoPositionInfoPrivate(const QGeoPositionInfoPrivate &other)
381 : QSharedData(other),
382 timestamp(other.timestamp),
383 coord(other.coord),
384 doubleAttribs(other.doubleAttribs)
385{
386}
387
388QGeoPositionInfoPrivate::~QGeoPositionInfoPrivate()
389{
390
391}
392
393bool QGeoPositionInfoPrivate::operator==(const QGeoPositionInfoPrivate &other) const
394{
395 return timestamp == other.timestamp
396 && coord == other.coord
397 && doubleAttribs == other.doubleAttribs;
398}
399
400QGeoPositionInfoPrivate *QGeoPositionInfoPrivate::get(const QGeoPositionInfo &info)
401{
402 return info.d.data();
403}
404
405size_t qHash(const QGeoPositionInfo &key, size_t seed) noexcept
406{
407 return qHashMulti(seed, key.d->coord);
408}
409
410namespace QTest
411{
412
413char *toString(const QGeoPositionInfo &info)
414{
415 QString result;
416 QDebug dbg(&result);
417 dbg << info;
418
419 return qstrdup(qPrintable(result));
420}
421
422} // namespace QTest
423
424QT_END_NAMESPACE