我正在尝试编写一个以性能为导向的数组查找,它将返回相对于用户当前位置最近的经度和纬度。
一个问题是我的数组中有5000个位置,我需要尽可能快地循环返回最接近的所有结果,我也遇到了过滤器的问题,因为它目前正在返回错误的结果(我认为这是由于查找只查找最接近当前的负面因素)
这是我的代码:
if(has('geolocation')){
navigator.geolocation.getCurrentPosition((position) => {
// Example result from getCurrentPosition (this is my exact location)
//
// position.coords = {
// latitude: 51.4523,
// longitude: -0.9724
// }
// This is the nearest location
//
// location = {
// latitude: 51.457495699999996,
// longitude: -0.973083
// }
// This is the location my filter keeps returning
//
// location = {
// latitude: "50.6931",
// longitude: "-4.0094",
// name: "Yes Tor"
// }
let closest = this.locations.filter((location) => {
console.log(location, position.coords);
return location.latitude <= position.coords.latitude && location.longitude <= position.coords.longitude;
}).pop();
console.log(closest); //Is incorrect
});
}
我已经评论了我目前的结果,我的问题是,是否有更快的方法可以做到这一点,以及是否有办法从当前的方面得到最接近的负面和正面。
如果有人需要,这里是一个数组结构的例子(长度是5968)
let this.locations = [
{
elevation: "936.0",
id: "350001",
latitude: "56.8716",
longitude: "-4.1969",
name: "A' Bhuidheanach Bheag",
region: "ta",
unitaryAuthArea: "Perth and Kinross"
},
{
elevation: "999.0",
id: "350024",
latitude: "57.6926",
longitude: "-5.1328",
name: "A'Chailleach (Fannaich Region)",
region: "he",
unitaryAuthArea: "Highland"
}
]
答案 0 :(得分:5)
找到2点之间的距离(Haversine公式):
function distance(position1,position2){
var lat1=position1.latitude;
var lat2=position2.latitude;
var lon1=position1.longitude;
var lon2=position2.longitude;
var R = 6371000; // metres
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2-lat1).toRadians();
var Δλ = (lon2-lon1).toRadians();
var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
现在使用:
var closest=locations[0];
var closest_distance=distance(closest,position.coords);
for(var i=1;i<locations.length;i++){
if(distance(locations[i],position.coords)<closest_distance){
closest_distance=distance(locations[i],position.coords);
closest=locations[i];
}
}
这具有O(n)的复杂性。对于5000个位置,大部分时间都是足够好的。
答案 1 :(得分:3)
您应该从所有位置构建一个kdtree(请参阅http://en.wikipedia.org/wiki/K-d_tree)并使用它来查找距用户位置最近的点。
Implementations- 有关可用的一些实现,请参阅Solid k-d tree implementation in javascript?。
答案 2 :(得分:0)
好吧,如果它在英国全部你肯定想要旋转位置以避免穿过零子午线(向所有经度加上180度,mod 360)。同时缩放纬度/经度,使得任一方向的一度与英国纬度的距离大致相同。
然后你可以在假设笛卡儿3D空间的情况下遵循sray的建议。
或者,如果您的位置数组不断变化,并且您不想每次都重建树,只需将每个位置映射到其3D笛卡尔距离并找到最小值。只有5k的位置,不应该太慢。