[英]Producing Points in a Circle with Specific Radius from Central Lat/Long
我需要能够获取一组纬度/经度坐标并在 map 上围绕这些坐标绘制一个圆形“围栏”,其中圆形中的点数和圆的半径都是可配置的。 我的目标是能够输入点、形状的半径和我希望它具有的点数,并接收一个 output 包含一个纬度/经度坐标列表,如果它可以在中心点周围完成一个形状连接的。
我已经能够提出一个可行的解决方案来完成我需要的大部分工作,但是有一些事情并没有按照我的预期工作,而且我对基础数学的理解很弱,以至于我不确定如何解决它们。
我引用了 CSharpHelper 的这篇文章,以在我的起点周围生成一个圆圈中的点,并从这个 StackOverflow 答案中进行数学运算,以尝试将我的英里半径转换为纬度和经度。 这是我到目前为止的代码:
public readonly struct LocationPoint
{
public LocationPoint(double lat, double lon)
{
Lat = lat;
Lon = lon;
}
public double Lat { get; }
public double Lon { get; }
}
private static List<LocationPoint> GetZoneCoordinates(LocationPoint center,
double radiusInMiles,
int numberOfPoints)
{
// Convert input miles to degrees latitude and longitude.
var radiusKm = radiusInMiles * 0.621371;
var radiusLon = 1 / (111.319 * Math.Cos(center.Lat)) * radiusKm;
var radiusLat = 1 / 110.574 * radiusKm;
// Calculate amount to increment angle for number of points.
var dTheta = 2 * Math.PI / numberOfPoints;
double theta = 0;
// Produce points.
var points = new List<LocationPoint>();
for (var i = 0; i < numberOfPoints; i++)
{
points.Add(new LocationPoint
(
center.Lat + radiusLat * Math.Sin(theta),
center.Lon + radiusLon * Math.Cos(theta)
));
theta += dTheta;
}
return points;
}
上面的代码可以很好地使用我给它的点数创建一个圆形。 我将以肯尼迪国际机场的中心点为例。 如果我以 5 英里和 8 个点的半径运行上述内容,我会得到一组坐标 map 到以下点:
这个形状有两个问题:
我在这里做错了什么?
您转换为公里是错误的。 var radiusKm = radiusInMiles * 0.621371;
应该是var radiusKm = radiusInMiles / 0.621371;
.
一种检测此类错误的直观方法:一公里比一英里短,因此对于任意数量的英里,您应该有比英里多的公里。 但是您的公式显然将原始数字减少到较小的数字,因此这是不对的。
如果您的原始转换因子带有单位(应该如此),那么检测这种错误的另一种方法是确保在数学中包含单位。 即0.621371
实际上是0.621371 mile/kilometer
。 当您在原始公式中包含单位时,您会得到mile * mile/kilometer
的单位,而您真正想要的只是kilometer
。
至于边界不是一个完美的圆,我会说是的,这可能至少部分是因为在那个纬度使用了映射投影。 请注意,map 中包含的网格线也不会形成完美的正方形,但会以与您的边界相同的方式延伸。 但请记住,您使用的公式假设地球是一个完美的球体,而且绝对不是。 与从两极到另一极的直径相比,它在赤道处凸出,因此将其视为完美球体将导致您在此处看到的扭曲。
如果这对其他人有帮助,我可以使用上面代码中的一些数学运算以及@PeterDuniho 的指导,得到一个真正的“大圆”距离计算的非常接近的近似值,现在方法输出创建更均匀圆形的坐标:
private static List<LocationPoint> GetZoneCoordinates(LocationPoint center,
double radiusInMiles,
int numberOfPoints)
{
// Convert input miles to degrees latitude and longitude.
var radiusKm = radiusInMiles / 0.621371;
var radiusLon = 1 / (111.319 * Math.Cos(center.Lat * (Math.PI / 180))) * radiusKm;
var radiusLat = 1 / 110.574 * radiusKm;
// Calculate amount to increment angle for number of points.
var dTheta = 2 * Math.PI / numberOfPoints;
double theta = 0;
// Produce points.
var points = new List<LocationPoint>();
for (var i = 0; i < numberOfPoints; i++)
{
points.Add(new LocationPoint
(
center.Lat + radiusLat * Math.Sin(theta),
center.Lon + radiusLon * Math.Cos(theta)
));
theta += dTheta;
}
return points;
}
不同之处在于计算radiusLon
的行 - 使用中心点纬度的转换弧度的余弦而不是原始度数。 我希望我可以说我理解为什么这会有所作为,但它在我迄今为止尝试过的所有纬度上都运作良好。
考虑到他在我的原始代码中发现了最严重的错误,我会将 Peter 的回复保留为已接受的答案。 再次感谢您的帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.