根据坐标在数组中查找对象
Find object in array based on coordinates
假设我有一个如下格式的数组:
var arr = [{lat: 123.123, lng: 321.321}, {lat: 567.567, lng: 765.765}]
基于一些地图坐标,我如何才能最有效地找到与地图坐标最接近的坐标的对象?
一个简单的解决方法是:
var getClosestPoint = function(coord, coordArray) {
var bestDistance = null;
var bestCoord = null;
for (var i = 0; i < coordArray.length; ++i) {
var currentCoord = coordArray[i];
var distance = getDistance(coord, currentCoord);
if ((bestDistance == null) || (distance < bestDistance)) {
bestDistance = distance;
bestCoord = currentCoord;
}
}
return {'distance': bestDistance, 'coord':bestCoord};
};
// Based on the solution here:
// http://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates
var getDistance = function(coordA, coordB) {
var R = 6371; // km
var dLat = (coordB.lat-coordA.lat).toRad();
var dLon = (coordB.lng-coordA.lng).toRad();
var lat1 = coordA.lat.toRad();
var lat2 = coordB.lat.toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
};
换句话说,朴素解就是迭代所有的点,更新当前的最佳距离和相应的坐标。如果你列出的要点很少,这样做可能是合理的。然而,更有效的解决方案是使用树结构,其中树中的每个内部节点由该节点下所有点的平均坐标表示。然后,您通过使用最近的平均坐标的节点降序搜索树,直到您到达叶节点。这种方法允许您在每次迭代中抛出更多的候选点,从而给出对数解。
换句话说,更有效的解决方案是:
var getClosestPoint = function(coord, coordNode) {
var children = coordNode.getChildren();
if (children.length == 0) {
return coordNode.getCenterCoord();
}
var closestChild = null;
var bestDistance = 0.0;
for (var i = 0; i < children.length; ++i) {
var currentCoord = children[i].getCenterCoord();
var distance = getDistance(coord, currentCoord);
if ((closestChild == null) || (distance < bestDistance)) {
closestChild = children[i];
bestDistance = distance;
}
}
return getClosestPoint(coord, closestChild);
}
当然,这假设您首先构建了这样一个树。如果您使用相同的点集重复运行"getClosestPoint()",那么构建这样的结构可能是值得的(如果您只对任何给定的点集执行一次"getClosestPoint()",那么朴素的解决方案可能是合理的)。关于K-D树和四叉树的文章可能会对进一步阅读这种一般方法以及如何在这些树中建立和划分点感兴趣。
我相信这应该在方形网格上工作。如果数值在某个点后重置,如在地球上,则需要对该解决方案进行一些调整。
function calculateDistance(x1, x2, y1, y2){
return Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2));
}
var retrievedCoords = {lat: 12234, lng: 135};
var closestPoint = arr[0];
var distanceToClosestPoint = calculateDistance(retrievedCoords.lat, arr[0].lat, retrievedCoords.lng, arr[0].lng);
for (var i = 1; i < arr.length; i++){
var tempDist = calculateDistance(retrievedCoords.lat, arr[i].lat, retrievedCoords.lng, arr[i].lng);
if (tempDist > distanceToClosestPoint){
closestPoint = arr[i];
distanceToClosestPoint = tempDist;
}
}
相关文章:
- Javascript:根据对象的嵌套数组中的值,在数组中查找对象的索引
- 正在数组中查找对象
- 在prototypejs中查找对象的类
- 通过知道对象的id在JSON中查找对象
- Javascript在JSON中查找对象(我使用Angular)
- 查找对象数组是否包含其中一个标记的最快方法
- 如何将查找对象值传递到FetchXml查询中
- JavaScript-通过类似的属性查找对象,并将其推送到一个新的数组中
- 通过匹配 - Javascript/AngularJS 中的参数来查找对象
- 正在查找对象集合的最大值
- 根据Angular JS中的属性值在列表中查找对象
- 在下划线中的对象中查找对象中的重复项
- 如何使用正则表达式查找对象成员名称
- 通过包含的字符串查找对象
- 在 Firebase 中通过对象的唯一 id 查找对象
- 在 javascript 中查找对象的类型
- 查找对象树中特定字段值的所有出现
- 如何在javascript数组中按键和值查找对象的索引
- 使用 Javascript/React.js 查找对象的数组索引
- 查找对象数组(Angularjs)中是否存在值