我有一些生成谷歌地图的C#代码.这些代码查看我需要在地图上绘制的所有点,然后计算出矩形的边界以包含这些点.然后,它会将此边界传递给Google Maps API,以适当地设置缩放级别,以显示地图上的所有点.
这段代码工作正常,但我有一个新的要求.
其中一个点可能具有与之相关的精度.如果是这种情况,那么我在半径设置为精度值的点周围绘制一个圆.再次,这工作正常,但我的边界检查现在没有做我想要它做的事情.我希望边界框包含完整的圆圈.
这需要算法采用点x并计算将在x以北z米以及x以南z米的点y.
有没有人有这个算法,最好是在C#中.我确实在这里找到了一个通用算法,但我似乎没有正确实现这个,因为我得到的答案是千米的漂移.
这是通用示例
Lat/lon given radial and distance
A point {lat,lon} is a distance d out on the tc radial from point 1 if:
lat=asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
IF (cos(lat)=0)
lon=lon1 // endpoint a pole
ELSE
lon=mod(lon1-asin(sin(tc)*sin(d)/cos(lat))+pi,2*pi)-pi
ENDIF
Run Code Online (Sandbox Code Playgroud)
这是我的C#翻译.
// Extend a Point North/South by the specified distance
public static Point ExtendPoint(Point _pt, int _distance, int _bearing )
{
Decimal lat = 0.0;
Decimal lng = 0.0;
lat = Math.Asin(Math.Sin(_pt.Lat) * Math.Cos(_distance) + Math.Cos(_pt.Lat) *
Math.Sin(_distance) * Math.Cos(_bearing));
if (Math.Cos(lat) == 0)
{
lng = _pt.Lng; // endpoint a pole
}
else
{
lng = (
(_pt.Lng - Math.Asin(Math.Sin(_bearing) * Math.Sin(_distance) / Math.Cos(lat))
+ Math.PI) % (2 * Math.PI)) - Math.PI;
}
ret = new Point(lat,lng);
return ret;
}
Run Code Online (Sandbox Code Playgroud)
我调用此函数的轴承为0来计算新的北偏位置,并将值180设置为计算新的南风位置.
任何人都可以看到我做错了或者可能提供一个已知的工作算法吗?
Eri*_*bal 23
我有一段非常相似的代码.与其他实现相比,它让我得到了非常接近的结果.
我认为与你的问题在于你使用"距离"作为以米为单位的线性距离而不是以弧度表示的角距离.
/// <summary>
/// Calculates the end-point from a given source at a given range (meters) and bearing (degrees).
/// This methods uses simple geometry equations to calculate the end-point.
/// </summary>
/// <param name="source">Point of origin</param>
/// <param name="range">Range in meters</param>
/// <param name="bearing">Bearing in degrees</param>
/// <returns>End-point from the source given the desired range and bearing.</returns>
public static LatLonAlt CalculateDerivedPosition(LatLonAlt source, double range, double bearing)
{
double latA = source.Latitude * UnitConstants.DegreesToRadians;
double lonA = source.Longitude * UnitConstants.DegreesToRadians;
double angularDistance = range / GeospatialConstants.EarthRadius;
double trueCourse = bearing * UnitConstants.DegreesToRadians;
double lat = Math.Asin(
Math.Sin(latA) * Math.Cos(angularDistance) +
Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));
double dlon = Math.Atan2(
Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));
double lon = ((lonA + dlon + Math.PI) % UnitConstants.TwoPi) - Math.PI;
return new LatLonAlt(
lat * UnitConstants.RadiansToDegrees,
lon * UnitConstants.RadiansToDegrees,
source.Altitude);
}
Run Code Online (Sandbox Code Playgroud)
哪里
public const double EarthRadius = 6378137.0; // WGS-84 ellipsoid parameters
Run Code Online (Sandbox Code Playgroud)
和LatLonAlt以度/米为单位(转换在内部进行).根据需要调整.
我假设你可以弄清楚它的价值UnitConstants.DegreesToRadians
是什么:)
Zar*_*dan 11
对于懒惰的人(像我一样))复制粘贴解决方案,Erich Mirabal的版本有很小的变化:
using System.Device.Location; // add reference to System.Device.dll
public static class GeoUtils
{
/// <summary>
/// Calculates the end-point from a given source at a given range (meters) and bearing (degrees).
/// This methods uses simple geometry equations to calculate the end-point.
/// </summary>
/// <param name="source">Point of origin</param>
/// <param name="range">Range in meters</param>
/// <param name="bearing">Bearing in degrees</param>
/// <returns>End-point from the source given the desired range and bearing.</returns>
public static GeoCoordinate CalculateDerivedPosition(this GeoCoordinate source, double range, double bearing)
{
var latA = source.Latitude * DegreesToRadians;
var lonA = source.Longitude * DegreesToRadians;
var angularDistance = range / EarthRadius;
var trueCourse = bearing * DegreesToRadians;
var lat = Math.Asin(
Math.Sin(latA) * Math.Cos(angularDistance) +
Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));
var dlon = Math.Atan2(
Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));
var lon = ((lonA + dlon + Math.PI) % (Math.PI*2)) - Math.PI;
return new GeoCoordinate(
lat * RadiansToDegrees,
lon * RadiansToDegrees,
source.Altitude);
}
private const double DegreesToRadians = Math.PI/180.0;
private const double RadiansToDegrees = 180.0/ Math.PI;
private const double EarthRadius = 6378137.0;
}
Run Code Online (Sandbox Code Playgroud)
用法:
[TestClass]
public class CalculateDerivedPositionUnitTest
{
[TestMethod]
public void OneDegreeSquareAtEquator()
{
var center = new GeoCoordinate(0, 0);
var radius = 111320;
var southBound = center.CalculateDerivedPosition(radius, -180);
var westBound = center.CalculateDerivedPosition(radius, -90);
var eastBound = center.CalculateDerivedPosition(radius, 90);
var northBound = center.CalculateDerivedPosition(radius, 0);
Console.Write($"leftBottom: {southBound.Latitude} , {westBound.Longitude} rightTop: {northBound.Latitude} , {eastBound.Longitude}");
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定我是否在这里遗漏了一些东西,但我认为这个问题可以改为:"我有一个纬度/经度点,而且我想找到该点以北x米和该点以南x米的点. "
如果这是问题,那么你不需要找到新的经度(这会使事情变得更简单),你只需要一个新的纬度.地球上任何地方的纬度大约为60海里,海里距离为1,852米.因此,对于新的纬度x南北:
north_lat = lat + x / (1852 * 60)
north_lat = min(north_lat, 90)
south_lat = lat - x / (1852 * 60)
south_lat = max(south_lat, -90)
Run Code Online (Sandbox Code Playgroud)
这并不完全准确,因为地球不是一个完美的球体,每个纬度之间恰好有60海里.然而,其他答案假设纬度线是等距的,所以我假设你不关心它.如果您对可能引入的错误感兴趣,维基百科上有一个很好的表格,显示了此链接中不同纬度的"纬度每1°变化的表面距离":
http://en.wikipedia.org/wiki/Latitude#Degree_length
如果您有一个给定的纬度和经度,您可以计算纬度x-km变化的正确纬度和经度,如下所示:
new-lat = ((old-km-north + x-km-change)/40,075) * 360)
^ is the ratio of the ^ times the ratio of the circle
of the earth the change by 360 to get the total ratio
covers. covered in degrees.
Run Code Online (Sandbox Code Playgroud)
这同样适用于经度.如果您有总距离加上更改,您可以以类似的方式计算总度数.
new-long = ((old-km-east + x-km-change)/40,075) * 360)
^ is the ratio of the ^ times the ratio of the circle
of the earth the change by 360 to get the total ratio
covers. covered in degrees.
Run Code Online (Sandbox Code Playgroud)
同样,这些计算应该有效,但我在这里运行纯粹的直觉,但逻辑似乎确实如此.
编辑:正如Skizz 40,075指出的那样,需要使用2.pi.r.cos(lat)或40074.cos(lat)在任意给定的纬度调整到地球的周长.
归档时间: |
|
查看次数: |
35873 次 |
最近记录: |