【问题标题】:Get distance along polyline from lat/lng point从纬度/经度点沿折线获取距离
【发布时间】:2017-08-28 18:01:09
【问题描述】:

我在 Google 地图上渲染一条折线,其数据如下所示:

data = [
  {
    distance: 3.45,
    lat: 37.37112776376307,
    lng: -122.13909476995468,
  },
  ...
];

当悬停在折线上时,我可以获得lat/lng 坐标,我想根据这些坐标获得沿线的距离。

我还没有找到使用 Maps API 执行此操作的简单方法。我想要从起点到沿折线任意点的距离;我发现的大多数答案都只是处理两点之间的(最短)距离,而不是沿着预定义的路线。

我的另一个想法是使用 D3(我用来绘制一些相关图表)来平分数据并获取距离。但是,我不知道如何根据两个数据点进行一分为二 (lat+ lng)。

关于如何完成我想做的事情的任何建议?

编辑:在我的数据中,distance 是在给定坐标处行进的累积距离。

【问题讨论】:

  • 我不熟悉 Google Maps API,但是这个距离是怎么确定的呢?它有方向(下一点)吗?如果折线上的悬停位置在两点的中间,并且不知道地形沿路径的分布情况,则必须将最后一点与光标之间的距离相加并得出近似值。跨度>
  • 如果您查看我对链接问题的回答,它会使用第三方库函数 GetPointAtDistance 来执行此操作。
  • @geocodezip:我想要那个答案的倒数,即:GetDistanceAtPoint 而不是GetPointAtDistance

标签: javascript google-maps d3.js


【解决方案1】:

您可以使用Turf 库来执行此操作(以及更多操作)。

使用 Turf,您可以将问题分解为几个较小的问题 —

  • 找到离光标最近的行的准确位置
  • 创建一条从起点到该点的折线
  • 测量该折线的长度。

例如,这里有一条从芝加哥到缅因州波特兰的路线,我们想知道它到雪城和波士顿之间的线路附近但不在我们路线上的斯克内克塔迪有多远:

const turf = require('@turf/helpers')
const lineSlice = require('@turf/line-slice')
const pointOnLine = require('@turf/point-on-line')
const lineDistance = require('@turf/line-distance')

var route = turf.lineString([
[-87.627453, 41.853555], // Chicago
[-87.389126, 41.587682], // Gary IN
[-81.674692, 41.420385], // Clevland
[-76.077655, 42.988040], // Syracuse
[-71.066601, 42.323782], // Boston
[-70.277662, 43.627106]  // Portland, ME
]);

var Schenectady = turf.point([-73.899115, 42.815089]); //Schenectady

var snapped = pointOnLine(route, Schenectady, 'miles');
var sliced = lineSlice(route.geometry.coordinates[0], snapped, route);
var length = lineDistance(sliced, 'miles');

console.log(length) // => 736.8317888716095

这与 Google 的 810 英里路线非常吻合,但并非都是直线。

【讨论】:

  • 您分解它的方式是有道理的,但希望不要添加另一个第 3 方库。我发布了一个关于我如何使用 Maps API 和普通 JS 的答案。
【解决方案2】:

我想我希望 Maps API 有一个类似

的方法
polyLine.computeDistanceBetween(point1, point2);

但事实并非如此。

我最终解决了类似于上面@Mark_M 描述的问题:

  1. Find the point on the polyline closest to the hovered point

    function getIndexOfNearestPoint(path, hoveredPoint) {
      let index = -1;
      let minDistance = 1000;
    
      path.forEach((pointOnPath, idx) => {
        const dist = window.google.maps.geometry.spherical.computeDistanceBetween(
          hoveredPoint,
          pointOnPath
        );
    
        if (dist < minDistance){
          minDistance = dist;
          index = idx;
        }
      });
    
      return index;
    }
    
  2. 计算折线上两点之间的距离

    function getDistanceAlongPath(path, startIndex, endIndex) {
      let distance = 0;
      for (let ii = startIndex; ii < endIndex; ii++) {
        distance += window.google.maps.geometry.spherical.computeDistanceBetween(
          path[ii],
          path[ii + 1]
        );
      }
      return distance;
    }
    

把它放在一起找到从折线起点到悬停点的累积距离:

polyline.addListener('mousemove', e => {
  const path = polyline.getPath().getArray();
  const hoveredPoint = e.latLng;
  const startIndex = 0;

  const endIndex = getIndexOfNearestPoint(path, hoveredPoint);
  const distance = getDistanceAlongPath(path, startIndex, endIndex);
});

【讨论】:

  • 我认为这不会让您从起点到折线的任意点。它让你从一开始就到达折线上的一个点,对吧?如果您的光标位于两点之间的中间,您会失去那个距离,不是吗?
  • 没错,但对于我的目的来说已经足够了(+/- 30 英尺)。如有必要,我可以增加折线密度以提高精度。
【解决方案3】:

如果您的数据集只是lat/lng 的列表,您可以使用this answer 根据Haversine formula(地球表面的最短距离)计算每个点之间的距离。

【讨论】:

  • 我不想要两点之间的最短距离。我想要两点之间沿折线的距离,即:从起点到悬停在折线上的任何点的累积距离。这通常不是最短距离。
  • polyline 不只是一个段列表吗?然后你的光标应该在一条线上,你会做每个点之间的长度总和,直到悬停的那个,但也许我误解了什么?请通过使用更多详细信息编辑您的问题来回答,演示链接会很好。
  • 实际上,这或多或少是我最终做的,虽然使用地图的computeDistanceBetween 方法。
猜你喜欢
  • 2017-09-05
  • 2014-08-29
  • 2015-02-26
  • 2019-12-09
  • 1970-01-01
  • 2013-10-25
  • 2012-07-07
  • 1970-01-01
相关资源
最近更新 更多