Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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#include "qgeocoordinate.h"
4#include "qgeocoordinate_p.h"
5#include "qlocationutils_p.h"
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
18
19static const double qgeocoordinate_EARTH_MEAN_RADIUS = 6371.0072;
20
21
23 lat(qQNaN()),
24 lng(qQNaN()),
25 alt(qQNaN())
26{}
27
34
37
38
44
50
53
172
182QGeoCoordinate::QGeoCoordinate(double latitude, double longitude)
184{
186 d->lat = latitude;
187 d->lng = longitude;
188 }
189}
190
203QGeoCoordinate::QGeoCoordinate(double latitude, double longitude, double altitude)
205{
207 d->lat = latitude;
208 d->lng = longitude;
209 d->alt = altitude;
210 }
211}
212
219
235{
236 if (this == &other)
237 return *this;
238
239 d = other.d;
240 return (*this);
241}
242
261
263
264
285bool QGeoCoordinate::isValid() const
286{
288 return t == Coordinate2D || t == Coordinate3D;
289}
290
295{
298 if (qIsNaN(d->alt))
299 return Coordinate2D;
300 return Coordinate3D;
301 }
302 return InvalidCoordinate;
303}
304
305
316{
317 return d->lat;
318}
319
328void QGeoCoordinate::setLatitude(double latitude)
329{
330 d->lat = latitude;
331}
332
343{
344 return d->lng;
345}
346
355void QGeoCoordinate::setLongitude(double longitude)
356{
357 d->lng = longitude;
358}
359
368{
369 return d->alt;
370}
371
377void QGeoCoordinate::setAltitude(double altitude)
378{
379 d->alt = altitude;
380}
381
394{
397 return 0;
398 }
399
400 // Haversine formula
401 double dlat = qDegreesToRadians(other.d->lat - d->lat);
402 double dlon = qDegreesToRadians(other.d->lng - d->lng);
403 double haversine_dlat = sin(dlat / 2.0);
404 haversine_dlat *= haversine_dlat;
405 double haversine_dlon = sin(dlon / 2.0);
406 haversine_dlon *= haversine_dlon;
407 double y = haversine_dlat
408 + cos(qDegreesToRadians(d->lat))
409 * cos(qDegreesToRadians(other.d->lat))
410 * haversine_dlon;
411 double x = 2 * asin(sqrt(y));
413}
414
427{
430 return 0;
431 }
432
433 double dlon = qDegreesToRadians(other.d->lng - d->lng);
434 double lat1Rad = qDegreesToRadians(d->lat);
435 double lat2Rad = qDegreesToRadians(other.d->lat);
436
437 double y = sin(dlon) * cos(lat2Rad);
438 double x = cos(lat1Rad) * sin(lat2Rad) - sin(lat1Rad) * cos(lat2Rad) * cos(dlon);
439
440 double azimuth = qRadiansToDegrees(atan2(y, x)) + 360.0;
441 double whole;
442 double fraction = modf(azimuth, &whole);
443 return qreal((int(whole + 360) % 360) + fraction);
444}
445
447 qreal distance, qreal azimuth,
448 double *lon, double *lat)
449{
450 double latRad = qDegreesToRadians(coord.d->lat);
451 double lonRad = qDegreesToRadians(coord.d->lng);
452 double cosLatRad = cos(latRad);
453 double sinLatRad = sin(latRad);
454
455 double azimuthRad = qDegreesToRadians(azimuth);
456
457 double ratio = (distance / (qgeocoordinate_EARTH_MEAN_RADIUS * 1000.0));
458 double cosRatio = cos(ratio);
459 double sinRatio = sin(ratio);
460
461 double resultLatRad = asin(sinLatRad * cosRatio
462 + cosLatRad * sinRatio * cos(azimuthRad));
463 double resultLonRad = lonRad + atan2(sin(azimuthRad) * sinRatio * cosLatRad,
464 cosRatio - sinLatRad * sin(resultLatRad));
465
466 *lat = qRadiansToDegrees(resultLatRad);
467 *lon = qRadiansToDegrees(resultLonRad);
468}
469
481{
482 if (!isValid())
483 return QGeoCoordinate();
484
485 double resultLon, resultLat;
487 &resultLon, &resultLat);
488 double resultAlt = d->alt + distanceUp;
489 return QGeoCoordinate(resultLat, QLocationUtils::wrapLong(resultLon), resultAlt);
490}
491
528{
530 return QString();
531
532 QString latStr;
533 QString longStr;
534
535 double absLat = qAbs(d->lat);
536 double absLng = qAbs(d->lng);
537 QChar symbol(0x00B0); // degrees symbol
538
539 switch (format) {
540 case Degrees:
542 latStr = QString::number(absLat, 'f', 5) + symbol;
543 longStr = QString::number(absLng, 'f', 5) + symbol;
544 break;
545 }
546 case DegreesMinutes:
548 double latMin = (absLat - int(absLat)) * 60;
549 double lngMin = (absLng - int(absLng)) * 60;
550
551 // We use QString::number(val, 'f', 3) to represent minutes.
552 // It rounds up to the next integer in case the fraction > 0.9995.
553 // Such behavior should be handled specifically when the rounded
554 // value is 60, so that we overflow to degrees correctly.
555 // If we overflow, the minutes should unconditionally be 0.0.
556 if (latMin > 59.9995) {
557 absLat++;
558 latMin = 0.0f;
559 }
560 if (lngMin > 59.9995) {
561 absLng++;
562 lngMin = 0.0f;
563 }
564
565 latStr = QString::fromLatin1("%1%2 %3'")
566 .arg(QString::number(int(absLat)))
567 .arg(symbol)
568 .arg(QString::number(latMin, 'f', 3));
569 longStr = QString::fromLatin1("%1%2 %3'")
570 .arg(QString::number(int(absLng)))
571 .arg(symbol)
572 .arg(QString::number(lngMin, 'f', 3));
573 break;
574 }
577 double latMin = (absLat - int(absLat)) * 60;
578 double lngMin = (absLng - int(absLng)) * 60;
579 double latSec = (latMin - int(latMin)) * 60;
580 double lngSec = (lngMin - int(lngMin)) * 60;
581
582 // We use QString::number(val, 'f', 1) to represent seconds.
583 // It rounds up to the next integer in case the fraction >= 0.95.
584 // Such behavior should be handled specifically when the rounded
585 // value is 60, so that we overflow to minutes correctly.
586 // If we overflow, the seconds should unconditionally be 0.0.
587 if (latSec >= 59.95) {
588 latMin++;
589 latSec = 0.0f;
590 // We cast to int to represent minutes, so we can use qRound()
591 // to determine if we need to overflow to full degrees.
592 // If we overflow, the minutes will unconditionally be 0.0.
593 if (qRound(latMin) >= 60) {
594 absLat++;
595 latMin = 0.0f;
596 }
597 }
598 if (lngSec >= 59.95) {
599 lngMin++;
600 lngSec = 0.0f;
601 if (qRound(lngMin) >= 60) {
602 absLng++;
603 lngMin = 0.0f;
604 }
605 }
606
607 latStr = QString::fromLatin1("%1%2 %3' %4\"")
608 .arg(QString::number(int(absLat)))
609 .arg(symbol)
610 .arg(QString::number(int(latMin)))
611 .arg(QString::number(latSec, 'f', 1));
612 longStr = QString::fromLatin1("%1%2 %3' %4\"")
613 .arg(QString::number(int(absLng)))
614 .arg(symbol)
615 .arg(QString::number(int(lngMin)))
616 .arg(QString::number(lngSec, 'f', 1));
617 break;
618 }
619 }
620
621 // now add the "-" to the start, or append the hemisphere char
622 switch (format) {
623 case Degrees:
624 case DegreesMinutes:
626 if (d->lat < 0)
627 latStr.insert(0, QStringLiteral("-"));
628 if (d->lng < 0)
629 longStr.insert(0, QStringLiteral("-"));
630 break;
631 }
635 if (d->lat < 0)
636 latStr.append(QString::fromLatin1(" S"));
637 else if (d->lat > 0)
638 latStr.append(QString::fromLatin1(" N"));
639 if (d->lng < 0)
640 longStr.append(QString::fromLatin1(" W"));
641 else if (d->lng > 0)
642 longStr.append(QString::fromLatin1(" E"));
643 break;
644 }
645 }
646
647 if (qIsNaN(d->alt))
648 return QString::fromLatin1("%1, %2").arg(latStr, longStr);
649 return QString::fromLatin1("%1, %2, %3m").arg(latStr, longStr, QString::number(d->alt));
650}
651
652bool QGeoCoordinate::equals(const QGeoCoordinate &lhs, const QGeoCoordinate &rhs)
653{
654 bool latEqual = (qIsNaN(lhs.d->lat) && qIsNaN(rhs.d->lat))
655 || qFuzzyCompare(lhs.d->lat, rhs.d->lat);
656 bool lngEqual = (qIsNaN(lhs.d->lng) && qIsNaN(rhs.d->lng))
657 || qFuzzyCompare(lhs.d->lng, rhs.d->lng);
658 bool altEqual = (qIsNaN(lhs.d->alt) && qIsNaN(rhs.d->alt))
659 || qFuzzyCompare(lhs.d->alt, rhs.d->alt);
660
661 if (!qIsNaN(lhs.d->lat) && ((lhs.d->lat == 90.0) || (lhs.d->lat == -90.0)))
662 lngEqual = true;
663
664 return (latEqual && lngEqual && altEqual);
665}
666
668 d(&dd)
669{
670}
671
672#ifndef QT_NO_DEBUG_STREAM
673QDebug QGeoCoordinate::debugStreaming(QDebug dbg, const QGeoCoordinate &coord)
674{
675 QDebugStateSaver saver(dbg);
676 double lat = coord.latitude();
677 double lng = coord.longitude();
678
680 dbg << tsm;
681 dbg.nospace() << "QGeoCoordinate(";
682 if (qIsNaN(lat))
683 dbg << '?';
684 else
685 dbg << lat;
686 dbg << ", ";
687 if (qIsNaN(lng))
688 dbg << '?';
689 else
690 dbg << lng;
691 if (coord.type() == QGeoCoordinate::Coordinate3D) {
692 dbg << ", ";
693 dbg << coord.altitude();
694 }
695 dbg << ')';
696 return dbg;
697}
698#endif
699
700#ifndef QT_NO_DATASTREAM
709QDataStream &QGeoCoordinate::dataStreamOut(QDataStream &stream, const QGeoCoordinate &coordinate)
710{
711 stream << coordinate.latitude();
712 stream << coordinate.longitude();
713 stream << coordinate.altitude();
714 return stream;
715}
716#endif
717
718#ifndef QT_NO_DATASTREAM
728QDataStream &QGeoCoordinate::dataStreamIn(QDataStream &stream, QGeoCoordinate &coordinate)
729{
730 double value;
731 stream >> value;
732 coordinate.setLatitude(value);
733 stream >> value;
734 coordinate.setLongitude(value);
735 stream >> value;
736 coordinate.setAltitude(value);
737 return stream;
738}
739#endif
740
746size_t qHash(const QGeoCoordinate &coordinate, size_t seed)
747{
749 // north and south pole are geographically equivalent (no matter the longitude)
750 if (coordinate.latitude() != 90.0 && coordinate.latitude() != -90.0)
751 seed = hash(seed, coordinate.longitude());
752 seed = hash(seed, coordinate.latitude());
753 seed = hash(seed, coordinate.altitude());
754 return seed;
755}
756
758
759#include "moc_qgeocoordinate.cpp"
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qdatastream.h:46
\inmodule QtCore
\inmodule QtCore
static void atDistanceAndAzimuth(const QGeoCoordinate &coord, qreal distance, qreal azimuth, double *lon, double *lat)
\inmodule QtPositioning
double longitude
This property holds the longitude in decimal degrees.
double latitude
This property holds the latitude in decimal degrees.
Q_INVOKABLE QGeoCoordinate atDistanceAndAzimuth(qreal distance, qreal azimuth, qreal distanceUp=0.0) const
Returns the coordinate that is reached by traveling distance meters from the current coordinate at az...
CoordinateFormat
Defines the possible formatting options for toString().
@ DegreesMinutesSecondsWithHemisphere
double altitude
This property holds the altitude in meters above sea level.
Q_INVOKABLE QString toString(CoordinateFormat format=DegreesMinutesSecondsWithHemisphere) const
Returns this coordinate as a string in the specified format.
QGeoCoordinate & operator=(const QGeoCoordinate &other)
Assigns other to this coordinate and returns a reference to this coordinate.
Q_INVOKABLE qreal azimuthTo(const QGeoCoordinate &other) const
Returns the azimuth (or bearing) in degrees from this coordinate to the coordinate specified by other...
void setLatitude(double latitude)
Sets the latitude (in decimal degrees) to latitude.
void setLongitude(double longitude)
Sets the longitude (in decimal degrees) to longitude.
Q_INVOKABLE qreal distanceTo(const QGeoCoordinate &other) const
Returns the distance (in meters) from this coordinate to the coordinate specified by other.
void setAltitude(double altitude)
Sets the altitude (meters above sea level) to altitude.
~QGeoCoordinate()
Destroys the coordinate object.
QGeoCoordinate()
Constructs a coordinate.
bool isValid
This property holds the validity of this geo coordinate.
CoordinateType
Defines the types of a coordinate.
CoordinateType type() const
Returns the type of this coordinate.
static bool isValidLong(double lng)
static bool isValidLat(double lat)
static double wrapLong(double lng)
\inmodule QtCore
Definition qshareddata.h:19
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
QHash< int, QWidget * > hash
[35multi]
Combined button and popup list for selecting options.
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
bool qIsNaN(qfloat16 f) noexcept
Definition qfloat16.h:284
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
static QT_BEGIN_NAMESPACE const double qgeocoordinate_EARTH_MEAN_RADIUS
size_t qHash(const QGeoCoordinate &coordinate, size_t seed)
constexpr float qRadiansToDegrees(float radians)
Definition qmath.h:281
constexpr float qDegreesToRadians(float degrees)
Definition qmath.h:260
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1390
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN()
GLint GLint GLint GLint GLint x
[0]
GLsizei GLsizei GLfloat distance
GLenum type
GLint GLsizei GLsizei GLenum format
GLint y
GLuint coord
GLdouble GLdouble t
Definition qopenglext.h:243
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define QT_DEFINE_QSDP_SPECIALIZATION_DTOR(Class)
#define QStringLiteral(str)
QTextStreamManipulator qSetRealNumberPrecision(int precision)
double qreal
Definition qtypes.h:187
QSharedPointer< T > other(t)
[5]