在 Openlayers 中,如何根据通过相同坐标的次数来缩放 MultiLineString 的笔划宽度?

In Openlayers, how can I scale the stroke width of a MultiLineString based on the number of times the same coordinates are passed through?

我的 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(),但我很难理解下一步该做什么。

如有任何帮助,我们将不胜感激。

我提出的解决方案是利用库 Turf 中名为 lineOverlap 的函数。请参阅该函数的文档 here。该函数接受两个线段和 returns 一个 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 的同时添加多层迭代应该会产生预期的效果。

是的,可以使用 Turf 来完成,但 Turf 仅适用于 EPSG:4326 坐标,在 EPSG:4326 中重叠的内容在 EPSG:3857 中显示时不一定重叠,反之亦然,例如 [[0,50],[5,55],[10,60]] 在转换为 EPSG:3857 时不是一条直线,而 [[0,50],[10,60]]是。转换还会引入非常小的舍入差异。尽管非常小,但任何差异都会阻止检测到重叠(并且使用 Turf 的 km 公差设置可能会产生误报)。此示例执行额外的迭代,并向您的 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>