C# 当数据太多时,计算距离的最佳和最快方法是什么?

C# 当数据太多时,计算距离的最佳和最快方法是什么?,c#,wcf,C#,Wcf,我正在用C编写一个WCF服务。我需要计算用户相对于当前用户登录的距离。例如,我需要当前距离当前用户10公里以内的所有用户 数据看起来是这样的 User Longitude Latitude 1 71.23232 31.23232 2 69.23232 30.23232 3 68.23232 28.23232 4 67.23232 27.23232 . . 1000 23.22332 45.22323 我用下面的方法来计算距离 pub

我正在用C编写一个WCF服务。我需要计算用户相对于当前用户登录的距离。例如,我需要当前距离当前用户10公里以内的所有用户

数据看起来是这样的

User    Longitude   Latitude
1   71.23232    31.23232
2   69.23232    30.23232
3   68.23232    28.23232
4   67.23232    27.23232
.
.
1000    23.22332    45.22323
我用下面的方法来计算距离

public static double Distance(double sLatitude, double sLongitude, double dLatitude, double dLongitude, char unit='m')
{
    var sCoord = new GeoCoordinate(sLatitude, sLongitude);
    var dCoord = new GeoCoordinate(dLatitude, dLongitude);

    if(unit == 'm')
        return sCoord.GetDistanceTo(dCoord);
    else if(unit == 'k')
        return (sCoord.GetDistanceTo(dCoord))/1000;
} 

用户1已登录,我需要获取用户1 10公里或20公里范围内的所有用户。有没有一种最致命的方法来获得这样的用户?我在后端使用SQL server。请告知。

此任务称为“空间索引构建”。您可以使用R-tree完成此任务。它的唯一目的是索引这些数据以供进一步搜索。更多


带有实现的框架可以在相当流行的项目中找到。

如果可能的话,一个很酷的想法是将用户的最新预计算距离信息保持在某个固定点。这可能是一个简单的字典,以公里为单位的四舍五入距离作为键。每次注册新用户时,只需更新预计算的距离缓存即可

为什么呢?好的,当您需要评估范围R内的用户时,用户X只需评估X到引用的距离,我们称之为D,然后丢弃所有预计算到引用的距离大于D+R或小于D-R的用户。当用户数量较多时,这可能会对性能产生很大影响

public static bool IsWithinRadius(double radius,double sLatitude, double sLongitude, 
                                  double dLatitude, double dLongitude, char unit='m')
{ // [sLatitude,sLongitude] defines the "center", i.e. the location of the current user.
    if(unit == 'm') radius=radius/1000 ; 
    double deltalat = (sLatitude -dLatitude )*40000f/360f ;
    double deltalon = (sLongitude-dLongitude)*40000f/360f ;
    if (deltalon>20000f) deltalon=40000f-deltalon ; // Points on both sides of meridian 0
    double loncorrection = Math.Cos(sLatitude*Math.PI/180);
    deltalon = deltalon*loncorrection ; 
    return Math.Sqrt(deltalat*deltalat+deltalon*deltalon)<radius ;   
} 

如果用户位置非常动态,这是不可能的;如果您必须频繁地更新预计算的距离,那么解决方案就是弄巧成拙。但是,由于没有上下文可供参考,为了防止它有任何用途,这里给出了一个想法。

在SQL Server中,您可以使用地理空间类型。这将允许您查询数据库并按距离排序

看看这个:


在100NM以下的范围内,以下代码将指示您是否有其他用户位于指定距离以下,并且具有良好的精度和优异的性能

public static bool IsWithinRadius(double radius,double sLatitude, double sLongitude, 
                                  double dLatitude, double dLongitude, char unit='m')
{ // [sLatitude,sLongitude] defines the "center", i.e. the location of the current user.
    if(unit == 'm') radius=radius/1000 ; 
    double deltalat = (sLatitude -dLatitude )*40000f/360f ;
    double deltalon = (sLongitude-dLongitude)*40000f/360f ;
    if (deltalon>20000f) deltalon=40000f-deltalon ; // Points on both sides of meridian 0
    double loncorrection = Math.Cos(sLatitude*Math.PI/180);
    deltalon = deltalon*loncorrection ; 
    return Math.Sqrt(deltalat*deltalat+deltalon*deltalon)<radius ;   
} 

比较距离时的一个简便技巧是通过比较平方距离来消除计算上昂贵的平方根。因此,要找到当前用户10公里范围内的所有用户,请计算x1-x0^2+y1-y0^2距离的平方,并将其与100公里^2进行比较。请注意,这些计算不会对lat/lon值起作用;你需要在一个投影中工作。@VMAtm这根本不是这个问题的重复。@eocron你需要更多的解释而不是重复来说服人们它不是,因为在两个纵横坐标之间求距离看起来非常相似。在计算几何f.e中,找到相关对象簇的方法之一是使用。但不确定SQL Server中的数据是否可以以这种方式存储,或者加载所有数据并在内存中构建该树是否有意义。无论如何,值得一看。@eocron您可以在链接的问题中找到解决方案,因为SQL中有地理距离计算。可能有一些参数,对吗?