Openlayers линии пересечения даты исчезает - PullRequest
0 голосов
/ 07 февраля 2019

Я работаю над открытыми слоями, возникает проблема, когда я пытаюсь добавить линию линий на карту, которая пересекает линию даты несколько раз.

Чтобы отобразить строку линий в двух мирах в непрерывном сегменте, который я добавилфункция HandleDateline(), которая возвращает мне измененный (смещенный влево или вправо) координаты.

Однако при увеличении масштаба левого мира до текущего установленного вида линия линий исчезает,Также, если вы попытаетесь переместить карту влево, линия исчезнет.

Странная вещь: если линия пересекается более 1 раза, линейная линия в левых мирах исчезает, в противном случае то же самое происходит и для правых миров.Также обратите внимание, что удалите либо первые 3, либо последние 3 точки из datelinecrossing[], которые я буду публиковать вниз.

Я ожидаю, что непрерывная линейная линия пересекает международную линию без каких-либо проблем, таких как исчезновение.

Если есть лучший подход к этому, я открыт для всех идей.Вот корзина: ol dateline problem

Ответы [ 3 ]

0 голосов
/ 07 февраля 2019

Необходимо разделить линии, пересекающие линию даты, программно на линии даты.

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>
0 голосов
/ 07 февраля 2019

Упрощение 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);
}
0 голосов
/ 07 февраля 2019

Просто установите экстент для вида карты для той части мира, над которой вы работаете.

...