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
qgeocoordinate.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
6
7#include <QDateTime>
8#include <QHash>
9#include <QDataStream>
10#include <QDebug>
11#include <QMetaType>
12#include <qnumeric.h>
13#include <qmath.h>
14
16
17QT_IMPL_METATYPE_EXTERN(QGeoCoordinate)
18
19static const double qgeocoordinate_EARTH_MEAN_RADIUS = 6371.0072;
20
21
22QGeoCoordinatePrivate::QGeoCoordinatePrivate():
23 lat(qQNaN()),
24 lng(qQNaN()),
25 alt(qQNaN())
26{}
27
28QGeoCoordinatePrivate::QGeoCoordinatePrivate(const QGeoCoordinatePrivate &other)
29 : QSharedData(other),
30 lat(other.lat),
31 lng(other.lng),
32 alt(other.alt)
33{}
34
35QGeoCoordinatePrivate::~QGeoCoordinatePrivate()
36{}
37
38
39QGeoMercatorCoordinatePrivate::QGeoMercatorCoordinatePrivate():
40 QGeoCoordinatePrivate(),
41 m_mercatorX(qQNaN()),
42 m_mercatorY(qQNaN())
43{}
44
45QGeoMercatorCoordinatePrivate::QGeoMercatorCoordinatePrivate(const QGeoMercatorCoordinatePrivate &other)
46 : QGeoCoordinatePrivate(other),
47 m_mercatorX(other.m_mercatorX),
48 m_mercatorY(other.m_mercatorY)
49{}
50
51QGeoMercatorCoordinatePrivate::~QGeoMercatorCoordinatePrivate()
52{}
53
54/*!
55 \class QGeoCoordinate
56 \inmodule QtPositioning
57 \ingroup QtPositioning-positioning
58 \since 5.2
59
60 \brief The QGeoCoordinate class defines a geographical position on the surface of the Earth.
61
62 A QGeoCoordinate is defined by latitude, longitude, and optionally, altitude.
63
64 Use type() to determine whether a coordinate is a 2D coordinate (has
65 latitude and longitude only) or 3D coordinate (has latitude, longitude
66 and altitude). Use distanceTo() and azimuthTo() to calculate the distance
67 and bearing between coordinates.
68
69 The coordinate values should be specified using the WGS84 datum. For more information
70 on geographical terms see this article on \l {http://en.wikipedia.org/wiki/Geographic_coordinate_system}{coordinates} and
71 another on \l {http://en.wikipedia.org/wiki/Geodetic_system}{geodetic systems}
72 including WGS84.
73
74 Azimuth in this context is equivalent to a compass bearing based on true north.
75
76 This class is a \l Q_GADGET since Qt 5.5. It can be
77 \l{Cpp_value_integration_positioning}{directly used from C++ and QML}.
78*/
79
80/*!
81 \enum QGeoCoordinate::CoordinateType
82 Defines the types of a coordinate.
83
84 \value InvalidCoordinate An invalid coordinate. A coordinate is invalid if its latitude or longitude values are invalid.
85 \value Coordinate2D A coordinate with valid latitude and longitude values.
86 \value Coordinate3D A coordinate with valid latitude and longitude values, and also an altitude value.
87*/
88
89/*!
90 \enum QGeoCoordinate::CoordinateFormat
91 Defines the possible formatting options for toString().
92
93 \value Degrees Returns a string representation of the coordinates in decimal degrees format.
94 \value DegreesWithHemisphere Returns a string representation of the coordinates in decimal degrees format, using 'N', 'S', 'E' or 'W' to indicate the hemispheres of the coordinates.
95 \value DegreesMinutes Returns a string representation of the coordinates in degrees-minutes format.
96 \value DegreesMinutesWithHemisphere Returns a string representation of the coordinates in degrees-minutes format, using 'N', 'S', 'E' or 'W' to indicate the hemispheres of the coordinates.
97 \value DegreesMinutesSeconds Returns a string representation of the coordinates in degrees-minutes-seconds format.
98 \value DegreesMinutesSecondsWithHemisphere Returns a string representation of the coordinates in degrees-minutes-seconds format, using 'N', 'S', 'E' or 'W' to indicate the hemispheres of the coordinates.
99
100 \sa toString()
101*/
102
103/*!
104 \property QGeoCoordinate::latitude
105 \brief This property holds the latitude in decimal degrees.
106
107 The property is undefined (\l {qQNaN()}) if the latitude has not been set.
108 A positive latitude indicates the Northern Hemisphere, and a negative
109 latitude indicates the Southern Hemisphere. When setting the latitude the
110 new value should be in the
111 \l {http://en.wikipedia.org/wiki/World_Geodetic_System}{WGS84} datum format.
112
113 To be valid, the latitude must be between -90 to 90 inclusive.
114
115 While this property is introduced in Qt 5.5, the related accessor functions
116 exist since the first version of this class.
117
118 \since 5.5
119*/
120
121/*!
122 \property QGeoCoordinate::longitude
123 \brief This property holds the longitude in decimal degrees.
124
125 The property is undefined (\l {qQNaN()}) if the longitude has not been set.
126 A positive longitude indicates the Eastern Hemisphere, and a negative
127 longitude indicates the Western Hemisphere. When setting the longitude the
128 new value should be in the
129 \l {http://en.wikipedia.org/wiki/World_Geodetic_System}{WGS84} datum format.
130
131 To be valid, the longitude must be between -180 to 180 inclusive.
132
133 While this property is introduced in Qt 5.5, the related accessor functions
134 exist since the first version of this class.
135
136 \since 5.5
137*/
138
139/*!
140 \property QGeoCoordinate::altitude
141 \brief This property holds the altitude in meters above sea level.
142
143 The property is undefined (\l {qQNaN()}) if the altitude has not been set.
144
145 While this property is introduced in Qt 5.5, the related accessor functions
146 exist since the first version of this class.
147
148 \since 5.5
149*/
150
151/*!
152 \property QGeoCoordinate::isValid
153 \brief This property holds the validity of this geo coordinate.
154
155 The geo coordinate is valid if the \l [CPP]{longitude} and \l [CPP]{latitude}
156 properties have been set to valid values.
157
158 While this property is introduced in Qt 5.5, the related accessor functions
159 exist since the first version of this class.
160
161 \since 5.5
162*/
163
164/*!
165 Constructs a coordinate. The coordinate will be invalid until
166 setLatitude() and setLongitude() have been called.
167*/
168QGeoCoordinate::QGeoCoordinate()
169 : d(new QGeoCoordinatePrivate)
170{
171}
172
173/*!
174 Constructs a coordinate with the given \a latitude and \a longitude.
175
176 If the latitude is not between -90 to 90 inclusive, or the longitude
177 is not between -180 to 180 inclusive, none of the values are set and
178 the type() will be QGeoCoordinate::InvalidCoordinate.
179
180 \sa isValid()
181*/
182QGeoCoordinate::QGeoCoordinate(double latitude, double longitude)
183 : d(new QGeoCoordinatePrivate)
184{
185 if (QLocationUtils::isValidLat(latitude) && QLocationUtils::isValidLong(longitude)) {
186 d->lat = latitude;
187 d->lng = longitude;
188 }
189}
190
191/*!
192 Constructs a coordinate with the given \a latitude, \a longitude
193 and \a altitude.
194
195 If the latitude is not between -90 to 90 inclusive, or the longitude
196 is not between -180 to 180 inclusive, none of the values are set and
197 the type() will be QGeoCoordinate::InvalidCoordinate.
198
199 Note that \a altitude specifies the meters above sea level.
200
201 \sa isValid()
202*/
203QGeoCoordinate::QGeoCoordinate(double latitude, double longitude, double altitude)
204 : d(new QGeoCoordinatePrivate)
205{
206 if (QLocationUtils::isValidLat(latitude) && QLocationUtils::isValidLong(longitude)) {
207 d->lat = latitude;
208 d->lng = longitude;
209 d->alt = altitude;
210 }
211}
212
213/*!
214 Constructs a coordinate from the contents of \a other.
215*/
216QGeoCoordinate::QGeoCoordinate(const QGeoCoordinate &other)
217 : d(other.d)
218{}
219
220/*!
221 \fn QGeoCoordinate::QGeoCoordinate(QGeoCoordinate &&other)
222 \since 6.2
223
224 Constructs a coordinate by moving from \a other.
225
226 \note The moved-from QGeoCoordinate object can only be destroyed or
227 assigned to. The effect of calling other functions than the destructor
228 or one of the assignment operators is undefined.
229*/
230
231/*!
232 Assigns \a other to this coordinate and returns a reference to this coordinate.
233*/
234QGeoCoordinate &QGeoCoordinate::operator=(const QGeoCoordinate &other)
235{
236 if (this == &other)
237 return *this;
238
239 d = other.d;
240 return (*this);
241}
242
243/*!
244 \fn QGeoCoordinate &QGeoCoordinate::operator=(QGeoCoordinate &&other)
245 \since 6.2
246
247 Move-assigns \a other to this coordinate and returns a reference to this
248 coordinate.
249
250 \note The moved-from QGeoCoordinate object can only be destroyed or
251 assigned to. The effect of calling other functions than the destructor
252 or one of the assignment operators is undefined.
253*/
254
255/*!
256 Destroys the coordinate object.
257*/
258QGeoCoordinate::~QGeoCoordinate()
259{
260}
261
262QT_DEFINE_QSDP_SPECIALIZATION_DTOR(QGeoCoordinatePrivate)
263
264/*!
265 \fn bool QGeoCoordinate::operator==(const QGeoCoordinate &lhs, const QGeoCoordinate &rhs)
266
267 Returns \c true if the latitude, longitude and altitude of the \a lhs
268 coordinate are the same as those of the \a rhs coordinate. Otherwise
269 returns \c false.
270
271 The longitude will be ignored if the latitude is +/- 90 degrees.
272*/
273
274/*!
275 \fn bool QGeoCoordinate::operator!=(const QGeoCoordinate &lhs, const QGeoCoordinate &rhs)
276
277 Returns \c true if latitude, longitude, or altitude of the \a lhs
278 coordinate are not identical to those of the \a rhs coordinate. Otherwise
279 returns \c false.
280*/
281
282/*!
283 \fn void QGeoCoordinate::swap(QGeoCoordinate &other)
284 \since 6.2
285 \memberswap{coordinate}
286*/
287
288/*!
289 Returns \c true if the \l longitude and \l latitude are valid.
290*/
291bool QGeoCoordinate::isValid() const
292{
293 CoordinateType t = type();
294 return t == Coordinate2D || t == Coordinate3D;
295}
296
297/*!
298 Returns the type of this coordinate.
299*/
300QGeoCoordinate::CoordinateType QGeoCoordinate::type() const
301{
302 if (QLocationUtils::isValidLat(d->lat)
303 && QLocationUtils::isValidLong(d->lng)) {
304 if (qIsNaN(d->alt))
305 return Coordinate2D;
306 return Coordinate3D;
307 }
308 return InvalidCoordinate;
309}
310
311
312/*!
313 Returns the latitude, in decimal degrees. The return value is undefined
314 if the latitude has not been set.
315
316 A positive latitude indicates the Northern Hemisphere, and a negative
317 latitude indicates the Southern Hemisphere.
318
319 \sa setLatitude(), type()
320*/
321double QGeoCoordinate::latitude() const
322{
323 return d->lat;
324}
325
326/*!
327 Sets the latitude (in decimal degrees) to \a latitude. The value should
328 be in the WGS84 datum.
329
330 To be valid, the latitude must be between -90 to 90 inclusive.
331
332 \sa latitude()
333*/
334void QGeoCoordinate::setLatitude(double latitude)
335{
336 d->lat = latitude;
337}
338
339/*!
340 Returns the longitude, in decimal degrees. The return value is undefined
341 if the longitude has not been set.
342
343 A positive longitude indicates the Eastern Hemisphere, and a negative
344 longitude indicates the Western Hemisphere.
345
346 \sa setLongitude(), type()
347*/
348double QGeoCoordinate::longitude() const
349{
350 return d->lng;
351}
352
353/*!
354 Sets the longitude (in decimal degrees) to \a longitude. The value should
355 be in the WGS84 datum.
356
357 To be valid, the longitude must be between -180 to 180 inclusive.
358
359 \sa longitude()
360*/
361void QGeoCoordinate::setLongitude(double longitude)
362{
363 d->lng = longitude;
364}
365
366/*!
367 Returns the altitude (meters above sea level).
368
369 The return value is undefined if the altitude has not been set.
370
371 \sa setAltitude(), type()
372*/
373double QGeoCoordinate::altitude() const
374{
375 return d->alt;
376}
377
378/*!
379 Sets the altitude (meters above sea level) to \a altitude.
380
381 \sa altitude()
382*/
383void QGeoCoordinate::setAltitude(double altitude)
384{
385 d->alt = altitude;
386}
387
388/*!
389 Returns the distance (in meters) from this coordinate to the coordinate
390 specified by \a other. Altitude is not used in the calculation.
391
392 This calculation returns the great-circle distance between the two
393 coordinates, with an assumption that the Earth is spherical for the
394 purpose of this calculation.
395
396 Returns 0 if the type of this coordinate or the type of \a other is
397 QGeoCoordinate::InvalidCoordinate.
398*/
399qreal QGeoCoordinate::distanceTo(const QGeoCoordinate &other) const
400{
401 if (type() == QGeoCoordinate::InvalidCoordinate
402 || other.type() == QGeoCoordinate::InvalidCoordinate) {
403 return 0;
404 }
405
406 // Haversine formula
407 double dlat = qDegreesToRadians(other.d->lat - d->lat);
408 double dlon = qDegreesToRadians(other.d->lng - d->lng);
409 double haversine_dlat = sin(dlat / 2.0);
410 haversine_dlat *= haversine_dlat;
411 double haversine_dlon = sin(dlon / 2.0);
412 haversine_dlon *= haversine_dlon;
413 double y = haversine_dlat
414 + cos(qDegreesToRadians(d->lat))
415 * cos(qDegreesToRadians(other.d->lat))
416 * haversine_dlon;
417 double x = 2 * asin(sqrt(y));
418 return qreal(x * qgeocoordinate_EARTH_MEAN_RADIUS * 1000);
419}
420
421/*!
422 Returns the azimuth (or bearing) in degrees from this coordinate to the
423 coordinate specified by \a other. Altitude is not used in the calculation.
424
425 The bearing returned is the bearing from the origin to \a other along the
426 great-circle between the two coordinates. There is an assumption that the
427 Earth is spherical for the purpose of this calculation.
428
429 Returns 0 if the type of this coordinate or the type of \a other is
430 QGeoCoordinate::InvalidCoordinate.
431*/
432qreal QGeoCoordinate::azimuthTo(const QGeoCoordinate &other) const
433{
434 if (type() == QGeoCoordinate::InvalidCoordinate
435 || other.type() == QGeoCoordinate::InvalidCoordinate) {
436 return 0;
437 }
438
439 double dlon = qDegreesToRadians(other.d->lng - d->lng);
440 double lat1Rad = qDegreesToRadians(d->lat);
441 double lat2Rad = qDegreesToRadians(other.d->lat);
442
443 double y = sin(dlon) * cos(lat2Rad);
444 double x = cos(lat1Rad) * sin(lat2Rad) - sin(lat1Rad) * cos(lat2Rad) * cos(dlon);
445
446 double azimuth = qRadiansToDegrees(atan2(y, x)) + 360.0;
447 double whole;
448 double fraction = modf(azimuth, &whole);
449 return qreal((int(whole + 360) % 360) + fraction);
450}
451
452void QGeoCoordinatePrivate::atDistanceAndAzimuth(const QGeoCoordinate &coord,
453 qreal distance, qreal azimuth,
454 double *lon, double *lat)
455{
456 double latRad = qDegreesToRadians(coord.d->lat);
457 double lonRad = qDegreesToRadians(coord.d->lng);
458 double cosLatRad = cos(latRad);
459 double sinLatRad = sin(latRad);
460
461 double azimuthRad = qDegreesToRadians(azimuth);
462
463 double ratio = (distance / (qgeocoordinate_EARTH_MEAN_RADIUS * 1000.0));
464 double cosRatio = cos(ratio);
465 double sinRatio = sin(ratio);
466
467 double resultLatRad = asin(sinLatRad * cosRatio
468 + cosLatRad * sinRatio * cos(azimuthRad));
469 double resultLonRad = lonRad + atan2(sin(azimuthRad) * sinRatio * cosLatRad,
470 cosRatio - sinLatRad * sin(resultLatRad));
471
472 *lat = qRadiansToDegrees(resultLatRad);
473 *lon = qRadiansToDegrees(resultLonRad);
474}
475
476/*!
477 Returns the coordinate that is reached by traveling \a distance meters
478 from the current coordinate at \a azimuth (or bearing) along a great-circle.
479 There is an assumption that the Earth is spherical for the purpose of this
480 calculation.
481
482 The altitude will have \a distanceUp added to it.
483
484 Returns an invalid coordinate if this coordinate is invalid.
485*/
486QGeoCoordinate QGeoCoordinate::atDistanceAndAzimuth(qreal distance, qreal azimuth, qreal distanceUp) const
487{
488 if (!isValid())
489 return QGeoCoordinate();
490
491 double resultLon, resultLat;
492 QGeoCoordinatePrivate::atDistanceAndAzimuth(*this, distance, azimuth,
493 &resultLon, &resultLat);
494 double resultAlt = d->alt + distanceUp;
495 return QGeoCoordinate(resultLat, QLocationUtils::wrapLong(resultLon), resultAlt);
496}
497
498/*!
499 Returns this coordinate as a string in the specified \a format.
500
501 For example, if this coordinate has a latitude of -27.46758, a longitude
502 of 153.027892 and an altitude of 28.1, these are the strings
503 returned depending on \a format:
504
505 \table
506 \header
507 \li \a format value
508 \li Returned string
509 \row
510 \li \l Degrees
511 \li -27.46758\unicode{0xB0}, 153.02789\unicode{0xB0}, 28.1m
512 \row
513 \li \l DegreesWithHemisphere
514 \li 27.46758\unicode{0xB0} S, 153.02789\unicode{0xB0} E, 28.1m
515 \row
516 \li \l DegreesMinutes
517 \li -27\unicode{0xB0} 28.054', 153\unicode{0xB0} 1.673', 28.1m
518 \row
519 \li \l DegreesMinutesWithHemisphere
520 \li 27\unicode{0xB0} 28.054 S', 153\unicode{0xB0} 1.673' E, 28.1m
521 \row
522 \li \l DegreesMinutesSeconds
523 \li -27\unicode{0xB0} 28' 3.2", 153\unicode{0xB0} 1' 40.4", 28.1m
524 \row
525 \li \l DegreesMinutesSecondsWithHemisphere
526 \li 27\unicode{0xB0} 28' 3.2" S, 153\unicode{0xB0} 1' 40.4" E, 28.1m
527 \endtable
528
529 The altitude field is omitted if no altitude is set.
530
531 If the coordinate is invalid, an empty string is returned.
532*/
533QString QGeoCoordinate::toString(CoordinateFormat format) const
534{
535 if (type() == QGeoCoordinate::InvalidCoordinate)
536 return QString();
537
538 QString latStr;
539 QString longStr;
540
541 double absLat = qAbs(d->lat);
542 double absLng = qAbs(d->lng);
543 QChar symbol(0x00B0); // degrees symbol
544
545 switch (format) {
546 case Degrees:
547 case DegreesWithHemisphere: {
548 latStr = QString::number(absLat, 'f', 5) + symbol;
549 longStr = QString::number(absLng, 'f', 5) + symbol;
550 break;
551 }
552 case DegreesMinutes:
553 case DegreesMinutesWithHemisphere: {
554 double latMin = (absLat - int(absLat)) * 60;
555 double lngMin = (absLng - int(absLng)) * 60;
556
557 // We use QString::number(val, 'f', 3) to represent minutes.
558 // It rounds up to the next integer in case the fraction > 0.9995.
559 // Such behavior should be handled specifically when the rounded
560 // value is 60, so that we overflow to degrees correctly.
561 // If we overflow, the minutes should unconditionally be 0.0.
562 if (latMin > 59.9995) {
563 absLat++;
564 latMin = 0.0f;
565 }
566 if (lngMin > 59.9995) {
567 absLng++;
568 lngMin = 0.0f;
569 }
570
571 latStr = QString::fromLatin1("%1%2 %3'")
572 .arg(QString::number(int(absLat)))
573 .arg(symbol)
574 .arg(QString::number(latMin, 'f', 3));
575 longStr = QString::fromLatin1("%1%2 %3'")
576 .arg(QString::number(int(absLng)))
577 .arg(symbol)
578 .arg(QString::number(lngMin, 'f', 3));
579 break;
580 }
581 case DegreesMinutesSeconds:
582 case DegreesMinutesSecondsWithHemisphere: {
583 double latMin = (absLat - int(absLat)) * 60;
584 double lngMin = (absLng - int(absLng)) * 60;
585 double latSec = (latMin - int(latMin)) * 60;
586 double lngSec = (lngMin - int(lngMin)) * 60;
587
588 // We use QString::number(val, 'f', 1) to represent seconds.
589 // It rounds up to the next integer in case the fraction >= 0.95.
590 // Such behavior should be handled specifically when the rounded
591 // value is 60, so that we overflow to minutes correctly.
592 // If we overflow, the seconds should unconditionally be 0.0.
593 if (latSec >= 59.95) {
594 latMin++;
595 latSec = 0.0f;
596 // We cast to int to represent minutes, so we can use qRound()
597 // to determine if we need to overflow to full degrees.
598 // If we overflow, the minutes will unconditionally be 0.0.
599 if (qRound(latMin) >= 60) {
600 absLat++;
601 latMin = 0.0f;
602 }
603 }
604 if (lngSec >= 59.95) {
605 lngMin++;
606 lngSec = 0.0f;
607 if (qRound(lngMin) >= 60) {
608 absLng++;
609 lngMin = 0.0f;
610 }
611 }
612
613 latStr = QString::fromLatin1("%1%2 %3' %4\"")
614 .arg(QString::number(int(absLat)))
615 .arg(symbol)
616 .arg(QString::number(int(latMin)))
617 .arg(QString::number(latSec, 'f', 1));
618 longStr = QString::fromLatin1("%1%2 %3' %4\"")
619 .arg(QString::number(int(absLng)))
620 .arg(symbol)
621 .arg(QString::number(int(lngMin)))
622 .arg(QString::number(lngSec, 'f', 1));
623 break;
624 }
625 }
626
627 // now add the "-" to the start, or append the hemisphere char
628 switch (format) {
629 case Degrees:
630 case DegreesMinutes:
631 case DegreesMinutesSeconds: {
632 if (d->lat < 0)
633 latStr.insert(0, QStringLiteral("-"));
634 if (d->lng < 0)
635 longStr.insert(0, QStringLiteral("-"));
636 break;
637 }
638 case DegreesWithHemisphere:
639 case DegreesMinutesWithHemisphere:
640 case DegreesMinutesSecondsWithHemisphere: {
641 if (d->lat < 0)
642 latStr.append(QString::fromLatin1(" S"));
643 else if (d->lat > 0)
644 latStr.append(QString::fromLatin1(" N"));
645 if (d->lng < 0)
646 longStr.append(QString::fromLatin1(" W"));
647 else if (d->lng > 0)
648 longStr.append(QString::fromLatin1(" E"));
649 break;
650 }
651 }
652
653 if (qIsNaN(d->alt))
654 return QString::fromLatin1("%1, %2").arg(latStr, longStr);
655 return QString::fromLatin1("%1, %2, %3m").arg(latStr, longStr, QString::number(d->alt));
656}
657
658bool QGeoCoordinate::equals(const QGeoCoordinate &lhs, const QGeoCoordinate &rhs)
659{
660 bool latEqual = (qIsNaN(lhs.d->lat) && qIsNaN(rhs.d->lat))
661 || qFuzzyCompare(lhs.d->lat, rhs.d->lat);
662 bool lngEqual = (qIsNaN(lhs.d->lng) && qIsNaN(rhs.d->lng))
663 || qFuzzyCompare(lhs.d->lng, rhs.d->lng);
664 bool altEqual = (qIsNaN(lhs.d->alt) && qIsNaN(rhs.d->alt))
665 || qFuzzyCompare(lhs.d->alt, rhs.d->alt);
666
667 if (!qIsNaN(lhs.d->lat) && ((lhs.d->lat == 90.0) || (lhs.d->lat == -90.0)))
668 lngEqual = true;
669
670 return (latEqual && lngEqual && altEqual);
671}
672
673QGeoCoordinate::QGeoCoordinate(QGeoCoordinatePrivate &dd):
674 d(&dd)
675{
676}
677
678#ifndef QT_NO_DEBUG_STREAM
679QDebug QGeoCoordinate::debugStreaming(QDebug dbg, const QGeoCoordinate &coord)
680{
681 QDebugStateSaver saver(dbg);
682 double lat = coord.latitude();
683 double lng = coord.longitude();
684
685 QTextStreamManipulator tsm = qSetRealNumberPrecision(11);
686 dbg << tsm;
687 dbg.nospace() << "QGeoCoordinate(";
688 if (qIsNaN(lat))
689 dbg << '?';
690 else
691 dbg << lat;
692 dbg << ", ";
693 if (qIsNaN(lng))
694 dbg << '?';
695 else
696 dbg << lng;
697 if (coord.type() == QGeoCoordinate::Coordinate3D) {
698 dbg << ", ";
699 dbg << coord.altitude();
700 }
701 dbg << ')';
702 return dbg;
703}
704#endif
705
706#ifndef QT_NO_DATASTREAM
707/*!
708 \fn QDataStream &QGeoCoordinate::operator<<(QDataStream &stream, const QGeoCoordinate &coordinate)
709
710 Writes the given \a coordinate to the specified \a stream.
711
712 \sa {Serializing Qt Data Types}
713*/
714
715QDataStream &QGeoCoordinate::dataStreamOut(QDataStream &stream, const QGeoCoordinate &coordinate)
716{
717 stream << coordinate.latitude();
718 stream << coordinate.longitude();
719 stream << coordinate.altitude();
720 return stream;
721}
722#endif
723
724#ifndef QT_NO_DATASTREAM
725/*!
726 \fn QDataStream &QGeoCoordinate::operator>>(QDataStream &stream, QGeoCoordinate &coordinate)
727
728 Reads a coordinate from the specified \a stream into the given
729 \a coordinate.
730
731 \sa {Serializing Qt Data Types}
732*/
733
734QDataStream &QGeoCoordinate::dataStreamIn(QDataStream &stream, QGeoCoordinate &coordinate)
735{
736 double value;
737 stream >> value;
738 coordinate.setLatitude(value);
739 stream >> value;
740 coordinate.setLongitude(value);
741 stream >> value;
742 coordinate.setAltitude(value);
743 return stream;
744}
745#endif
746
747/*! \fn size_t qHash(const QGeoCoordinate &coordinate, size_t seed = 0)
748 \relates QHash
749
750 Returns a hash value for \a coordinate, using \a seed to seed the calculation.
751*/
752size_t qHash(const QGeoCoordinate &coordinate, size_t seed)
753{
754 QtPrivate::QHashCombine hash;
755 // north and south pole are geographically equivalent (no matter the longitude)
756 if (coordinate.latitude() != 90.0 && coordinate.latitude() != -90.0)
757 seed = hash(seed, coordinate.longitude());
758 seed = hash(seed, coordinate.latitude());
759 seed = hash(seed, coordinate.altitude());
760 return seed;
761}
762
763QT_END_NAMESPACE
764
765#include "moc_qgeocoordinate.cpp"
Combined button and popup list for selecting options.
constexpr size_t qHash(const QSize &s, size_t seed=0) noexcept
Definition qsize.h:191