简体   繁体   English

Openlayers日期线交叉线串消失

[英]Openlayers dateline crossing linestring disappears

I am working on openlayers, there is an issue when I try to add a linestring on the map which crosses the dateline several times. 我正在使用openlayers,当我尝试在地图上添加多次跨越日期线的线串时出现问题。

To display the linestring across two worlds in the continuous segment I have added a function HandleDateline() which returns me modified (shifted either to left or right world) coordinates. 为了显示连续段中两个世界的线串,我添加了一个HandleDateline()函数,该函数返回修改后的坐标(向左或向右移动)

However, when you zoom-in on the left world to current settled view the linestring disappears. 但是,当您在左侧环境中放大到当前的固定视图时,线串将消失。 Also if you try to move the map to left, the line goes away. 同样,如果您尝试将地图向左移动,该线也会消失。

The weird thing is if the line crosses more than 1 time, linestring on left worlds disappears otherwise same happens for right worlds. 奇怪的是,如果线相交超过1次,则左侧世界上的线串消失,否则右侧世界上的情况相同。 Too observe that, remove either first 3 or last 3 points from datelinecrossing[] which I will be posting down. 太注意了,从我将要张贴的datelinecrossing[]删除前3个点或最后3个点。

I am expecting a continuous linestring crossing the international dateline without any issues like disappearing. 我希望连续的线串跨越国际日期变更线而不会出现任何消​​失的问题。

If there is a better approach to this, I am open to all ideas. 如果有更好的方法,我愿意接受所有想法。 Here is the bin : ol dateline problem 这是bin: ol dateline problem

You have to split the lines crossing the dateline programmatically at the dateline. 您必须以编程方式在日期线上分割与日期线交叉的线。

 var points = [ [-170, -10], [170, 0], [-170, 10] ]; var vectorSource = new ol.source.Vector(); vectorSource.addFeature(createFeature(points)); var vectorLayer = new ol.layer.Vector({ source: vectorSource, style: new ol.style.Style({ stroke: new ol.style.Stroke({ width: 2, color: "red" }) }) }); var osmLayer = new ol.layer.Tile({ source: new ol.source.OSM() }); var map = new ol.Map({ layers: [osmLayer, vectorLayer], target: document.getElementById("map"), view: new ol.View({ center: ol.proj.transform([180, 0], "EPSG:4326", "EPSG:3857"), zoom: 3 }) }); var graticule = new ol.Graticule({ strokeStyle: new ol.style.Stroke({ color: "rgba(255,120,0,0.9)", width: 1.5, lineDash: [0.5, 4] }), showLabels: true }); graticule.setMap(map); // ------------------------------------------------- function createFeature(points) { var pointsSplitted = []; var pointsArray = []; pointsSplitted.push(points[0]); var lastLambda = points[0][0]; for (var i = 1; i < points.length; i++) { var lastPoint = points[i - 1]; var nextPoint = points[i]; if (Math.abs(nextPoint[0] - lastLambda) > 180) { var deltaX = xToValueRange(nextPoint[0] - lastPoint[0]); var deltaY = nextPoint[1] - lastPoint[1]; var deltaXS = xToValueRange(180 - nextPoint[0]); var deltaYS; if (deltaX === 0) { deltaYS = 0; } else { deltaYS = deltaY / deltaX * deltaXS; } var sign = lastPoint[0] < 0 ? -1 : 1; pointsSplitted.push([180 * sign, nextPoint[1] + deltaYS]); pointsArray.push(pointsSplitted); pointsSplitted = []; pointsSplitted.push([-180 * sign, nextPoint[1] + deltaYS]); } pointsSplitted.push(nextPoint); lastLambda = nextPoint[0]; } pointsArray.push(pointsSplitted); var geom = new ol.geom.MultiLineString(pointsArray); geom.transform("EPSG:4326", "EPSG:3857"); var feature = new ol.Feature({ geometry: geom }); return feature; } function xToValueRange(x) { if (Math.abs(x) > 180) { var sign = x < 0 ? -1 : 1; return x - 2 * 180 * sign; } else { return x; } } 
 html, body, #map { width: 100%; height: 100%; overflow: hidden } 
 <link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" /> <script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script> <body> <div id="map" class="map" tabindex="0"></div> </body> 

Simplifying HandleDateline so all coordinates are either in the western part of the normal world or the eastern part of the left world seems to fix it (so if the geometry crosses the date line the extent starts in the left world) 简化HandleDateline以便所有坐标都位于正常世界的西部或左侧世界的东部,似乎可以解决此问题(因此,如果几何图形越过日期线,则范围将从左侧世界开始)

 function HandleDateline(array) {
        for (var i = 0; i < array.length ; i++) {
            if (array[i][0] > 0) {
                array[i][0] -= 360;
            }
        }
    }

However in worlds to the right the points west of the dateline then appear to be rendered below to linestring, while those east of the dateline are above it. 但是,在右侧的世界中,日期线以西的点似乎呈现在线串的下方,而日期线以东的点则位于线串的上方。 Moving HandleDateline(datelinecrossing); 移动HandleDateline(datelinecrossing); above datelinecrossing.forEach fixes that. 上述datelinecrossing.forEach解决此问题。

You might also want to consider using a multipoint geometry for the points (unless you need them to be individually selectable). 您可能还需要考虑对点使用多点几何体(除非您需要它们可以单独选择)。

HandleDateline(datelinecrossing);
var pdlcrossing = new ol.Feature({
    geometry: new ol.geom.MultiPoint(datelinecrossing).transform('EPSG:4326', 'EPSG:3857')
});
drawingSource.addFeature(pdlcrossing);
var dlcrossing = new ol.Feature({
    geometry: new ol.geom.LineString(datelinecrossing).transform('EPSG:4326', 'EPSG:3857')
});
drawingSource.addFeature(dlcrossing);

There is still a problem zooming in west of the dateline in the worlds on the right, so I think there will need to be two sets of each geometry, one offset to the left and another 360 degrees to the right: 在右边的世界中,在日期线以西缩放时仍然存在问题,因此我认为每种几何都需要两组,一组向左偏移,另一组向右360度:

function PlotGeometries(datelinecrossing){
  var pgeom = new ol.geom.MultiPoint(datelinecrossing);
  var pdlcrossing = new ol.Feature({
    geometry: pgeom.clone().transform('EPSG:4326', 'EPSG:3857')
  });
  drawingSource.addFeature(pdlcrossing);
  pgeom.translate(360,0);
  var pdlcrossing2 = new ol.Feature({
    geometry: pgeom.transform('EPSG:4326', 'EPSG:3857')
  });
  drawingSource.addFeature(pdlcrossing2);
  var geom = new ol.geom.LineString(datelinecrossing);
  var dlcrossing = new ol.Feature({
    geometry: geom.clone().transform('EPSG:4326', 'EPSG:3857')
  });
  drawingSource.addFeature(dlcrossing);
  geom.translate(360,0);
  var dlcrossing2 = new ol.Feature({
    geometry: geom.transform('EPSG:4326', 'EPSG:3857')
  });
  drawingSource.addFeature(dlcrossing2);
}

只需为您正在处理的世界的一部分设置地图视图的范围即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM