【发布时间】:2017-11-01 11:16:45
【问题描述】:
据我所知,OpenLayers 中没有内置功能可以将两点的直线投影成跟随地球曲率的曲线。
当我得到一条直通马达加斯加的路线时,这是一个问题:
前端是否有解决这个问题的方法,我在 OpenLayers 中遗漏的任何功能,或者是否有任何第三方解决方案来计算这个问题。
我知道这种计算在前端很难,而且还取决于两点之间的点的分辨率。
【问题讨论】:
标签: openlayers curve points map-projections
据我所知,OpenLayers 中没有内置功能可以将两点的直线投影成跟随地球曲率的曲线。
当我得到一条直通马达加斯加的路线时,这是一个问题:
前端是否有解决这个问题的方法,我在 OpenLayers 中遗漏的任何功能,或者是否有任何第三方解决方案来计算这个问题。
我知道这种计算在前端很难,而且还取决于两点之间的点的分辨率。
【问题讨论】:
标签: openlayers curve points map-projections
我不相信 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>
【讨论】: