Esempio n. 1
0
void QDeclarativePosition::setCoordinate(const QGeoCoordinate &coordinate)
{
    if (m_coordinate == coordinate)
        return;

    m_coordinate = coordinate;

    if (coordinate.type() == QGeoCoordinate::Coordinate3D && !m_altitudeValid) {
        m_altitudeValid = true;
        emit altitudeValidChanged();
    } else if (m_altitudeValid) {
        m_altitudeValid = false;
        emit altitudeValidChanged();
    }
    if (coordinate.isValid()) {
        if (!m_longitudeValid) {
            m_longitudeValid = true;
            emit longitudeValidChanged();
        }
        if (!m_latitudeValid) {
            m_latitudeValid = true;
            emit latitudeValidChanged();
        }
    } else {
        if (m_longitudeValid) {
            m_longitudeValid = false;
            emit longitudeValidChanged();
        }
        if (m_latitudeValid) {
            m_latitudeValid = false;
            emit latitudeValidChanged();
        }
    }
    emit coordinateChanged();
}
/*!
    Returns the distance (in meters) from this coordinate to the coordinate
    specified by \a other. Altitude is not used in the calculation.

    This calculation returns the great-circle distance between the two
    coordinates, with an assumption that the Earth is spherical for the
    purpose of this calculation.

    Returns 0 if the type of this coordinate or the type of \a other is
    QGeoCoordinate::InvalidCoordinate.
*/
qreal QGeoCoordinate::distanceTo(const QGeoCoordinate &other) const
{
    if (type() == QGeoCoordinate::InvalidCoordinate
            || other.type() == QGeoCoordinate::InvalidCoordinate) {
        return 0;
    }

    // Haversine formula
    double dlat = qgeocoordinate_degToRad(other.d->lat - d->lat);
    double dlon = qgeocoordinate_degToRad(other.d->lng - d->lng);
    double y = sin(dlat / 2.0) * sin(dlat / 2.0)
               + cos(qgeocoordinate_degToRad(d->lat))
               * cos(qgeocoordinate_degToRad(other.d->lat))
               * sin(dlon / 2.0) * sin(dlon / 2.0);
    double x = 2 * atan2(sqrt(y), sqrt(1 - y));
    return qreal(x * qgeocoordinate_EARTH_MEAN_RADIUS * 1000);
}
/*!
    Returns the azimuth (or bearing) in degrees from this coordinate to the
    coordinate specified by \a other. Altitude is not used in the calculation.

    There is an assumption that the Earth is spherical for the purpose of
    this calculation.

    Returns 0 if the type of this coordinate or the type of \a other is
    QGeoCoordinate::InvalidCoordinate.
*/
qreal QGeoCoordinate::azimuthTo(const QGeoCoordinate &other) const
{
    if (type() == QGeoCoordinate::InvalidCoordinate
            || other.type() == QGeoCoordinate::InvalidCoordinate) {
        return 0;
    }

    double dlon = qgeocoordinate_degToRad(other.d->lng - d->lng);
    double lat1Rad = qgeocoordinate_degToRad(d->lat);
    double lat2Rad = qgeocoordinate_degToRad(other.d->lat);

    double y = sin(dlon) * cos(lat2Rad);
    double x = cos(lat1Rad) * sin(lat2Rad) - sin(lat1Rad) * cos(lat2Rad) * cos(dlon);

    double whole;
    double fraction = modf(qgeocoordinate_radToDeg(atan2(y, x)), &whole);
    return qreal((int(whole + 360) % 360) + fraction);
}
QDebug operator<<(QDebug dbg, const QGeoCoordinate &coord)
{
    double lat = coord.latitude();
    double lng = coord.longitude();

    dbg.nospace() << "QGeoCoordinate(";
    if (qIsNaN(lat))
        dbg.nospace() << '?';
    else
        dbg.nospace() << lat;
    dbg.nospace() << ", ";
    if (qIsNaN(lng))
        dbg.nospace() << '?';
    else
        dbg.nospace() << lng;
    if (coord.type() == QGeoCoordinate::Coordinate3D) {
        dbg.nospace() << ", ";
        dbg.nospace() << coord.altitude();
    }
    dbg.nospace() << ')';
    return dbg;
}