快速比较地理点之间的距离

时间:2013-05-30 08:20:14

标签: java distance geopoints

我有一个(非常长的)点列表,我在地图中显示。我需要计算从每一个到用户输入点的距离,并从最近到最远的列表进行排序。

现在我这样做:

private List<Point> sortedPointList(LatLng ll, List<Point> pointList)
    SparseArray<Double> distances = new SparseArray<Double>();
    for (Point ll : pointList){
        double distance = calcDistance(ll.getLatLng(), point);
        distances.put(ll.getId(), distance);
    }
    Collections.sort(pointList, new Comparator<Point>(){

        @Override
        public int compare(final Tramo lhs, final Tramo rhs) {
            return distances.get(lhs.getId()).compareTo(distances.get(rhs.getId()));
        }
    });
    return pointList
}


private double calcDistance(LatLng ll1, LatLng ll2){
    final double lat1 = ll1.latitude;
    final double lon1 = ll1.longitude;
    final double lat2 = ll2.latitude;
    final double lon2 = ll2.longitude;
    final double lat = lat2-lat1;
    final double lon = lon2-lon1;
    final double squareLat = lat*lat;
    final double squareLon = lon*lon;
    final double squareDistance = squareLat+squareLon;
    return squareDistance;
}

calcDistance实际上返回两点之间实际距离的平方,因为我认为比较该平方将得到与比较实际值相同的结果,并且它因为我不需要而快得多制作那个平方根。

然而,它仍然很慢(这是一个很长的列表),我真的很感激加速这个过程的一些想法。我在排序之前预先计算了距离,所以我不会多次计算每个距离,但我想不出任何其他改进。有什么我想念的吗?

1 个答案:

答案 0 :(得分:1)

你可以在多个踏板之间划分,例如使用四个线程并使用thread1计算前1/4点的距离,使用thread2等计算第二个1/4点的距离。确保SparseArray#put是线程安全的(我不是'我知道你正在使用什么库) - 如果你需要锁定put方法,那么如果你在多个线程中分割它,程序实际上可能会运行得更慢。

使用单精度而不是双精度浮点计算也会加快速度。如果您只关心固定精度(例如两个小数点的精度),那么您可以使用fixed point arithmetic代替,它基本上使用整数运算。

根据您的程序正在执行的操作,您可以延迟计算到更远点的距离 - 例如,如果您一次向用户显示25个点,那么您可以确定最接近的100-左右点,然后等待计算下一个100点左右,直到用户滚动到75-100点为止;用户可能只关心前25个点,在这种情况下,您永远不必计算其他点的距离。要执行此操作,您需要使用range treek-d tree对点进行索引,以便您可以快速确定最接近查询点的点,而无需遍历整个列表;如果您的积分位于数据库中,则可以执行范围查询。请注意,在任何一种情况下,树/查询都会根据其曼哈顿距离(delta-lat + delta-lon,而不是delta-lat ^ 2 + delta-lon * 2)找到最近的点,因此您仍需要计算他们的笛卡尔距离。