在Openlayers中,如何根据传递相同坐标的次数缩放MultiLineString的笔触宽度?

时间:2019-03-02 06:19:11

标签: openlayers openlayers-5

我的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 :(得分:1)

是的,可以使用Turf来完成,但是Turf仅适用于EPSG:4326坐标,并且当显示在EPSG:3857中时,EPSG:4326中的重叠部分不一定重叠,反之亦然,例如[[0,50] ,[5,55],[10,60]]转换为EPSG:3857时不是很直线,而[[0,50],[10,60]]则是直线。变换还会引入很小的舍入差异。尽管差异很小,但将不会检测到任何重叠(并且使用Turf的km公差设置会产生假阳性)。本示例进行了额外的迭代,并向MultiLineString中添加了一个额外的组件以测试较长线段的顶点之间的交点。在四舍五入到12个位置后,在EPSG:4326中检测到重叠(即使现实分数值也可能不起作用),但是如果放大得足够多,您会发现它是EPSG:3857中的平行线。真正需要的是基于Turf lineOverlap源的函数,该函数将在任何坐标上工作并处理适合那些坐标的mm公差。

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>

答案 1 :(得分:0)

我想出的解决方案是利用Turf库中名为lineOverlap的函数。请参阅该功能here的文档。该函数接受两个线段,并返回其中有重叠的FeatureCollection的{​​{1}}。

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]); } 的同时添加多层迭代应该具有预期的效果。