我试图找到目的地点,给定一个起点lat / long,bearing&距离。下面这个网站的计算器给了我想要的结果。
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 :(得分:20)
这是一些可以实现您想要的目标的代码。
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;
}
答案 1 :(得分:2)
这是我从http://www.movable-type.co.uk/scripts/latlong.html转换为C#的代码。使用起来应该非常简单。
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
是地球半径的常数,以米为单位。
它使用元组,因此您可以使用.Lat
或.Lon
分别访问纬度或经度。
答案 2 :(得分:0)
几何库(V3)中非常简单的解决方案,如果你没有使用google maps api V3的问题(例如,取决于应用程序 - 实时资产跟踪 - 免费许可证不适用或者你可能不会想要从V2重构为V3。
1st:使用您当前的声明声明一个额外的库ALONG:
<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;
第3名:去那里
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
答案 3 :(得分:0)
以下是我在http://www.movable-type.co.uk/scripts/latlong.html编写的JavaScript代码的实现,我自己编写并在我自己的项目中使用。如果愿意,您可以将它实现到您的项目中。
注意:坐标是一个具有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
};
}