我使用的是openlayers3,我有编码的几何体。我可以得到路径中所有点的坐标(lat,lng)(每条路径约500个点)。给定路径中的随机点,如何计算路径开始到该点之间的距离?
我已经看过turfjs并且看起来非常有希望,但我用它描绘的解决方案并不是很好。取一个随机点(p1),我可以发现最接近p1的路径的点(p2),然后生成一个新的多边形并计算它的总距离。尽管搜索将是O(log n)和新的多边形O(n)。
,但它可能存在性能问题编辑:随机点不一定在路径内,它是一个GPS坐标,并且存在误差范围。
编辑2:关闭点数的估计,每条路径大约有500点,而不是5k
有谁知道更好的方法?我对openlayers3和turfjs都不是很有经验。
答案 0 :(得分:3)
如你所说,你正在使用OpenLayers 3,我使用OpenLayers 3
做了一个例子,其想法是:
获取Closest Point across the LineString
坐标
迭代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>