В Openlayers, как я могу масштабировать ширину обводки MultiLineString в зависимости от того, сколько раз проходили одни и те же координаты? - PullRequest
0 голосов
/ 02 марта 2019

Моя MultiLineString в настоящее время имеет такой стиль:

'MultiLineString': new Style({
    stroke: new Stroke({
        color: 'green',
        width: 1
    })
}),

И координаты для моей MultiLineString выглядят примерно так:

[
[[3, 8], [4, 10], [5, 12]],
[[2, 4], [3, 8], [4, 10]]
]

, где есть некоторые совпадения в данных.Я хочу масштабировать ширину линии, где данные перекрываются, чтобы проиллюстрировать, что линия пропадает несколько раз.Я предполагаю, что мне нужно использовать RenderFunction () , но мне трудно понять, что делать дальше.

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

Да, это можно сделать с помощью Turf, но Turf работает только с EPSG: 4326 координат, и что перекрытия в EPSG: 4326 не обязательно будут перекрываться при отображении в EPSG: 3857 и наоборот, например [[0,50], [5,55], [10,60]] не совсем прямая линия при преобразовании в EPSG: 3857, тогда как [[0,50], [10,60]].Преобразования также вводят очень небольшие различия округления.Несмотря на очень маленькую разницу, любое различие прекратит обнаружение перекрытий (а использование параметра допуска Turf для км может дать ложные срабатывания).Этот пример выполняет дополнительные итерации и добавляет дополнительный компонент в MultiLineString для проверки пересечения между вершинами длинных отрезков.После округления до 12 мест в EPSG обнаруживается перекрытие: с 4326 (с реальными дробными значениями, которые могут даже не работать), но если вы увеличите масштаб достаточно, вы увидите, что это параллельная линия в EPSG: 3857.Что действительно необходимо, так это функция, основанная на источнике Turf lineOverlap, которая будет работать с любыми координатами и обрабатывать допуски в мм, соответствующие этим координатам.

var transformR = function(coordinates, output, dimensions) {
  var dims = dimensions || 2;
  for (var i=0; i<coordinates.length; i+=dims) {
coordinates[i] = Math.round(coordinates[i]*1e12)/1e12;
coordinates[i+1] = Math.round(coordinates[i+1]*1e12)/1e12;
  }
  return coordinates;
}

var style = function(feature) {

  switch(feature.getGeometry().getType()) {
case 'MultiLineString': 

  var increment = 2;
  var styles = [
    new ol.style.Style({
      stroke: new ol.style.Stroke({
        color: 'green',
        width: increment
      })
    })
  ];

  var overlaps = [];
  var format = new ol.format.GeoJSON();
  var geometry = feature.getGeometry().clone().transform(map.getView().getProjection(), 'EPSG:4326');
  geometry.applyTransform(transformR); // round transformed coordinates
  var linestrings = geometry.getLineStrings();
  for (var i=0; i<linestrings.length-1; i++) {
    for (var j=i+1; j<linestrings.length; j++) {
      var line1 = format.writeFeatureObject(new ol.Feature(linestrings[i]));
      var line2 = format.writeFeatureObject(new ol.Feature(linestrings[j]));
      var overlapping = turf.lineOverlap(line1, line2).features;
      overlapping.forEach(function(overlap){ overlaps.push(overlap.geometry.coordinates); });
    }
  }
  overlaps.forEach(function(overlap){
    var width = increment;
    var line = turf.lineString(overlap);
    for (var i=0; i<linestrings.length; i++) {
      var line1 = format.writeFeatureObject(new ol.Feature(linestrings[i]));
      var overlapping = turf.lineOverlap(line, line1).features;
      if (overlapping.length > 0 && JSON.stringify(overlapping[0].geometry.coordinates) == JSON.stringify(overlap)) {
        width += increment;
      }
    }
    styles.push(
      new ol.style.Style({
        geometry: new ol.geom.LineString(overlap).transform('EPSG:4326', map.getView().getProjection()),
        stroke: new ol.style.Stroke({
          color: 'green',
          width: width
        })
      })
    );
  });

  return styles;

  }

}

var multiline = new ol.Feature(new ol.geom.MultiLineString([
  [[6, 14], [2, 6]],
  [[3, 8], [4, 10], [5, 12]],
  [[2, 4], [3, 8], [4, 10]]
]));

var source = new ol.source.Vector();

var map = new ol.Map({
layers: [
    new ol.layer.Vector({
        source: source,
        style: style
    })
],
target: 'map',
view: new ol.View()
});

multiline.getGeometry().transform('EPSG:4326', map.getView().getProjection());
source.addFeature(multiline);

map.getView().fit(multiline.getGeometry());
<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>
<script src="https://npmcdn.com/@turf/turf@5.1.6/turf.min.js"></script>

<div id="map" class="map"></div>
0 голосов
/ 03 марта 2019

Решение, которое я придумал, заключается в использовании функции с именем lineOverlap в библиотеке Turf.Смотрите документацию по этой функции здесь .Функция принимает два линейных сегмента и возвращает FeatureCollection с перекрытием LineSegment.

import * as turf from '@turf/turf';
import GeoJSON from 'ol/format/GeoJSON.js';

const routes = [
    turf.lineString([[1,2],[3,4],[5,6]]),
    turf.lineString([[3,4],[5,6],[7,8]])
];
let overlapping = turf.lineOverlap(routes[0], routes[1]);

let format = new GeoJSON();

// convert to a format readable by OverLayers
let lines = format.readFeatures(overlapping);

// lines will only ever have a length of 1 or 0
if(lines.length) {

  // this adds an attribute onto the feature which I then read in the styling function
  lines[0].set('size', 2);

  lines[0].getGeometry().transform('EPSG:4326', 'EPSG:3857');
  vectorSource.addFeature(lines[0]);
}

Добавление нескольких слоев итерации при увеличении size должно иметь желаемый эффект.

...