You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Turf.js通过LineString分割多边形时仅生成单个多边形的问题求助

Turf.js通过LineString分割多边形时仅生成单个多边形的问题求助

我正在做一个项目,需要用LineString把一个多边形分割成两个独立的多边形,目前用Turf.js来处理相交、分割和多边形化这类几何操作。虽然我确认输入的几何数据看起来是正确的,但turf.polygonize函数始终只生成一个有效多边形,达不到我需要两个的要求。下面是我的具体场景、实现代码以及遇到的问题。

预期输出

用一条与多边形相交的LineString,将原多边形精确分割成两个有效的多边形。

我的实现代码

dividePolygon() {    
    try {

      const featureGroup = new L.FeatureGroup(this.layers);
      this.map.addLayer(featureGroup);

      this.selectedPlots.forEach(plot => {
        featureGroup.addLayer(plot);
      });

      const drawControl = new L.Control.Draw({
        edit: {
          featureGroup: featureGroup,
        },
        draw: {
          polyline: {
            shapeOptions: {
              color: 'red',
              weight: 4,
            },
          },
        },
      });

      this.map.addControl(drawControl);

      this.map.on(L.Draw.Event.CREATED, (e: any) => {

        const drawnLineLayer = e.layer as L.Polyline;

        featureGroup.eachLayer((layer: L.Layer) => {
          const plotGeoJSON = (layer as L.Polygon).toGeoJSON() as Feature<Polygon>;
          const drawnLineGeoJSON = drawnLineLayer.toGeoJSON() as Feature<LineString>;

          const intersectionPoints = turf.lineIntersect(drawnLineGeoJSON, plotGeoJSON);

          if (intersectionPoints.features.length > 0) {
            console.log("Original Polygon Coordinates:", plotGeoJSON.geometry.coordinates);
            console.log("Intersection Points: ", intersectionPoints);

            // Slice the line segment inside the polygon
            const slicedLine = turf.lineSlice(
              turf.point(intersectionPoints.features[0].geometry.coordinates),
              turf.point(intersectionPoints.features[1].geometry.coordinates),
              drawnLineGeoJSON
            );

            console.log("Sliced Line Coordinates:", slicedLine);

            const splitPolygons = this.splitPolygonWithLine(plotGeoJSON, slicedLine);

            if (splitPolygons && splitPolygons.length === 2) {

              // Updated polygons on the map
              const newPlot1Layer = L.geoJSON(splitPolygons[0]).addTo(this.map);
              const newPlot2Layer = L.geoJSON(splitPolygons[1]).addTo(this.map);

              // Remove the original polygon from the map
              this.map.removeLayer(layer);
            } else {
              console.error('Error: The polygon was not split into exactly two polygons.');
            }
          }
        });
      });

    } catch (error) {
      console.error('Error while dividing the polygon:', error);
    }
  }


  splitPolygonWithLine(polygon: Feature<Polygon>, line: Feature<LineString>): Feature<Polygon>[] | null {
    if (!turf.booleanIntersects(line, polygon)) {
      console.error("Error: Line does not intersect the polygon.");
      return null;
    }

    try {
      const flippedPolygon = turf.flip(polygon);
      const flippedLine = turf.flip(line);
      const polygonBoundary = turf.polygonToLine(flippedPolygon) as Feature<LineString>;

      // Split the polygon boundary using the slicing line
      const splitLines = turf.lineSplit(polygonBoundary, flippedLine);

      if (splitLines.features.length < 2) {
        console.error("Error: Unable to split the polygon boundary into two parts.");
        return null;
      }

      // Combine split lines with the slicing line to form the full boundary
      const combinedLines = turf.featureCollection([
        ...splitLines.features,
        flippedLine,
      ]);

      const splitPolygons = turf.polygonize(combinedLines);

      // Ensure polygons are closed loops
      splitPolygons.features.forEach(poly => {
        const coords = poly.geometry.coordinates[0];
        if (coords[0][0] !== coords[coords.length - 1][0] ||
          coords[0][1] !== coords[coords.length - 1][1]) {
          coords.push(coords[0]); // Close the loop if necessary
        }
      });

      const validPolygons = splitPolygons.features.filter(poly => {
        const area = turf.area(poly);
        return area > 0 && turf.booleanWithin(turf.centroid(poly), flippedPolygon);
      });

      // Ensure we have exactly two valid polygons
      if (validPolygons.length === 2) {
        return validPolygons.map(poly => turf.flip(poly));
      } else {
        console.error("Error: Did not generate exactly two valid polygons. Found:", validPolygons.length);
        return null;
      }
    } catch (error) {
      console.error("Error during polygon split:", error);
      return null;
    }
  }

核心问题

执行分割并调用turf.polygonize方法后,我只得到了一个多边形,而不是预期的两个。控制台输出的错误信息是:

Error: Did not generate exactly two valid polygons. Found: 1

即使相交点和分割后的线段看起来都是正确的,但最后合并线段并多边形化的步骤始终无法得到我想要的结果。

补充信息

下面是我测试时用到的几何数据:

flippedPolygon

{
    "type": "Feature",
    "properties": {},
    "geometry": {
        "type": "Polygon",
        "coordinates": [
            [
                [
                    48.347445,
                    4.112343
                ],
                [
                    48.347496,
                    4.112406
                ],
                [
                    48.347836,
                    4.112835
                ],
                [
                    48.34798,
                    4.113035
                ],
                [
                    48.348278,
                    4.113461
                ],
                [
                    48.348149,
                    4.113679
                ],
                [
                    48.347672,
                    4.114473
                ],
                [
                    48.347133,
                    4.115373
                ],
                [
                    48.346583,
                    4.116293
                ],
                [
                    48.346129,
                    4.11705
                ],
                [
                    48.345695,
                    4.117775
                ],
                [
                    48.345222,
                    4.118562
                ],
                [
                    48.344637,
                    4.119537
                ],
                [
                    48.344299,
                    4.120098
                ],
                [
                    48.344169,
                    4.119938
                ],
                [
                    48.343821,
                    4.119506
                ],
                [
                    48.343497,
                    4.119104
                ],
                [
                    48.343437,
                    4.119035
                ],
                [
                    48.343434,
                    4.118924
                ],
                [
                    48.343633,
                    4.118593
                ],
                [
                    48.343799,
                    4.118312
                ],
                [
                    48.34406,
                    4.117874
                ],
                [
                    48.344221,
                    4.117605
                ],
                [
                    48.344413,
                    4.117285
                ],
                [
                    48.34454,
                    4.117072
                ],
                [
                    48.344822,
                    4.116602
                ],
                [
                    48.34496,
                    4.116371
                ],
                [
                    48.345241,
                    4.115902
                ],
                [
                    48.345391,
                    4.11565
                ],
                [
                    48.345711,
                    4.115113
                ],
                [
                    48.346046,
                    4.114551
                ],
                [
                    48.346387,
                    4.113982
                ],
                [
                    48.346797,
                    4.113296
                ],
                [
                    48.347209,
                    4.112606
                ],
                [
                    48.347363,
                    4.112344
                ],
                [
                    48.347445,
                    4.112343
                ]
            ]
        ]
    }
}

flippedLine

{
    "type": "Feature",
    "properties": {},
    "geometry": {
        "type": "LineString",
        "coordinates": [
            [
                48.34542127624858,
                4.115599208013975
            ],
            [
                48.34619290725344,
                4.116943456469385
            ]
        ]
    }
}

备注:内容来源于stack exchange,提问作者Suhaib Janjua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 03:23:16