从数组中获取最近的纬度和经度

时间:2015-03-18 09:48:34

标签: javascript arrays loops

我正在尝试编写一个以性能为导向的数组查找,它将返回相对于用户当前位置最近的经度和纬度。

一个问题是我的数组中有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"
                }
            ]

3 个答案:

答案 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的位置,不应该太慢。