解决方案 »

  1.   

    这个方法 用于计算两个点之间的距离
    private static double distance(double lon1, double lat1, double lon2, double lat2) {
    double pi = 0.0174532925199432944; // PI / 180;
    double t5 = Math.sin(lat1 * pi) * Math.sin(lat2 * pi) + Math.cos(lat1 * pi) * Math.cos(lat2 * pi)
    * Math.cos((lon1 - lon2) * pi);
    return (Math.atan(-t5 / Math.sqrt(-t5 * t5 + 1)) + 2 * Math.atan(1)) * 3437.74677 * 1.1508 * 1.6093470878864446
    * 1000;
    }
      

  2.   

    知道两个点的距离怎么计算了,做一次对所有好友的迭代,一一计算距离不就出来了?或者说,你是考虑性能问题,好友太多,距离计算量太大? 比如R-tree?
      

  3.   

    是的,好友太多,其实不是好友也得列出来,就是不可能把所有的人的距离都算出来再处理,因为速度确实慢。俺不是给你提示了么? R-Tree
    或者gg一下 高维检索 空间划分 虾米的 这方面的paper是很多的
      

  4.   

    我算的不是两个点,我是5公里以内的所有点可以先对数据进行一些简单的处理,比如 先根据已知的经纬度和 5公里这个距离,得出一个经度和纬度的边界值,也就是地图上的一个矩形范围,用这个边界值先过滤一遍好友列表,然后再计算距离进行过滤,这是简单的两步处理。其实即使是第二步,也不是所有的点都要计算的,比如 假设已知点A经纬度分别为a1,a2你已经计算出一个点B(b1,b2)在这个范围内,如果有个点C(c1,c2),满足 a1< c1 <b1 且 a2 < c2< b2 的话 肯定也在这个范围内的(当然如果a1 > b1的话 前边的式子就得用 > 了,a2 b2亦然)
      

  5.   

    我算的不是两个点,我是5公里以内的所有点可以先对数据进行一些简单的处理,比如 先根据已知的经纬度和 5公里这个距离,得出一个经度和纬度的边界值,也就是地图上的一个矩形范围,用这个边界值先过滤一遍好友列表,然后再计算距离进行过滤,这是简单的两步处理。其实即使是第二步,也不是所有的点都要计算的,比如 假设已知点A经纬度分别为a1,a2你已经计算出一个点B(b1,b2)在这个范围内,如果有个点C(c1,c2),满足 a1< c1 <b1 且 a2 < c2< b2 的话 肯定也在这个范围内的(当然如果a1 > b1的话 前边的式子就得用 > 了,a2 b2亦然)
    或者你也可以这样优化。如上图 你已经计算出B点在5公里范围内了,可以根据B点和A点的经纬度差值,再构建一个矩形区域,那么 在这个区域中的点都无需再计算了 肯定都在这个范围内了。 (当然 你也可以直接计算5公里这个圆的内接正方形进行过滤,那么 就只有少量的位于内接正方形以外的点需要计算距离了)
      

  6.   

    我算的不是两个点,我是5公里以内的所有点可以先对数据进行一些简单的处理,比如 先根据已知的经纬度和 5公里这个距离,得出一个经度和纬度的边界值,也就是地图上的一个矩形范围,用这个边界值先过滤一遍好友列表,然后再计算距离进行过滤,这是简单的两步处理。其实即使是第二步,也不是所有的点都要计算的,比如 假设已知点A经纬度分别为a1,a2你已经计算出一个点B(b1,b2)在这个范围内,如果有个点C(c1,c2),满足 a1< c1 <b1 且 a2 < c2< b2 的话 肯定也在这个范围内的(当然如果a1 > b1的话 前边的式子就得用 > 了,a2 b2亦然)
    或者你也可以这样优化。如上图 你已经计算出B点在5公里范围内了,可以根据B点和A点的经纬度差值,再构建一个矩形区域,那么 在这个区域中的点都无需再计算了 肯定都在这个范围内了。 (当然 你也可以直接计算5公里这个圆的内接正方形进行过滤,那么 就只有少量的位于内接正方形以外的点需要计算距离了)
    嗯,非常不错的建议,还有没有其它的办法
      

  7.   

    利用GeoHash值做索引来实现快速查找和粗排序,在利用计算两点间距离实现精确距离计算和精确排序。
    实际上这里的问题主要是解决计算量大的问题,我们的解决方案是为了快速定位和减少计算,否则用户想查出5公里范围的好友如果需要很长时间,我想他早也没有心气看了。
    方案:使用redis做缓存,使用你的经纬度计算出来的的GeoHash的code值得前8、7、6、5位建立四个桶,你的好友或是其他用户如果登录系统也会用他们的经纬度计算出一个GeoHash的code,这些人都会按照8、7、6、5的顺序放入桶内,这样这些桶里就有你想要的人了,取桶的顺序是8、7、6、5依次来,当然一般用户在手机上能翻几页也就够了,所以一般8、7里面的数据就已经满足用户的翻页需求了,剩下的估计就是搜索了,那其实同样的逻辑。
    注意:8桶的人一定会在7桶里,一次类推,但是反过来就不成立,所以你要记得去重。
    希望这样简单的介绍对你有所帮助!