2010-07-12 2 views
9

Я пытаюсь найти пункт назначения, учитывая начальную точку lat/long, подшипник & расстояние. Калькулятор с этого сайта ниже дает мне желаемые результаты.Рассчитать конечную точку, заданную дистанцию, подшипник, начальную точку

http://www.movable-type.co.uk/scripts/latlong.html

Когда я пытаюсь реализовать то же самое через код, я не получить правильные результаты.

Ниже мой код -

private GLatLng pointRadialDistance(double lat1, double lon1, 
       double radianBearing, double radialDistance) 
    { 
     double rEarth = 6371.01; 
     lat1 = DegreeToRadian(lat1); 
     lon1 = DegreeToRadian(lon1); 
     radianBearing = DegreeToRadian(radianBearing); 
     radialDistance = radialDistance/rEarth; 
     double lat = Math.Asin(Math.Sin(lat1) * Math.Cos(radialDistance) + Math.Cos(lat1) 
         * Math.Sin(radialDistance) * Math.Cos(radianBearing)); 
     double lon; 
     if (Math.Cos(lat) == 0) 
     { // Endpoint a pole 
      lon = lon1; 
     } 
     else 
     { 
      lon = ((lon1 - Math.Asin(Math.Sin(radianBearing) * Math.Sin(radialDistance)/Math.Cos(lat)) 
          + Math.PI) % (2 * Math.PI)) - Math.PI; 
     } 
     lat = RadianToDegree(lat); 
     lon = RadianToDegree(lon); 
     GLatLng newLatLng = new GLatLng(lat, lon); 
     return newLatLng; 
    } 

    public double Bearing(double lat1, double long1, double lat2, double long2) 
    { 
     //Convert input values to radians 
     lat1 = DegreeToRadian(lat1); 
     long1 = DegreeToRadian(long1); 
     lat2 = DegreeToRadian(lat2); 
     long2 = DegreeToRadian(long2); 

     double deltaLong = long2 - long1; 

     double y = Math.Sin(deltaLong) * Math.Cos(lat2); 
     double x = Math.Cos(lat1) * Math.Sin(lat2) - 
       Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(deltaLong); 
     double bearing = Math.Atan2(y, x); 
     return bearing; 
    } 

    public double DegreeToRadian(double angle) 
    { 
    return Math.PI * angle/180.0; 
    } 

    public double RadianToDegree(double angle) 
    { 
     return 180.0 * angle/Math.PI; 
    } 

Из основной программы, я называю процедуры суб следующим образом -

double bearing = Bearing(-41.294444, 174.814444, -40.90521, 175.6604); 
GLatLng endLatLng = pointRadialDistance(-41.294444, 174.814444, bearing, 80); 

Я получаю ниже результатов -

Bearing=1.02749621782165 
endLatLng=-40.5751022737927,174.797458881699 

Ответ Я ожидаю, что это -40.939722,175.646389 (ссылка на сайте выше).

Может кто-нибудь предположить, какую ошибку я делаю в коде здесь?

+0

Во-первых, результат, возвращаемый Bearing, должен быть преобразован в степень. – 2011-06-02 04:03:32

ответ

18

Вот код, который позволяет выполнить то, что вы хотите.

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; 
} 
0

очень простое решение в геометрии библиотеки (V3), если вы не имеете проблема- с помощью API V3 Google Maps (в зависимости от приложения - отслеживание активов в режиме реального времени, например - свободная лицензия не применяется Или вы не захотите реорганизовать с V2 на V3).

первый: объявить дополнительную библиотеку вместе с вашей текущей декларации:

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

второй: установить начальную точку, курс и расстояние

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

третий: туда

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

сделанный, вы сейчас в городе Лондон. Для получения дополнительной информации о computeDistance, computeHeading и 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

0

Ниже приводится реализация кода JavaScript в http://www.movable-type.co.uk/scripts/latlong.html, который я написал для себя и использовать в своих проектах. Вы можете реализовать его в своем проекте, если хотите.

Примечание: Координата - это класс с свойствами X (долгота), Y (широта), Z (высота). ToDegree() и ToRadian() - это расширения для типа Double. Наконец, GetTarget() является расширением для экземпляра Coordinate.

/// <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 
    }; 
} 
Смежные вопросы