据我所知,OpenLayers中没有内置功能可以将两个点的直线投影到跟随地球曲率的曲线上。
当我有一条直接通过马达加斯加的路线时,这是一个问题:
此问题的前端是否有任何解决方案,我在OpenLayers中遗漏的任何功能,或者是否有任何第三方解决方案来计算此问题。
我知道这种计算在前端很难,而且还取决于两点之间点的分辨率。
答案 0 :(得分:3)
我不认为openlayers有针对此问题的打包解决方案。有一些选项可以解决这个问题,一个是使用javascript取两个点并返回代表大圆路径的geoJson路线。
使用诸如arc.js之类的库,我们可以在两点之间绘制大圆弧:
var generator = new arc.GreatCircle({x: -90, y: -70},{x: 89, y: 70}); // points to connect
var n = 50; // n of points
var coords = generator.Arc(n).geometries[0].coords;
var geojson = {"type":"Feature","geometry":{"type":"LineString","coordinates": coords},"properties":null } ;
然后你可以将geojson传递给openlayers。请参阅this gist。
然而,由于大多数渲染器不使用球面几何体(相反处理纬度,而不是笛卡尔坐标,这解释了您试图避免的直线),这种建议的方法仍然会导致在北部附近撞击的长线段极点,因为每个线段仍然是一条直线,并且杆本身占据整个顶部/底部线,通常是默认投影。一种解决方案是使用arc.js沿着线采样更多点,请参阅此gist(更好地查看here,它将为您节省平移)。虽然如果长线段仍然存在,可以通过剪切地图的北边缘或限制其可见性来修复此问题。
另一种方法是使用d3这样的库,它可以与openlayers配对,默认情况下使用球形几何(因此是我所知道的唯一可以使绕组的库,工具或程序多边形的顺序很重要(当使用地理坐标空间时,因为它不会将地理坐标视为平面 - 而技术上geojsonlint和其他geojson验证器会因为“错误”缠绕而抱怨,这些验证器不会考虑您可能选择多边形边缘另一边的空间))。这是一个较低级别的库,但它将提供更多的能力来定制地图,但需要开箱即用的解决方案。
连接两个点的基本线可能看起来像(取决于设置):
var geojson = {"type":"Feature","geometry":{"type":"LineString","coordinates": [[90,50],[-89,50]]},"properties":null };
var feature = svg.append("path")
.datum(geojson)
.attr("d",path);
var width = 600, height = 300;
var svg = d3.select("svg")
.attr("width",width)
.attr("height",height);
var projection = d3.geoMercator() // projection type
.translate([width/2,height/2])
.scale(width/Math.PI/2*0.7)
var path = d3.geoPath().projection(projection) // path generator
var geojson = [
{"type":"Feature","geometry":{"type":"LineString","coordinates": [[90,50],[-89,50]]},"properties":null },
{"type":"Feature","geometry":{"type":"LineString","coordinates": [[90,-50],[-89,50]]},"properties":null }];
var feature = svg.selectAll("path")
.data(geojson)
.enter().append("path")
.attr("d",path)
.attr("stroke","steelblue")
.attr("stroke-width",3)
// Add the world to reference the lines:
d3.json("https://unpkg.com/world-atlas@1/world/110m.json", function(error, world) {
if (error) throw error;
svg.append("path")
.datum(topojson.mesh(world))
.attr("d",path)
.attr("stroke","#ccc")
.lower();
});
path {
fill: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/3.0.2/topojson.js"></script>
<svg></svg>