[英]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.