webgis端通用的几何要素LineString分割Polygon
作者:互联网
完整代码类如下:
import * as turf from '@turf/turf'
/**
* geoJson数据处理模块
* (需要引入turf.js)
* 输入输出数据均为标准geoJson格式
*/
const geoClipUtil = {
/**
* 合并多边形
*/
unionPolygon: function (polygons) {
var polygon = polygons[0];
for (var i = 0; i < polygons.length; i++) {
polygon = turf.union(polygon, polygons[i]);
};
return polygon;
},
/**
* 线分割面
* 面类型只能是polygon或是环
* 线与多边形必须有两个交点
*/
polygonClipByLine: function (polygon, clipLine) {
if (polygon.geometry.type === 'Polygon') {
var polyLine = turf.polygonToLine(polygon)
if (polyLine.geometry.type === 'LineString') { // 切割普通多边形
return this.singlePolygonClip(polyLine, clipLine);
} else if (polyLine.geometry.type === 'MultiLineString') { //切割环
return this.multiPolygonClip(polyLine, clipLine);
}
} else if (polygon.geometry.type === 'MultiPolygon') {
// 若输入的多边形类型为Multipolygon则拆分成多个Polygon
var polygons = this.multiPolygon2polygons(polygon)
var clipPolygon = null;
var clipPolygonIndex = -1
// 获取MultiPolygon中与切割线相交的多边形(有且只能有一个多边形相交2个交点)
polygons.forEach(function (polygon, index) {
var polyLine = turf.polygonToLine(polygon)
if (turf.lineIntersect(polyLine, clipLine).features.length === 2) {
if (!clipPolygon) {
clipPolygon = polygon
clipPolygonIndex = index
} else {
return { state: 'error', message: 'MultiPolygon只能有一个多边形与切割线存在交点' };
}
}
})
if (clipPolygonIndex !== -1) {
polygons.splice(clipPolygonIndex, 1)
return turf.featureCollection(polygons.concat(this.polygonClipByLine(clipPolygon, clipLine).features));
} else {
return { state: 'error', message: 'MultiPolygon与切割线无交点' };
}
} else {
return { state: 'error', message: '输入的多边形类型为错误' };
}
},
/**
* 线分割面
* 切割普通多边形
*/
singlePolygonClip: function (polyLine, clipLine) {
// 获得裁切点
var intersects = turf.lineIntersect(polyLine, clipLine);
if (intersects.features.length !== 2) {
return { state: 'error', message: '切割线与多边形交点应该为2个,当前交点个数为' + intersects.features.length };
}
// 检查切割线与多边形的位置关系 (切割线的起点和终点不能落在多边形内部)
var clipLineLength = clipLine.geometry.coordinates.length;
var clipLineStartPoint = turf.point(clipLine.geometry.coordinates[0])
var clipLineEndPoint = turf.point(clipLine.geometry.coordinates[clipLineLength - 1])
var polygon = turf.polygon([polyLine.geometry.coordinates])
if (turf.booleanPointInPolygon(clipLineStartPoint, polygon) || turf.booleanPointInPolygon(clipLineEndPoint, polygon)) {
return { state: 'error', message: '切割线起点或终点不能在 裁剪多边形内部' };
}
// 通过裁切点 分割多边形(只能获得多边形的一部分)
var slicedPolyLine = turf.lineSlice(intersects.features[0], intersects.features[1], polyLine);
// 裁剪线分割 保留多边形内部部分
var slicedClipLine = turf.lineSlice(intersects.features[0], intersects.features[1], clipLine);
// 重新拼接多边形 存在 对接的问题 所以先进行判断 如何对接裁剪的多边形和裁剪线
var resultPolyline1 = this.connectLine(slicedPolyLine, slicedClipLine)
resultPolyline1.properties.clipName = 'clip_01'
// 闭合线 来构造多边形
resultPolyline1.geometry.coordinates.push(resultPolyline1.geometry.coordinates[0])
var resultPolygon1 = turf.lineToPolygon(resultPolyline1);
// 构造切割的另一面多边形
var firstPointOnLine = this.isOnLine(turf.point(polyLine.geometry.coordinates[0]), slicedPolyLine);
var pointList = [];
if (firstPointOnLine) {
for (var i = 0; i < polyLine.geometry.coordinates.length; i++) {
var coordinate = polyLine.geometry.coordinates[i];
if (!this.isOnLine(turf.point(coordinate), slicedPolyLine)) {
pointList.push(coordinate)
}
};
} else {
var skipNum = 0; // 记录前面被跳过的点的个数
var isStartPush = false;
for (var i = 0; i < polyLine.geometry.coordinates.length; i++) {
var coordinate = polyLine.geometry.coordinates[i];
if (!this.isOnLine(turf.point(coordinate), slicedPolyLine)) {
if (isStartPush) {
pointList.push(coordinate)
} else {
skipNum++
}
} else {
isStartPush = true;
}
};
// 将前面跳过的点补充到 点数组中
for (var i = 0; i < skipNum; i++) {
pointList.push(polyLine.geometry.coordinates[i])
}
}
var slicedPolyLine_2 = turf.lineString(pointList, slicedPolyLine.properties);
var resultPolyline2 = this.connectLine(slicedPolyLine_2, slicedClipLine)
resultPolyline2.properties.clipName = 'clip_02'
// 闭合线 来构造多边形
resultPolyline2.geometry.coordinates.push(resultPolyline2.geometry.coordinates[0])
var resultPolygon2 = turf.lineToPolygon(resultPolyline2);
// 返回面要素集
return {
features: turf.featureCollection([
resultPolygon1,
resultPolygon2
]), state: 'success'
};
},
/**
* 线分割面
* 切割环
*/
multiPolygonClip: function (polyLine, clipLine) {
// 将环 多边形分割成 内部逆时针多边形+外部多边形
var outPolyline, insidePolylineList = [];
for (var i = 0; i < polyLine.geometry.coordinates.length; i++) {
var splitPolyline = turf.lineString(polyLine.geometry.coordinates[i]);
if (turf.booleanClockwise(splitPolyline)) {
if (outPolyline) {
return { state: 'error', message: '出现了两个外部多边形无法处理' };
} else {
outPolyline = splitPolyline
}
} else {
var intersects = turf.lineIntersect(splitPolyline, clipLine);
if (intersects.features.length > 0) {
return { state: 'error', message: '切割线不能与内环有交点' };
}
insidePolylineList.push(splitPolyline)
}
}
var resultCollection = this.singlePolygonClip(outPolyline, clipLine)
for (var i = 0; i < resultCollection.features.length; i++) {
for (var j = 0; j < insidePolylineList.length; j++) {
var startPoint = turf.point(insidePolylineList[j].geometry.coordinates[0]);
if (turf.booleanPointInPolygon(startPoint, resultCollection.features[i])) {
resultCollection.features[i] = turf.mask(resultCollection.features[i], turf.lineToPolygon(insidePolylineList[j]));
}
}
}
return resultCollection
},
/**
* 连接两条线
* 方法会将两条线段最近的一段直接连接
*/
connectLine: function (line1, line2) {
var line2_length = line2.geometry.coordinates.length;
var line1_startPoint = line1.geometry.coordinates[0]
var line2_startPoint = line2.geometry.coordinates[0]
var line2_endPoint = line2.geometry.coordinates[line2_length - 1]
var pointList = [];
// 获取line1 所有点坐标
for (var i = 0; i < line1.geometry.coordinates.length; i++) {
var coordinate = line1.geometry.coordinates[i];
pointList.push(coordinate)
};
// 判断两条线的 起点是否接近,如果接近 逆转line2线 进行连接
if (turf.distance(line1_startPoint, line2_startPoint) < turf.distance(line1_startPoint, line2_endPoint)) {
line2.geometry.coordinates = line2.geometry.coordinates.reverse();
}
for (var i = 0; i < line2.geometry.coordinates.length; i++) {
var coordinate = line2.geometry.coordinates[i];
pointList.push(coordinate)
};
return turf.lineString(pointList, line1.properties);
},
/**
* 判断点是否在线里面
* 注:线组成的坐标对比
*/
isOnLine: function (point, line) {
for (var i = 0; i < line.geometry.coordinates.length; i++) {
var coordinate = line.geometry.coordinates[i];
if (point.geometry.coordinates[0] === coordinate[0] && point.geometry.coordinates[1] === coordinate[1]) {
return true;
}
};
return false;
},
/**
* 获得两条线交点
*/
getIntersectPoints: function (line1, line2) {
return turf.lineIntersect(line1, line2);
},
/**
* multiPolygon转polygons
*/
multiPolygon2polygons: function (multiPolygon) {
if (multiPolygon.geometry.type !== 'MultiPolygon') {
return
}
var polygons = [];
multiPolygon.geometry.coordinates.forEach((item) => {
var polygon = {
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: []
}
};
polygon.geometry.coordinates = item;
polygons.push(polygon)
});
return polygons;
},
/**
* polygons转multiPolygon
* 考虑polygons中就存在多面的情况
*/
polygons2MultiPolygon: function (geoJson) {
var newGeoJson = {
type: "FeatureCollection",
features: [{ geometry: { coordinates: [], type: "MultiPolygon" }, type: "Feature", properties: {} }]
};
geoJson.features.forEach((item) => {
if (item.geometry.type === "Polygon") {
newGeoJson.features[0].geometry.coordinates.push(item.geometry.coordinates);
} else {
item.geometry.coordinates.forEach((item) => {
newGeoJson.features[0].geometry.coordinates.push(item);
})
}
})
return newGeoJson;
},
}
export default geoClipUtil
基于turf的相关api链接:GET START | Turf.js中文网
示例:多边形切割demo
标签:多边形,Polygon,geometry,webgis,coordinates,return,var,turf,LineString 来源: https://blog.csdn.net/u013869554/article/details/120516495