turfjs是一个地理空间分析库,用于处理各种空间计算
在工作中有需要对图形进行拆分需求,网上也查了一些资料,都不是很好用,所以自己实现了一下,在实现过程中也遇到了点问题。特此分享一下,供大家参考
/**
* 拆分多边形
* @param feature 待拆分的openlayers feature
* @param lineFeature 绘制的分割线段feature
* @returns {*[]|*}
*/
function splitFeature(feature, lineFeature) {
let geoJson = new ol.format.GeoJSON();
let geojsonFeature = geoJson.writeFeatureObject(feature);
//获取由孔生成的feature
let holeFeature = this.getHoleFeature(geojsonFeature);
if (geojsonFeature.geometry.type == 'Polygon') {
//去掉孔,后面统一处理
geojsonFeature.geometry.coordinates = [geojsonFeature.geometry.coordinates[0]]
} else {
//multipolygon 去掉带孔,后面统一处理
geojsonFeature.geometry.coordinates = geojsonFeature.geometry.coordinates.map(c => [c[0]]);
}
let geojsonSplitFeature = geoJson.writeFeatureObject(lineFeature);
let outerLine = turf.polygonToLine(geojsonFeature);
outerLine = turf.truncate(outerLine, {precision: 7});
let truncatedSplitter = turf.truncate(geojsonSplitFeature, {precision: 7});
let intersectCollection = turf.lineIntersect(outerLine, truncatedSplitter);
if (intersectCollection.features.length < 2) {
return [];
}
let intersectCombined = turf.combine(intersectCollection).features[0];
// split lines with points
let outerPieceCollection = null;
if (outerLine.features) {
outerLine.features.forEach(f => {
let r = turf.lineSplit(f, intersectCombined);
if (!outerPieceCollection) {
outerPieceCollection = r;
} else {
outerPieceCollection.features.push(r);
}
})
} else {
//polygon
outerPieceCollection = turf.lineSplit(outerLine, intersectCombined);
}
let splitterPieceCollection = turf.lineSplit(truncatedSplitter, intersectCombined);
// polygonize pieces
let pieceCollection = turf.featureCollection(outerPieceCollection.features.concat(splitterPieceCollection.features));
let polygonCollection = turf.polygonize(pieceCollection);
// 过滤落在外面的feautre
let innerPolygons = this.filterOuterFeatures(feature, polygonCollection.features);
// 带孔多边形的处理
if (holeFeature) {
innerPolygons = innerPolygons.map(p => {
return turf.difference(p, holeFeature);
})
}
let innerPolygonCollection = turf.featureCollection(innerPolygons);
//转成ol feature
let features = geoJson.readFeatures(innerPolygonCollection);
return features;
}
/**
* 获取由geojsonFeature中的孔生成的feature
* @param geojsonFeature
*/
function getHoleFeature(geojsonFeature) {
let coordinates;
if (geojsonFeature.geometry.type == 'Polygon') {
//去掉带孔的,后面统一处理
if (geojsonFeature.geometry.coordinates.length > 1) {
coordinates = geojsonFeature.geometry.coordinates.slice(1);
}
} else {
coordinates = [];
geojsonFeature.geometry.coordinates.forEach(c => {
if (c.length > 1) {
coordinates = coordinates.concat(c.slice(1));
}
});
}
if (!coordinates || coordinates.length == 0) {
return null;
}
return {
geometry: {
coordinates: coordinates,
type: 'MultiPolygon'
},
type: 'Feature'
}
}
/**
* 过滤落在外面的feature
* @param orgFeature
* @param resultFeatures
* @returns {*}
*/
function filterOuterFeatures(orgFeature, resultFeatures) {
let geoJson = new ol.format.GeoJSON();
let orgFeatures;
if (orgFeature.getGeometry().getType() == 'MultiPolygon') {
//multipolygon转多个polygon
let polygons = orgFeature.getGeometry().getPolygons();
orgFeatures = polygons.map(polygon => {
let feature = new ol.Feature({
geometry: polygon
});
return geoJson.writeFeatureObject(feature);
});
} else {
orgFeatures = [geoJson.writeFeatureObject(orgFeature)];
}
let innerPolygons = resultFeatures.filter(polygon => {
//生成缓冲区
let bufferP = turf.buffer(polygon, -0.00000006, {units: 'degrees'});
bufferP = turf.truncate(bufferP, {precision: 7});
let find = orgFeatures.find(org => {
//判断拆分后的面是否落在原始多边形内
return turf.booleanContains(org, bufferP);
})
if (find) {
return true;
}
return false;
});
return innerPolygons;
},