对于游戏,我需要计算地图上的项目是否在玩家的范围内。 地图是地球。 我使用Haversine公式来计算玩家和每个项目之间的距离。 然而,我做了一些分析,发现所有这些sin / cos计算都太慢,无法进行smoth游戏。
还有其他方法来检查地球上的两个点是否可能有x米的范围? 该方法不需要精确,但必须快速并且如果距离<= x则返回true。如果距离> 1,它也可以返回true。 x(但不应总是返回true)。
我的测试代码(LinqPad)
void Main()
{
var lat = 53.553072;
var lng = 9.993023;
var lat0 = 53.553073;
var lng0 = 9.993178;
"Google Maps: 10.02m".Dump(); // 10.02m
$"Euclid: {DistanceEuclid(lat, lng, lat0, lng0)}m".Dump(); // 10,2396639400397m
$"Haversine: {DistanceHaversine(lat, lng, lat0, lng0)}m".Dump(); // 10,2396637520237m
}
const int R = 6371000;
const double PiBy180 = Math.PI / 180;
const double deglen = 111194.93;
double DistanceEuclid(double lat, double lng, double lat0, double lng0)
{
var x = lat - lat0;
var y = (lng - lng0)*Math.Cos(ToRadians(lat0));
return deglen*Math.Sqrt(x*x + y*y);
}
public double DistanceHaversine(double lat, double lng, double lat0, double lng0)
{
var lat1 = ToRadians(lat);
var lat2 = ToRadians(lat0);
var dLat = ToRadians(lat0 - lat);
var dLng = ToRadians(lng0 - lng);
var h = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Sin(dLng / 2) * Math.Sin(dLng / 2);
var c = 2 * Math.Atan2(Math.Sqrt(h), Math.Sqrt(1 - h));
return R * c;
}
double ToRadians(double degrees) => degrees * PiBy180;
答案 0 :(得分:0)
对于曲率可以忽略不计的短距离情况,可以使用线性近似并获取点之间的欧几里德距离。
长距离测量的快速而肮脏的方法,其中曲率问题可能涉及预先计算球体(即地球)上的点之间的弧长,以提前确定不同的弧长。例如,您将创建一个数组/查找表,以查找关于纵向(垂直)轴的半球的φ0,φ1和Δλ(|λ0-λ1|)的量化值的近似值,因为距离是相同的对于相等和相反的纵向差异。您可以通过增加阵列的大小来提高准确性。如果您的内存预算不紧张,您可以尝试将其设置得非常大。
使用特定的数据结构或修正公式可能会提高逼近的准确性,但我不确定。
然后你可以比较物品和玩家之间的距离和距离。