如何将地图上的两点线投影成曲线OpenLayers [英] How to project two point line on the map into a curved line OpenLayers

查看:65
本文介绍了如何将地图上的两点线投影成曲线OpenLayers的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,OpenLayers中没有内置功能可将两个点的直线投影成跟随地球曲率的曲线.

As for my knowledge, there is no built-in feature in OpenLayers to project the straight line of two points into curved line following the curvature of the Earth.

当我有一条直达马达加斯加的路线时,这是一个问题:

This was a problem when I got a route that was going straight through Madagascar:

前端是否有解决此问题的解决方案,我在OpenLayers中缺少的任何功能,还是有任何第三方解决方案来计算此问题.

Is there any solution on the frontend for this problem, any feature that I missed in OpenLayers, or is there any third-party solution to calculate this.

我知道这种计算很难在前端进行,而且还取决于两点之间的点的分辨率.

I know that this kind of calculation is hard on the frontend, and it also depends on the resolution of the dots between two points.

推荐答案

我不认为openlayers有针对此问题的打包解决方案.有多种方法可以解决此问题,但是,一种方法是使用javascript取得两点并返回代表大圆路径的geoJson路线.

I do not believe that openlayers has a packaged solution for this problem. There are options for dealing with this however, one is to use javascript to take two points and return geoJson routes that represent great circle paths.

使用诸如 arc.js 之类的库,我们可以在两个之间绘制大圆弧点:

Using a library such as arc.js, we can plot great circle arcs between two points:

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.参见此要点.

Then you can pass the geojson on to openlayers. See this gist.

但是,由于大多数渲染器不使用球形几何图形(而是将经度和纬度视作笛卡尔,这说明了您要避免的直线),因此建议的方法仍然可以导致长线段在北方附近命中极点,因为每个线段仍然是一条直线,而极点本身占据了整个上/下线(通常是默认投影).一种解决方案是使用arc.js对沿线的更多点进行采样,请参见要点(更好的视图此处,它将节省您的平移).尽管如果长线段仍然存在,则可以通过裁剪地图的北边缘或限制其可见性来解决此问题.

However, as most renderers don't use spherical geometry (instead treating lat,long as cartesian, which explains the straight lines you are trying to avoid), this suggested approach can still lead to long line segments that hit near the north pole, as each segment is still a straight line and the pole itself occupies the entire top/bottom line in what is often the default projection. One solution would be to sample many more points along the line using arc.js, see this gist (better view here, it'll save you the panning up). Though if long line segments persist, this might be fixed by clipping the northern edge of the map, or restricting its visibility.

另一种选择是使用诸如d3之类的库,该库可以与openlayers配对,并且默认情况下使用球形几何体(因此,这是我所知道的唯一可以绕线的库,工具或程序多边形的顺序很重要(使用地理坐标空间时,因为它不会将地理坐标视为平面-虽然从技术上讲,geojsonlint和其他geojson验证器会抱怨缠绕"错误,但这些验证器并没有考虑到您可能正在选择多边形边缘另一侧的空间).这是一个较低级别的库,但将提供更多自定义地图的功能,但以开箱即用的解决方案为代价.

The alternative is to use a library such as d3, which can be paired with openlayers, and which uses spherical geometry by default ( and consequently is the only library, tool, or program I know of that will make winding order of polygons matter (when using geographic coordinate space, since it doesn't treat geographic coordinates as planar - while technically geojsonlint and other geojson validators will complain if it is wound "wrong", these validators aren't considering that you might be selecting the space on the other side of a polygon's edges)). This is a lower level library, but will offer some more ability to customize the map at the expense of out of the box solutions.

连接两点的基本线可能看起来像(取决于设置):

A basic line connecting two points might look like (depending on setup):

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>

这篇关于如何将地图上的两点线投影成曲线OpenLayers的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆