2017-08-28 153 views
-2

我渲染谷歌地图的数据,看起来像这样一个折线:获取从纬度/经度点沿折线距离

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

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

我还没有找到一个简单的方法来做到这一点与地图API。我想要沿着折线从开始到任意点的距离;我发现的大多数答案只是两点之间的距离(最短),而不是沿着预定义的路线。

我的另一个想法是使用D3(我用它来绘制一些相关的图表)来平分数据并获得距离。然而,我不知道如何基于两个数据点(lat + lng)平分。

有关如何完成我想要做的任何建议?

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

+0

的[计算在给定时间地理位置(可能的复制https://stackoverflow.com/questions/ 25562799 /按给定时间计算地理位置) – geocodezip

+0

我对Google Maps API不熟悉,但如何确定此距离?它有一个方向(下一点)吗?如果多段线上的悬停位置位于两点的中间,并且您不知道沿路径分布的地形如何,则必须将最后一点与光标之间的距离和近似值加起来。 – LEI

+0

如果你看看我对链接问题的回答,它会使用第三方库函数'GetPointAtDistance'来做到这一点。 – geocodezip

回答

0

我猜我希望Google地图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. 计算上的折线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); 
}); 
+0

我不认为这会让你从*开始到沿着折线*的任意点。它会让你从一开始到多线上已有的点之一,对吧?如果你的光标在两点之间的一半,你会失去这个距离,不是吗? –

+0

这是真的,但对我的目的而言(+/- 30英尺)就足够了。如有必要,我可以增加折线密度以提高精度。 – ericgio

0

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

+0

虽然我不希望两点之间的距离最短。我想要在两点之间沿着多段线*的距离*,即:从起点到多段线上任意一点的距离的累积距离。这通常不是最短的距离。 – ericgio

+0

是不是[polyline](https://developers.google.com/maps/documentation/javascript/examples/polyline-simple)只是一个段的列表?然后你的光标应该在一行,你会做*每个点之间的长度的总和,直到被徘徊*,但也许我误解了一些东西?请回答编辑您的问题更多的细节,演示链接将是很好的。 – LEI

+0

实际上,尽管使用了Maps的'computeDistanceBetween'方法,这或多或少是我最终做的。 – ericgio

1

您可以使用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英里路线非常接近,并非都是直线。

+0

你分解它的方式是有道理的,但希望不要添加另一个第三方库。我发布了一个关于我如何使用Maps API和普通JS实现的答案。 – ericgio