【问题标题】:Calculate point between two coordinates based on a percentage根据百分比计算两个坐标之间的点
【发布时间】:2016-02-27 16:45:15
【问题描述】:

我正在寻找一个函数,它返回两点之间的点(纬度、经度)(我还指定了它们的经度、经度),并且该点基于距离百分比。

所以,我在函数上指定了 Lat1、Lon1、Lat2、Lon2 和一个 %,它返回一个点,例如,从第一个点到第二个点的距离为 20%。

【问题讨论】:

  • 如果您使用的是 Google Maps api,请查看 interpolate,它会计算其他两个点之间的某个分数 (0-1) 之间的一个点。

标签: javascript coordinates geocoding


【解决方案1】:

这两个答案可能对特定用户有用,但我想指出一些问题。

lguiel 的解决方案适用于游戏或短距离,但不适用于地球上的几何计算。

spirographer 的答案是正确的,但由于它非常理论化,因此可能很难编程。

我将第二个答案翻译成实用的编程语言,以便您可以将其用于自己的项目。

Full code | Run online

// Original calculation from https://www.movable-type.co.uk/scripts/latlong.html
LatLng calculateIntermediatePoint(LatLng point1, LatLng point2, double perc) {
  //const φ1 = this.lat.toRadians(), λ1 = this.lon.toRadians();
  //const φ2 = point.lat.toRadians(), λ2 = point.lon.toRadians();
  double lat1 = degreesToRadians(point1.latitude);
  double lng1 = degreesToRadians(point1.longitude);
  double lat2 = degreesToRadians(point2.latitude);
  double lng2 = degreesToRadians(point2.longitude);

  //const Δφ = φ2 - φ1;
  //const Δλ = λ2 - λ1;
  double deltaLat = lat2 - lat1;
  double deltaLng = lng2 - lng1;

  //const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ/2) * Math.sin(Δλ/2);
  //const δ = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  double calcA = sin(deltaLat / 2) * sin(deltaLat / 2) +
      cos(lat1) * cos(lat2) * sin(deltaLng / 2) * sin(deltaLng / 2);
  double calcB = 2 * atan2(sqrt(calcA), sqrt(1 - calcA));

  //const A = Math.sin((1-fraction)*δ) / Math.sin(δ);
  //const B = Math.sin(fraction*δ) / Math.sin(δ);
  double A = sin((1 - perc) * calcB) / sin(calcB);
  double B = sin(perc * calcB) / sin(calcB);

  //const x = A * Math.cos(φ1) * Math.cos(λ1) + B * Math.cos(φ2) * Math.cos(λ2);
  //const y = A * Math.cos(φ1) * Math.sin(λ1) + B * Math.cos(φ2) * Math.sin(λ2);
  //const z = A * Math.sin(φ1) + B * Math.sin(φ2);
  double x = A * cos(lat1) * cos(lng1) + B * cos(lat2) * cos(lng2);
  double y = A * cos(lat1) * sin(lng1) + B * cos(lat2) * sin(lng2);
  double z = A * sin(lat1) + B * sin(lat2);

  //const φ3 = Math.atan2(z, Math.sqrt(x*x + y*y));
  //const λ3 = Math.atan2(y, x);
  double lat3 = atan2(z, sqrt(x * x + y * y));
  double lng3 = atan2(y, x);

  //const lat = φ3.toDegrees();
  //const lon = λ3.toDegrees();
  return LatLng(radiansToDegrees(lat3), radiansToDegrees(lng3));
}

【讨论】:

  • 谢谢。可以确认,即是正确答案。像魅力一样工作!
【解决方案2】:

假设坐标是十进制数。你可以使用这个等式。

function midpoint(lat1, long1, lat2, long2, per) {
     return [lat1 + (lat2 - lat1) * per, long1 + (long2 - long1) * per];
}

根据百分比返回新的所需坐标 [lat, long](例如 per=0.2 表示 20%)。

【讨论】:

  • lat long 的中点一般不是这个公式计算的中点,因为它们是球体上的坐标,而不是平面。
  • Iguiel 我也想过这个,但不是这样。例如,对于 P1(37.740675, -25.661043) 和 P2(37.738096, -25.669267),20% 返回 P3(7.5478771, -5,133031)。这让我身处非洲,而不是 P1 和 P2 之间的亚速尔群岛。
  • 嗨 Swift-R,我明白了,我认为我的方程式有误,应该是:[lat1+(lat2-lat1)*per, long1+(long2-long1)*per] I将编辑我的答案。我希望它对你有用。
  • 除了地图之外,这对于其他与 javascript 相关的创意来说实际上是一个非常好的功能 - 我用这支笔试驾了它codepen.io/headwinds/pen/BLVXwa?editors=0010
  • 这个等式在数学上是不正确的。线性插值纬度/经度不是正确的球面数学。
【解决方案3】:

这是一个很有帮助的参考资料(检查底部)

http://www.movable-type.co.uk/scripts/latlong.html

中间点

也可以计算两点之间大圆路径上任意分数的中间点。

公式:

a = sin((1−f)⋅δ) / sin δ
b = sin(f⋅δ) / sin δ
x = a ⋅ cos φ1 ⋅ cos λ1 + b ⋅ cos φ2 ⋅ cos λ2
y = a ⋅ cos φ1 ⋅ sin λ1 + b ⋅ cos φ2 ⋅ sin λ2
z = a ⋅ sin φ1 + b ⋅ sin φ2
φi = atan2(z, √x² + y²)
λi = atan2(y, x)

其中 f 是沿大圆路线的分数(f=0 是点 1,f=1 是点 2),δ是两点之间的角距离d/R

【讨论】:

  • 我不明白百分比的来源。
  • f 是从点 1 到点 2 的分数。百分比是分母为 100 的分数。例如,如果您的百分比是 39%,那么分数f = 39/100.
猜你喜欢
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 2013-07-25
  • 2020-02-12
  • 1970-01-01
  • 1970-01-01
  • 2021-08-04
  • 2011-08-13
相关资源
最近更新 更多