使用turf.js进行面拆分

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;

        },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值