我的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(),但是我很难理解下一步该怎么做。
任何帮助将不胜感激。
答案 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]);
}
的同时添加多层迭代应该具有预期的效果。