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