2017-01-11 4 views
2

私はopenlayers3を使用していますが、私はエンコードされたジオメトリを持っています。パス内のすべてのポイント(パスあたり約500ポイント)の座標(lat、lng)を取得できます。パス内にランダムな点がある場合、パスの始点からその点までの距離をどのように計算すればよいでしょうか?パスに沿って2つのポイント間の距離を計算する方法は?

私はturfjsを見てきましたが、それは非常に有望ですが、私がそれを使って描いた解決策はあまりうまくいかないでしょう。ランダムな点(p1)を取ることで、p1に最も近いパスの点(p2)を見つけて新しいポリゴンを生成し、その総距離を計算することができました。 O(log n)と新しいポリゴンO(n)が検索されますが、パフォーマンスの問題が発生する可能性があります。

EDIT:ランダムな点は必ずしも経路の内側にあるわけではなく、GPS座標で誤差があります。

EDIT 2:ポイント数の推定はオフ、各パスが約500点を持った、ではない5kの

より良いアプローチの人を知っていますか?私はopenlayers3とturfjsのどちらにもあまり経験はありません。

+1

5Kポイントはかなり密に聞こえる、あなたはポリラインとしてこれを解釈することができます。私は最初から各点までの距離の合計を保持する配列を作成(およびキャッシュ)します。したがって、2つの配列の参照+減算によって、2つの点の間の距離を取得することができます。 – Thomas

+1

パスのポイントをループし、個々のパスの距離を計算し、最後のポイントを保存し、必要なポイントが最後のポイントと実際のポイントの間にある場合は各繰り返しをチェックインできます。条件が真の場合、このランダムな点を実際の点として使用し、計算を停止します。 –

+0

@Thomas、このランダムな点は座標の1つではないので、単なるルックアップではなく、ランダムな点に最も近い座標を見つけなければなりません。 – lalkmim

答えて

3

あなたはOpenLayersを3を使用している述べたように、私はOpenLayers 3を使用した例をやった、アイデアは次のとおりです。

  1. Closest Point across the LineStringが計算ラインストリングのポイントを超える座標

  2. 反復を与えなさい個々のパスの距離を計算し、最も近いポイントが個々のパスと交差するかどうかを確認します。パスあたり

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

+2

ありがとう、それは非常に役に立ちました。 – lalkmim

関連する問題