Javascript 在坐标数组中,找到离给定坐标最近的点

Javascript 在坐标数组中,找到离给定坐标最近的点,javascript,arrays,angular,typescript,arrayobject,Javascript,Arrays,Angular,Typescript,Arrayobject,我有一个对象,它有两个属性-纬度和经度。我想通过考虑两个属性从对象数组中获得最接近的匹配 obj = {latitude: 55.87, longitude: 4.20} [ { "latitude": 55.85, "longitude": 4.22 }, { "latitude": 55.89, "longitude": 4.16 }, { "

我有一个对象,它有两个属性-纬度和经度。我想通过考虑两个属性从对象数组中获得最接近的匹配

obj = {latitude: 55.87, longitude: 4.20}

[
  {
    "latitude": 55.85,
    "longitude": 4.22
  },
  {
    "latitude": 55.89,
    "longitude": 4.16
  },
  {
    "latitude": 55.88,
    "longitude": -4.24
  }
]

我需要得到最匹配的数组索引。

你可以用JS来实现这一点。你可以用这个


你可以用JS来做这件事。你可以用这个

计算点与阵列中每个点之间的球面距离有一个简单的方法,例如,使用:

const haversine={经度:洛纳,纬度:拉塔},{经度:洛纳,纬度:拉塔}=>{ 常数{PI,sin,cos,atan2}=Math, r=PI/180, R=6371, deltaLat=latB-latA*r, deltaLon=lonB-lonA*r, a=正弦塔拉/2**2+coscoslatB*r*latA*r*正弦塔拉/2**2, c=2*atan2a**0.5,1-a**0.5, d=R*c 返回d }, obj={纬度:55.87,经度:4.20}, arr=[{纬度:55.85,经度:4.22},{纬度:55.89,经度:4.16},{纬度:55.88,经度:-4.24}], {最近的}=arr.reducer,o=>{ 常数距离=哈弗西尼奥,obj 距离&& r、 最近距离=o,r。距离=距离 返回r },{最近的:空,距离:空} console.lognest .作为控制台包装器{min height:100%;}有一个计算点与阵列中每个点之间球面距离的方法,例如,使用:

const haversine={经度:洛纳,纬度:拉塔},{经度:洛纳,纬度:拉塔}=>{ 常数{PI,sin,cos,atan2}=Math, r=PI/180, R=6371, deltaLat=latB-latA*r, deltaLon=lonB-lonA*r, a=正弦塔拉/2**2+coscoslatB*r*latA*r*正弦塔拉/2**2, c=2*atan2a**0.5,1-a**0.5, d=R*c 返回d }, obj={纬度:55.87,经度:4.20}, arr=[{纬度:55.85,经度:4.22},{纬度:55.89,经度:4.16},{纬度:55.88,经度:-4.24}], {最近的}=arr.reducer,o=>{ 常数距离=哈弗西尼奥,obj 距离&& r、 最近距离=o,r。距离=距离 返回r },{最近的:空,距离:空} console.lognest
.as控制台包装{min height:100%;}使用下面的代码获取索引。我遵循与@Meadow相同的模式

let points = [{
        "latitude": 55.85,
        "longitude": 4.22
      },
      {
        "latitude": 55.89,
        "longitude": 4.16
      },
      {
        "latitude": 55.88,
        "longitude": -4.24
      },
      {
        "latitude": 55.86,
        "longitude": 4.21
      }
    ];
    let allDistance:any = [];

    points.forEach((x,index)=> {
      var res = this.getDistance(x.latitude, x.longitude, 55.87, 4.20, "km");
      allDistance.push({ distance: res, obj: x,index: index});
    });

    allDistance.sort((a, b) => a.distance - b.distance);
    console.log("Index:"+allDistance[0].index);  
    console.log(allDistance);   
获取距离方法:


使用下面的代码获取索引。我遵循与@Meadow相同的模式

let points = [{
        "latitude": 55.85,
        "longitude": 4.22
      },
      {
        "latitude": 55.89,
        "longitude": 4.16
      },
      {
        "latitude": 55.88,
        "longitude": -4.24
      },
      {
        "latitude": 55.86,
        "longitude": 4.21
      }
    ];
    let allDistance:any = [];

    points.forEach((x,index)=> {
      var res = this.getDistance(x.latitude, x.longitude, 55.87, 4.20, "km");
      allDistance.push({ distance: res, obj: x,index: index});
    });

    allDistance.sort((a, b) => a.distance - b.distance);
    console.log("Index:"+allDistance[0].index);  
    console.log(allDistance);   
获取距离方法:


这将有助于@alou:您所指的线程是关于平面坐标的,当谈到球面距离时(这里是这种情况),你需要一些更复杂的公式使用哈弗森公式计算每个点的距离,然后选择距离最短的点。这将有助于@alou:你所指的线是关于平面坐标的,当谈到球面距离时(这里是这种情况),您需要一些更复杂的公式使用哈弗森公式计算每个点的距离,然后选择距离最短的点。虽然您的代码不太适合直接基准测试,但我不能确定,我想说的是,建立距离数组并进行排序以找到最近的距离比在单个循环中找到最近的距离要昂贵。虽然您的代码不太适合直接基准测试,但我不能确定,我要说的是,建立距离数组并进行排序以查找最近的距离比在单个循环中查找最近的距离要昂贵。感谢您花时间编写代码Yevgen。非常感谢你的帮助。是的,我们可以这样做。我发现的另一个选择是在Angular中使用haversine库,它给出了输出。。。但是是的,就像你提到的,我们需要使用哈弗森公式来得到结果。@SuryaN:这完全取决于你-你是想实现10行自己的哈弗森实现还是维护外部库。哪一行在性能方面会更好?请让我知道。我是个新手。不幸的是,棱角不是我的强项,我来自React阵营,所以我不能用一些精确的基准来支持我的观点。不过,我想说的是,库的开销会多一点,所以它的执行速度可能会稍微慢一点,初始渲染速度可能会慢一点。我不建议使用该库的原因是完全不同的:对于一个由10行代码实现的功能来说,附加库并维护它的依赖关系似乎没有多大意义。我同意@Yevgen的观点。很好的解释。感谢您花时间编写代码Yevgen。非常感谢你的帮助。是的,我们可以这样做。我发现的另一个选择是使用
haversine在角度上给出了输出。。。但是是的,就像你提到的,我们需要使用哈弗森公式来得到结果。@SuryaN:这完全取决于你-你是想实现10行自己的哈弗森实现还是维护外部库。哪一行在性能方面会更好?请让我知道。我是个新手。不幸的是,棱角不是我的强项,我来自React阵营,所以我不能用一些精确的基准来支持我的观点。不过,我想说的是,库的开销会多一点,所以它的执行速度可能会稍微慢一点,初始渲染速度可能会慢一点。我不建议使用该库的原因是完全不同的:对于一个由10行代码实现的功能来说,附加库并维护它的依赖关系似乎没有多大意义。我同意@Yevgen的观点。很好的解释。
  getDistance(markerLat: any, markerLon: any, sourceLat: any, sourceLng: any,unit): any {
    var radlat1 = Math.PI * sourceLat / 180;
    var radlat2 = Math.PI * markerLat / 180;
    var theta = sourceLng - markerLon;
    var radtheta = Math.PI * theta / 180;
    var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
    if (dist > 1) {
      dist = 1;
    }
    dist = Math.acos(dist);
    dist = dist * 180 / Math.PI;
    dist = dist * 60 * 1.1515;
    dist = dist * 1.609344;
    if (unit != 'mi') {
      return isNaN(dist) ? 0 : dist;
    }
    return isNaN(dist * 0.62137) ? 0 : dist * 0.62137;
  }