使用turf分割多边形(面)

618 阅读2分钟

- 公司需求,所以写了一个公共的class来进行多边形的分割:(画一条线去分割一个多边形)

class chunkUtil {
    constructor() {
        this.turf = window.turf || "";
        if (!this.turf) {
            throw new Error("请确定turf已挂载至window");
        }

    }
    clipPolygon(polygon, polyline) {
        const types = typeof polygon;
        const types1 = typeof polyline;
        if (!polygon) {
            throw console.error("请传入面");
        }
        if (!polyline) {
            throw console.error("请传入线");
        }
        if ([types, types1].includes('string')) {
            const polygonParse = JSON.parse(polygon);
            const polylineParse = JSON.parse(polyline);
            const isLon = !polygonParse && !polygonParse.features && !polygonParse.features.length;
            const isLine = !polylineParse && !polylineParse.features && !polylineParse.features.length;
            if (isLon || isLine) {
                throw new Error("请确定为面与线都为json串格式");
            }
            return this._setFloors(polygonParse, polylineParse)
        } else {
            throw new Error("暂时只支持json串格式的转换,如需支持json格式,请与作者沟通。");
        }

    }
    _setFloors(A, B) {
        const { turf } = this;
        if ([A.type, B.type].includes('FeatureCollection')) {
            const geojsonA = A.features[0];
            if (geojsonA.geometry.type !== 'Polygon') {
                throw new Error("第一个值请传入面");
            }

            const polyline = turf.polygonToLine(geojsonA);
            if (polyline.geometry.type === "LineString") {
                const lines = B.features[0]
                const singClip = this._singeClips(polyline, lines)
                return singClip

            }
        }

    }

    _singeClips(A, B) {
        const { turf } = this;
        const C = turf.lineIntersect(A, B);
        if (C.features.length !== 2) {
            throw new Error("请确定线与面有两个相交点");
        }
        const L = B.geometry.coordinates.length;
        const SP = turf.point(B.geometry.coordinates[0]);
        const EP = turf.point(B.geometry.coordinates[L - 1]);
        const P = turf.polygon([A.geometry.coordinates])
        if (turf.booleanPointInPolygon(SP, P) || turf.booleanPointInPolygon(EP, P)) {
            throw new Error("线起点或终点不能在面内部");
        }
        const PL = turf.lineSlice(C.features[0], C.features[1], A);
        const CL = turf.lineSlice(C.features[0], C.features[1], B);
        const RL = this.connectLine(PL, CL);
        RL.geometry.coordinates.push(RL.geometry.coordinates[0]); //闭合
        const RP1 = turf.lineToPolygon(RL);
        const FL = this.isLines(turf.point(A.geometry.coordinates[0]), PL);
        const pList = [];
        if (FL) {
            for (let i = 0; i < A.geometry.coordinates.length; i++) {
                const coordinate = A.geometry.coordinates[i];
                if (!this.isLines(turf.point(coordinate), PL)) {
                    pList.push(coordinate)
                }

            }

        } else {
            let sNum = 0;
            let isStartPush = false;
            for (let i = 0; i < A.geometry.coordinates.length; i++) {
                const coordinate = A.geometry.coordinates[i];
                if (!this.isLines(turf.point(coordinate), PL)) {
                    if (isStartPush) {
                        pList.push(coordinate)
                    } else {
                        sNum++;
                    }
                } else {
                    isStartPush = true;
                }
            }


            for (let i = 0; i < sNum; i++) {
                pList.push(A.geometry.coordinates[i]);
            }


        }

        const PL2 = turf.lineString(pList);
        const RL2 = this.connectLine(PL2, CL);
        RL2.geometry.coordinates.push(RL2.geometry.coordinates[0]);
        const RP2 = turf.lineToPolygon(RL2);
        return turf.featureCollection([RP1, RP2])
    }
    connectLine(l1, l2) {
        const l2l = l2.geometry.coordinates.length;
        const l1sp = l1.geometry.coordinates[0];
        const l2sp = l2.geometry.coordinates[0];
        const l2ep = l2.geometry.coordinates[l2l - 1];
        const pList = [];
        for (let i = 0; i < l1.geometry.coordinates.length; i++) {
            const coordinate = l1.geometry.coordinates[i];
            pList.push(coordinate);
        }

        if (this.turf.distance(l1sp, l2sp) < this.turf.distance(l1sp, l2ep)) {
            l2.geometry.coordinates = l2.geometry.coordinates.reverse();
        }
        for (let i = 0; i < l2.geometry.coordinates.length; i++) {
            const coordinate = l2.geometry.coordinates[i];
            pList.push(coordinate);

        }
        return this.turf.lineString(pList)
    }

    isLines(P, L) {
        for (let i = 0; i < L.geometry.coordinates.length; i++) {
            const coordinate = L.geometry.coordinates[i];
            if (P.geometry.coordinates[0] === coordinate[0] && P.geometry.coordinates[1] === coordinate[1]) {
                return true
            }
        }
        return false;
    }
}

export { chunkUtil }

提示:

  1. 请确保turf已挂载至window;
  2. 请确保传入的面、线为字符串格式的json串;
  3. 如报错,请按照提示修改;
//引入该js;
    try{
        const chunkFn = new chunkUtil();
        const json = aaa.clipPolygon(a,c);
        console.log(json);
        \\json 为 多面。包括已分割的两个面,如需分开,把json.features中两个数组拎出即可。
    }catch(err){
        console.log(err.message);
    }

如需支持更多格式,请在该基础上进行修改或者联系我。有时间可进行优化。 如有错误处,请指正~~