Calculate endpoint given distance, bearing, starting point

本小妞迷上赌 提交于 2019-11-28 00:59:48

Here's some code that achieves what you want to do.

public static GeoLocation FindPointAtDistanceFrom(GeoLocation startPoint, double initialBearingRadians, double distanceKilometres)
{
    const double radiusEarthKilometres = 6371.01;
    var distRatio = distanceKilometres / radiusEarthKilometres;
    var distRatioSine = Math.Sin(distRatio);
    var distRatioCosine = Math.Cos(distRatio);

    var startLatRad = DegreesToRadians(startPoint.Latitude);
    var startLonRad = DegreesToRadians(startPoint.Longitude);

    var startLatCos = Math.Cos(startLatRad);
    var startLatSin = Math.Sin(startLatRad);

    var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(initialBearingRadians)));

    var endLonRads = startLonRad
        + Math.Atan2(
            Math.Sin(initialBearingRadians) * distRatioSine * startLatCos,
            distRatioCosine - startLatSin * Math.Sin(endLatRads));

    return new GeoLocation
    {
        Latitude = RadiansToDegrees(endLatRads),
        Longitude = RadiansToDegrees(endLonRads)
    };
}

public struct GeoLocation
{
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}

public static double DegreesToRadians(double degrees)
{
    const double degToRadFactor = Math.PI / 180;
    return degrees * degToRadFactor;
}

public static double RadiansToDegrees(double radians)
{
    const double radToDegFactor = 180 / Math.PI;
    return radians * radToDegFactor;
}

Here is my code that I converted to C# from http://www.movable-type.co.uk/scripts/latlong.html. It should be pretty simple to use.

public static (double Lat, double Lon) Destination((double Lat, double Lon) startPoint, double distance, double bearing)
    {
        double lat1 = startPoint.Lat * (Math.PI / 180);
        double lon1 = startPoint.Lon * (Math.PI / 180);
        double brng = bearing * (Math.PI / 180);
        double lat2 = Math.Asin(Math.Sin(lat1) * Math.Cos(distance / radius) + Math.Cos(lat1) * Math.Sin(distance / radius) * Math.Cos(brng));
        double lon2 = lon1 + Math.Atan2(Math.Sin(brng) * Math.Sin(distance / radius) * Math.Cos(lat1), Math.Cos(distance / radius) - Math.Sin(lat1) * Math.Sin(lat2));
        return (lat2 * (180 / Math.PI), lon2 * (180 / Math.PI));
    }

radius is a constant for the Earth's radius in meters.

It uses tuples so you can access the latitude or longitude individually with .Lat or .Lon.

very simple solution in geometry library (V3), if you do not have a problema with using the google maps api V3 (depending on the application - realtime asset tracking, for example - the free license is not applicable OR you might not want to refactor from V2 to V3).

1st: declare an extra library ALONG with your current declaration:

<script type="text/javascript" src="http://maps.google.com/maps/api/js?libraries=geometry&sensor=false"></script>

2nd: establish starting point, heading and distance

var nyc = new google.maps.LatLng(40.715, -74.002);
var distance = 5576673;
var heading = 51.2145;

3rd: go there

var endPoint = google.maps.geometry.spherical.computeOffset(nyc, distance, heading);
var london = new google.maps.Marker({
  position: endPoint,
  map: map
});

done, you are now in London town. for more info regarding computeDistance, computeHeading and computeArea:

http://www.svennerberg.com/2011/04/calculating-distances-and-areas-in-google-maps-api-3/

http://code.google.com/intl/en/apis/maps/documentation/javascript/geometry.html

Below is the implementation of the JavaScript code at http://www.movable-type.co.uk/scripts/latlong.html which I wrote for myself and use in my own projects. You can implement it to your project if you will.

Note: Coordinate is a class with X (longitude), Y (latitude), Z (altitude) properties. ToDegree() and ToRadian() are extensions for Double type. Finally, GetTarget() is an extension for a Coordinate instance.

/// <summary>Calculates the destination coordinate by given angle and distance.</summary>
/// <param name="origin">Origin.</param>
/// <param name="bearing">Azimuth.</param>
/// <param name="distance">Distance (km).</param>
/// <returns>Coordinate.</returns>
public static Coordinate GetTarget(
this Coordinate origin, double bearing, double distance, double altitude = 0)
{
    var d = distance / 6371;
    var rlat = origin.Y.ToRadian();
    var rlon = origin.X.ToRadian();
    var rbearing = bearing.ToRadian();
    var lat2 = rlat + (d * Math.Cos(rbearing));
    var dlat = lat2 - rlat;
    var dphi = Math.Log((Math.Tan((lat2 / 2) + (Math.PI / 4))) / (Math.Tan((rlat / 2) + (Math.PI / 4))));
    var q =
        Math.Abs(dlat) > 0.0000000001
        ? dlat / dphi
        : Math.Cos(rlat);
    var dlon = (d * Math.Sin(rbearing)) / q;

    if (Math.Abs(lat2) > Math.PI / 2)
    {
        lat2 = lat2 > 0 ? Math.PI : Math.PI - lat2;
    }

    var lon2 = (rlon + dlon + Math.PI) % (2 * Math.PI) - Math.PI;

    return new Coordinate
    {
        X = lon2.ToDegree(),
        Y = lat2.ToDegree(),
        Z = origin.Z
    };
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!