[英]Comparing distances between geopoints fast
我在地圖上顯示了一個(很長的)點列表。 我需要計算每個點到用戶輸入點的距離,並從最近到最遠對列表進行排序。
現在,我正在這樣做:
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計算前1/4個點的距離,使用線程2計算第二個1/4點的距離,等等。只需確保SparseArray#put
是線程安全的(我不知道您要為此使用哪個庫)-如果需要在put
方法周圍加一個鎖,那么如果您在多個線程之間拆分它,則該程序實際上可能運行得較慢。
使用單精度而不是雙精度浮點計算也可以加快速度。 如果只關心固定精度(例如,兩個小數點精度),則可以改用定點算術 ,該算術實際上使用整數算術。
根據程序的工作情況,您可能可以延遲計算到其他點的距離-例如,如果您一次向用戶顯示25個點,則可以確定最接近的100左右點,然后等待計算下一個100點左右,直到用戶滾動到75-100點為止; 無論如何,用戶可能只關心前25個點,在這種情況下,您不必計算其他點的距離。 為此,您需要使用范圍樹或kd樹為點建立索引,以便您可以快速確定最接近查詢點的點,而不必遍歷整個列表。 如果您的點在數據庫中,則可以執行范圍查詢。 請注意,無論哪種情況,樹/查詢都是根據其曼哈頓距離(delta-lat + delta-lon,而不是delta-lat ^ 2 + delta-lon * 2)來查找最接近的點,因此您仍然需要計算他們的笛卡爾距離。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.