Openlayers日期线交叉线串消失

Openlayers dateline crossing linestring disappears

我正在使用 openlayers,当我尝试在地图上添加多次穿过日期变更线的线串时出现问题。

为了在连续段中显示跨越两个世界的线串,我添加了一个函数 HandleDateline(),returns 我修改了它 (移动到左世界或右世界)坐标.

但是,当您将左侧世界放大到当前固定视图时,线串会消失。此外,如果您尝试将地图向左移动,该线就会消失。

奇怪的是,如果线交叉超过 1 次,左侧世界的线串会消失,否则右侧世界也会发生同样的情况。请注意,从我将发布的 datelinecrossing[] 中删除前 3 点或后 3 点。

我期待跨越国际日期变更线的连续线串不会出现任何消​​失等问题。

如果有更好的方法,我愿意接受所有想法。 这是垃圾箱:ol dateline problem

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

您必须在日期变更线上以编程方式拆分跨越日期变更线的线。

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>

简化 HandleDateline 所以所有坐标要么在正常世界的西部,要么在左边世界的东部似乎修复了它(所以如果几何穿过日期变更线,范围从左世界)

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

然而,在右边的世界中,日期变更线以西的点似乎呈现在线串下方,而日期变更线以东的点则在其上方。将 HandleDateline(datelinecrossing); 移动到 datelinecrossing.forEach 上方可以解决这个问题。

您可能还想考虑对点使用多点几何(除非您需要它们可以单独选择)。

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);

在右侧的世界中,在日期变更线以西进行缩放仍然存在问题,因此我认为每个几何体需要两组,一组向左偏移,另一组向右偏移 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);
}