static void calculatePeripheralPoints(QList<QGeoCoordinate> &path, const QGeoCoordinate &center, qreal distance, int steps)
{
    // Calculate points based on great-circle distance
    // Calculation is the same as GeoCoordinate's atDistanceAndAzimuth function
    // but tweaked here for computing multiple points

    // pre-calculate
    qreal latRad = qgeocoordinate_degToRad(center.latitude());
    qreal lonRad = qgeocoordinate_degToRad(center.longitude());
    qreal cosLatRad = std::cos(latRad);
    qreal sinLatRad = std::sin(latRad);
    qreal ratio = (distance / (qgeocoordinate_EARTH_MEAN_RADIUS * 1000.0));
    qreal cosRatio = std::cos(ratio);
    qreal sinRatio = std::sin(ratio);
    qreal sinLatRad_x_cosRatio = sinLatRad * cosRatio;
    qreal cosLatRad_x_sinRatio = cosLatRad * sinRatio;

    for (int i = 0; i < steps; ++i) {
        qreal azimuthRad = 2 * M_PI * i / steps;
        qreal resultLatRad = std::asin(sinLatRad_x_cosRatio
                                   + cosLatRad_x_sinRatio * std::cos(azimuthRad));
        qreal resultLonRad = lonRad + std::atan2(std::sin(azimuthRad) * cosLatRad_x_sinRatio,
                                       cosRatio - sinLatRad * std::sin(resultLatRad));
        qreal lat2 = qgeocoordinate_radToDeg(resultLatRad);
        qreal lon2 = qgeocoordinate_radToDeg(resultLonRad);
        if (lon2 < -180.0) {
            lon2 += 360.0;
        } else if (lon2 > 180.0) {
            lon2 -= 360.0;
        }
        path << QGeoCoordinate(lat2, lon2, center.altitude());
    }
}
Exemplo n.º 2
0
/*!
    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);
}
Exemplo n.º 3
0
/*!
    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);
}
void QGeoCoordinatePrivate::atDistanceAndAzimuth(const QGeoCoordinate &coord,
                                                 qreal distance, qreal azimuth,
                                                 double *lon, double *lat)
{
    double latRad = qgeocoordinate_degToRad(coord.d->lat);
    double lonRad = qgeocoordinate_degToRad(coord.d->lng);
    double cosLatRad = cos(latRad);
    double sinLatRad = sin(latRad);

    double azimuthRad = qgeocoordinate_degToRad(azimuth);

    double ratio = (distance / (qgeocoordinate_EARTH_MEAN_RADIUS * 1000.0));
    double cosRatio = cos(ratio);
    double sinRatio = sin(ratio);

    double resultLatRad = asin(sinLatRad * cosRatio
                               + cosLatRad * sinRatio * cos(azimuthRad));
    double resultLonRad  = lonRad
                           + atan2(sin(azimuthRad) * sinRatio * cosLatRad,
                                   cosRatio - sinLatRad * sin(resultLatRad));

    *lat = qgeocoordinate_radToDeg(resultLatRad);
    *lon = qgeocoordinate_radToDeg(resultLonRad);
}