【问题标题】:How to calculate a distance between two points along a path?如何计算路径上两点之间的距离?
【发布时间】:2017-01-11 13:56:12
【问题描述】:

我正在使用 openlayers3,并且我有编码的几何图形。我可以获得路径中所有点的坐标(lat,lng)(每条路径大约 500 个点)。给定路径内的一个随机点,我如何计算路径起点到该点之间的距离?

我查看了 turfjs,它看起来很有希望,但我使用它描绘的解决方案并不是很好。取一个随机点 (p1),我可以发现路径中最接近 p1 的点 (p2),然后生成一个新多边形并计算其总距离。它可能存在性能问题,尽管搜索将是 O(log n) 和新的多边形 O(n)。

编辑:随机点不一定在路径内,它是 GPS 坐标,存在误差。

编辑 2:对点数的估计已关闭,每条路径大约有 500 个点,而不是 5k

有人知道更好的方法吗?我对 openlayers3 和 turfjs 都不是很有经验。

【问题讨论】:

  • 每条路径 5k 点听起来非常密集,您可以将其解释为折线。我将创建(并缓存)一个数组,该数组包含从起点到每个点的距离总和。因此,您可以通过 2 次数组查找 + 减法获得两个点之间的距离。
  • 您可以循环路径的点,计算各个路径的距离,存储最后一个点并在每次迭代中检查所需点是否在最后一个点和实际点之间。如果条件为真,则将此随机点作为实际点并停止计算。
  • @Thomas,这个随机点不是坐标之一,所以不是简单的查找,我要找到离随机点最近的坐标。
  • @jose-hermosilla-rodrigo 该点不一定在路径内,随机点是 GPS 坐标,因此可能存在一些定位错误。无论如何,到目前为止,您的答案更完整,如果没有更好的选择,请将其放在答案中,我会接受。
  • 使用使用叉积的公式得到距离。您只需要线的 2 个点,以及要计算距离的点。

标签: javascript openlayers-3 turfjs


【解决方案1】:

正如您提到的,您使用的是 OpenLayers 3,我使用 OpenLayers 3 做了一个示例,想法是:

  1. 给定坐标获取Closest Point across the LineString

  2. 遍历 LineString 点,计算每个单独路径的距离,看看我们最近的点是否与单独的路径相交。

/* Let's Generate a Random LineString */

var length = 5000;

var minLongitude = Math.random()*-180 + 180;

var minLatitude = Math.random()*-90 + 90;

var wgs84Sphere = new ol.Sphere(6378137);

var lastPoint = [minLongitude, minLatitude]

var points = Array.from({ length })
.map( _ =>{
  var newPoint =  [
    Math.random() * (Math.random() > 0.8 ? -.005 : .005) + lastPoint[0]
    , Math.random() * (Math.random() > 0.2 ? -.005 : .005) + lastPoint[1]
  ]
  lastPoint = newPoint;
  return newPoint;
})

var distanceTotal = points
.reduce((dis, p, i)=>{
  if(points[i + 1])
    dis += wgs84Sphere.haversineDistance(p, points[i + 1] )
    return dis;          
}, 0);

console.log(distanceTotal)

var extent = new ol.extent.boundingExtent(points)

//console.log(points)

var lineString = new ol.Feature({
  geometry : new ol.geom.LineString(points)
});

var source = new ol.source.Vector();

var layer = new ol.layer.Vector({ source });

source.addFeature(lineString);


var map = new ol.Map({
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    })
  ],
  target: 'map',
  controls: ol.control.defaults({
    attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
      collapsible: false
    })
  }),
  view: new ol.View({
    projection : 'EPSG:4326',
    center: [0, 0],
    zoom: 2
  })
});

map.addLayer(layer)
map.getView().fit(extent, map.getSize())

var auxLayer = new ol.layer.Vector({ source : new ol.source.Vector() })

var styleAux = new ol.style.Style({
  stroke: new ol.style.Stroke({
    color: 'green',
    width: 2
  })
});

var styleAuxLine = new ol.style.Style({
  stroke: new ol.style.Stroke({
    color: 'green',
    width: 0.5
  })
});

var styleAuxPoint = new ol.style.Style({
  image : new ol.style.Circle({
    radius: 5,
    fill: null,
    stroke: new ol.style.Stroke({color: 'black', width: 2})
  })
});

var styleAuxSourcePoint = new ol.style.Style({
  image : new ol.style.Circle({
    radius: 3,
    fill: null,
    stroke: new ol.style.Stroke({color: '#00bbff', width: 0.5})
  })
});

auxLayer.setStyle(function(f, r){
  var type = f.getGeometry().getType();
  if(type === 'LineString') return styleAux;
  return styleAuxPoint;
})

map.addLayer(auxLayer);

map.on('pointermove', function(e){
  if(e.dragging) return;
  var coord = e.coordinate;
  var distance = 0;

  var pointsGeometry = [];

  var sourcePointFeature = new ol.Feature({
    geometry : new ol.geom.Point(coord)
  });

  var closestPoint = lineString.getGeometry().getClosestPoint(coord);                
  var lineDiffFeature = new ol.Feature({
    geometry : new ol.geom.LineString([
      coord, closestPoint
    ])
  });
  for(let i = 0; i< points.length - 1; i++){
    var p = points[i]
    var next = points[i + 1];
    var subLineStringGeom = new ol.geom.LineString([ p, next ]);

    pointsGeometry.push(p);

    var e = 1e-10;
    var extent = [ closestPoint[0] - e, closestPoint[1] - e
                  , closestPoint[0] + e, closestPoint[1] + e
                 ]

    if(subLineStringGeom.intersectsExtent(extent)){
      //console.log(i);
      pointsGeometry.push(closestPoint);
      distance += wgs84Sphere.haversineDistance(p, closestPoint);
      break;
    }
    distance += wgs84Sphere.haversineDistance(p, next);
  }
  console.log(closestPoint)
  var cpGeometry = new ol.geom.Point(closestPoint);
  var cpFeature = new ol.Feature({ geometry : cpGeometry });

  var geometry = new ol.geom.LineString(pointsGeometry);
  var newFeature = new ol.Feature({ geometry });

  auxLayer.getSource().clear();
  auxLayer.getSource().refresh();

  auxLayer.getSource().addFeature(lineDiffFeature);
  auxLayer.getSource().addFeature(newFeature);
  auxLayer.getSource().addFeature(sourcePointFeature);
  auxLayer.getSource().addFeature(cpFeature);
  sourcePointFeature.setStyle(styleAuxSourcePoint);
  lineDiffFeature.setStyle(styleAuxLine);
  //console.log(geometry.getLength())
  console.log(distance);

})
html, body, #map {
  width : 100%;
  height : 100%;
  padding : 0px;
  margin : 0px;
}
<script src="https://openlayers.org/en/v3.20.1/build/ol.js"></script>
<link href="https://openlayers.org/en/v3.20.1/css/ol.css" rel="stylesheet"/>
<div id="map" class="map" tabindex="0"></div>

【讨论】:

  • 谢谢,这非常有帮助。
猜你喜欢
  • 2021-04-30
  • 2012-06-14
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
相关资源
最近更新 更多