如何计算路径上两点之间的距离?

时间:2017-01-11 13:56:13

标签: javascript openlayers-3 turfjs

我使用的是openlayers3,我有编码的几何体。我可以得到路径中所有点的坐标(lat,lng)(每条路径约500个点)。给定路径中的随机点,如何计算路径开始到该点之间的距离?

我已经看过turfjs并且看起来非常有希望,但我用它描绘的解决方案并不是很好。取一个随机点(p1),我可以发现最接近p1的路径的点(p2),然后生成一个新的多边形并计算它的总距离。尽管搜索将是O(log n)和新的多边形O(n)。

,但它可能存在性能问题

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

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

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

1 个答案:

答案 0 :(得分:3)

如你所说,你正在使用OpenLayers 3,我使用OpenLayers 3做了一个例子,其想法是:

  1. 获取Closest Point across the LineString坐标

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

  3. /* 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>