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
3// Qt-Security score:significant reason:default
7
8#include <QDateTime>
9#include <QHash>
10#include <QDataStream>
11#include <QDebug>
12#include <QMetaType>
13#include <qnumeric.h>
14#include <qmath.h>
15
17
18QT_IMPL_METATYPE_EXTERN(QGeoCoordinate)
19
20static const double qgeocoordinate_EARTH_MEAN_RADIUS = 6371.0072;
21
22
23QGeoCoordinatePrivate::QGeoCoordinatePrivate():
24 lat(qQNaN()),
25 lng(qQNaN()),
26 alt(qQNaN())
27{}
28
29QGeoCoordinatePrivate::QGeoCoordinatePrivate(const QGeoCoordinatePrivate &other)
30 : QSharedData(other),
31 lat(other.lat),
32 lng(other.lng),
33 alt(other.alt)
34{}
35
36QGeoCoordinatePrivate::~QGeoCoordinatePrivate()
37{}
38
39
40QGeoMercatorCoordinatePrivate::QGeoMercatorCoordinatePrivate():
41 QGeoCoordinatePrivate(),
42 m_mercatorX(qQNaN()),
43 m_mercatorY(qQNaN())
44{}
45
46QGeoMercatorCoordinatePrivate::QGeoMercatorCoordinatePrivate(const QGeoMercatorCoordinatePrivate &other)
47 : QGeoCoordinatePrivate(other),
48 m_mercatorX(other.m_mercatorX),
49 m_mercatorY(other.m_mercatorY)
50{}
51
52QGeoMercatorCoordinatePrivate::~QGeoMercatorCoordinatePrivate()
53{}
54
55/*!
56 \class QGeoCoordinate
57 \inmodule QtPositioning
58 \ingroup QtPositioning-positioning
59 \since 5.2
60
61 \brief The QGeoCoordinate class defines a geographical position on the surface of the Earth.
62
63 A QGeoCoordinate is defined by latitude, longitude, and optionally, altitude.
64
65 Use type() to determine whether a coordinate is a 2D coordinate (has
66 latitude and longitude only) or 3D coordinate (has latitude, longitude
67 and altitude). Use distanceTo() and azimuthTo() to calculate the distance
68 and bearing between coordinates.
69
70 The coordinate values should be specified using the WGS84 datum. For more information
71 on geographical terms see this article on \l {http://en.wikipedia.org/wiki/Geographic_coordinate_system}{coordinates} and
72 another on \l {http://en.wikipedia.org/wiki/Geodetic_system}{geodetic systems}
73 including WGS84.
74
75 Azimuth in this context is equivalent to a compass bearing based on true north.
76
77 This class is also accessible in QML as \l[QML]{geoCoordinate}.
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
544 switch (format) {
545 case Degrees:
546 case DegreesWithHemisphere: {
547 latStr = QString::asprintf("%.5f°", absLat);
548 longStr = QString::asprintf("%.5f°", absLng);
549 break;
550 }
551 case DegreesMinutes:
552 case DegreesMinutesWithHemisphere: {
553 double latMin = (absLat - int(absLat)) * 60;
554 double lngMin = (absLng - int(absLng)) * 60;
555
556 // We use QString::number(val, 'f', 3) to represent minutes.
557 // It rounds up to the next integer in case the fraction > 0.9995.
558 // Such behavior should be handled specifically when the rounded
559 // value is 60, so that we overflow to degrees correctly.
560 // If we overflow, the minutes should unconditionally be 0.0.
561 if (latMin > 59.9995) {
562 absLat++;
563 latMin = 0.0f;
564 }
565 if (lngMin > 59.9995) {
566 absLng++;
567 lngMin = 0.0f;
568 }
569
570 latStr = QString::asprintf("%d° %.3f'", int(absLat), latMin);
571 longStr = QString::asprintf("%d° %.3f'", int(absLng), lngMin);
572 break;
573 }
574 case DegreesMinutesSeconds:
575 case DegreesMinutesSecondsWithHemisphere: {
576 double latMin = (absLat - int(absLat)) * 60;
577 double lngMin = (absLng - int(absLng)) * 60;
578 double latSec = (latMin - int(latMin)) * 60;
579 double lngSec = (lngMin - int(lngMin)) * 60;
580
581 // We use QString::number(val, 'f', 1) to represent seconds.
582 // It rounds up to the next integer in case the fraction >= 0.95.
583 // Such behavior should be handled specifically when the rounded
584 // value is 60, so that we overflow to minutes correctly.
585 // If we overflow, the seconds should unconditionally be 0.0.
586 if (latSec >= 59.95) {
587 latMin++;
588 latSec = 0.0f;
589 // We cast to int to represent minutes, so we can use qRound()
590 // to determine if we need to overflow to full degrees.
591 // If we overflow, the minutes will unconditionally be 0.0.
592 if (qRound(latMin) >= 60) {
593 absLat++;
594 latMin = 0.0f;
595 }
596 }
597 if (lngSec >= 59.95) {
598 lngMin++;
599 lngSec = 0.0f;
600 if (qRound(lngMin) >= 60) {
601 absLng++;
602 lngMin = 0.0f;
603 }
604 }
605
606 latStr = QString::asprintf("%d° %d' %.1f\"", int(absLat), int(latMin), latSec);
607 longStr = QString::asprintf("%d° %d' %.1f\"", int(absLng), int(lngMin), lngSec);
608 break;
609 }
610 }
611
612 // now add the "-" to the start, or append the hemisphere char
613 switch (format) {
614 case Degrees:
615 case DegreesMinutes:
616 case DegreesMinutesSeconds: {
617 if (d->lat < 0)
618 latStr.insert(0, QStringLiteral("-"));
619 if (d->lng < 0)
620 longStr.insert(0, QStringLiteral("-"));
621 break;
622 }
623 case DegreesWithHemisphere:
624 case DegreesMinutesWithHemisphere:
625 case DegreesMinutesSecondsWithHemisphere: {
626 if (d->lat < 0)
627 latStr.append(QString::fromLatin1(" S"));
628 else if (d->lat > 0)
629 latStr.append(QString::fromLatin1(" N"));
630 if (d->lng < 0)
631 longStr.append(QString::fromLatin1(" W"));
632 else if (d->lng > 0)
633 longStr.append(QString::fromLatin1(" E"));
634 break;
635 }
636 }
637
638 if (qIsNaN(d->alt))
639 return QString::fromLatin1("%1, %2").arg(latStr, longStr);
640 return QString::fromLatin1("%1, %2, %3m").arg(latStr, longStr, QString::number(d->alt));
641}
642
643bool QGeoCoordinate::equals(const QGeoCoordinate &lhs, const QGeoCoordinate &rhs)
644{
645 bool latEqual = (qIsNaN(lhs.d->lat) && qIsNaN(rhs.d->lat))
646 || QtPrivate::fuzzyCompare(lhs.d->lat, rhs.d->lat);
647 bool lngEqual = (qIsNaN(lhs.d->lng) && qIsNaN(rhs.d->lng))
648 || QtPrivate::fuzzyCompare(lhs.d->lng, rhs.d->lng);
649 bool altEqual = (qIsNaN(lhs.d->alt) && qIsNaN(rhs.d->alt))
650 || QtPrivate::fuzzyCompare(lhs.d->alt, rhs.d->alt);
651
652 if (!qIsNaN(lhs.d->lat) && ((lhs.d->lat == 90.0) || (lhs.d->lat == -90.0)))
653 lngEqual = true;
654
655 return (latEqual && lngEqual && altEqual);
656}
657
658QGeoCoordinate::QGeoCoordinate(QGeoCoordinatePrivate &dd):
659 d(&dd)
660{
661}
662
663#ifndef QT_NO_DEBUG_STREAM
664QDebug QGeoCoordinate::debugStreaming(QDebug dbg, const QGeoCoordinate &coord)
665{
666 QDebugStateSaver saver(dbg);
667 double lat = coord.latitude();
668 double lng = coord.longitude();
669
670 QTextStreamManipulator tsm = qSetRealNumberPrecision(11);
671 dbg << tsm;
672 dbg.nospace() << "QGeoCoordinate(";
673 if (qIsNaN(lat))
674 dbg << '?';
675 else
676 dbg << lat;
677 dbg << ", ";
678 if (qIsNaN(lng))
679 dbg << '?';
680 else
681 dbg << lng;
682 if (coord.type() == QGeoCoordinate::Coordinate3D) {
683 dbg << ", ";
684 dbg << coord.altitude();
685 }
686 dbg << ')';
687 return dbg;
688}
689#endif
690
691#ifndef QT_NO_DATASTREAM
692/*!
693 \fn QDataStream &QGeoCoordinate::operator<<(QDataStream &stream, const QGeoCoordinate &coordinate)
694
695 Writes the given \a coordinate to the specified \a stream.
696
697 \sa {Serializing Qt Data Types}
698*/
699
700QDataStream &QGeoCoordinate::dataStreamOut(QDataStream &stream, const QGeoCoordinate &coordinate)
701{
702 stream << coordinate.latitude();
703 stream << coordinate.longitude();
704 stream << coordinate.altitude();
705 return stream;
706}
707#endif
708
709#ifndef QT_NO_DATASTREAM
710/*!
711 \fn QDataStream &QGeoCoordinate::operator>>(QDataStream &stream, QGeoCoordinate &coordinate)
712
713 Reads a coordinate from the specified \a stream into the given
714 \a coordinate.
715
716 \sa {Serializing Qt Data Types}
717*/
718
719QDataStream &QGeoCoordinate::dataStreamIn(QDataStream &stream, QGeoCoordinate &coordinate)
720{
721 double value;
722 stream >> value;
723 coordinate.setLatitude(value);
724 stream >> value;
725 coordinate.setLongitude(value);
726 stream >> value;
727 coordinate.setAltitude(value);
728 return stream;
729}
730#endif
731
732/*! \fn size_t qHash(const QGeoCoordinate &coordinate, size_t seed = 0)
733 \relates QHash
734
735 Returns a hash value for \a coordinate, using \a seed to seed the calculation.
736*/
737size_t qHash(const QGeoCoordinate &coordinate, size_t seed)
738{
739 QtPrivate::QHashCombine hash(seed);
740 // north and south pole are geographically equivalent (no matter the longitude)
741 if (coordinate.latitude() != 90.0 && coordinate.latitude() != -90.0)
742 seed = hash(seed, coordinate.longitude());
743 seed = hash(seed, coordinate.latitude());
744 seed = hash(seed, coordinate.altitude());
745 return seed;
746}
747
748QT_END_NAMESPACE
749
750#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:192