openlayer 实现裁切功能

563 阅读1分钟

画线裁切

image.png

裁切结果

image.png

调用代码

调用 主要是使用turf实现

let line = res.customVectorLayer //获取openlayer绘制的线图层

let polygon = g_config.selectLayer //获取openlayer面图层

let geojsonFormat = new GeoJSON(); // 创建 GeoJSON 格式化对象

let featuresLine = line.getSource().getFeatures()
let geojsonStrLine = geojsonFormat.writeFeatures(featuresLine); 
geojsonStrLine = JSON.parse(geojsonStrLine)
let featuresPolygon = polygon.getSource().getFeatures()
let geojsonStrPolygon = geojsonFormat.writeFeatures(featuresPolygon); 
geojsonStrPolygon = JSON.parse(geojsonStrPolygon)
let polygonCuts = this.polygonCut(geojsonStrPolygon.features[0],geojsonStrLine.features[0])

polygonCut(poly, line, tolerance = 0.000001, toleranceType = 'kilometers') {
      if (line.geometry === void 0 || line.geometry.type.toLowerCase().indexOf('linestring') === -1) {
        // throw "传入的必须为linestring";
        return;
      }
    
      if (line.geometry.type === 'LineString') {
        if (
          turf.booleanPointInPolygon(turf.point(line.geometry.coordinates[0]), poly) ||
          turf.booleanPointInPolygon(
            turf.point(line.geometry.coordinates[line.geometry.coordinates.length - 1]),
            poly,
          )
        ) {
          // throw "起点和终点必须在多边形之外";
    
          return;
        }
      }
      // 2. 计算交点,并把线的点合并
      //计算相交点
      let lineIntersect = turf.lineIntersect(line, poly);
    
      //获取一个或一组Feature,并将所有位置作为点返回。拆分为点
      //将线拆分成点
      const lineExp = turf.explode(line);
    
      for (let i = 0; i < lineExp.features.length - 1; i++) {
        lineIntersect.features.push(turf.point(lineExp.features[i].geometry.coordinates));
      }
      // 3. 计算线的缓冲区
      const lineBuffer = turf.buffer(line, tolerance, {
        units: toleranceType,
      });
    
      // 4. 计算线缓冲和多边形的difference,返回"MultiPolygon",所以将其拆开
      //通过从第一个多边形剪裁第二个多边形来查找两个多边形之间的差异。
      const _body = turf.difference(poly, lineBuffer);
      
      let pieces = [];
      if (_body.geometry.type === 'Polygon') {
        pieces.push(turf.polygon(_body.geometry.coordinates));
      } else {
        _body.geometry.coordinates.forEach(function (a) {
          pieces.push(turf.polygon(a));
        });
      }
      // 5. 处理点数据
      for (let p = 0; p < pieces.length; p++) {
        const piece = pieces[p];
        for (let c = 0; c < piece.geometry.coordinates[0].length; c++) {
          const coord = piece.geometry.coordinates[0][c];
          const p = turf.point(coord);
          for (let lp = 0; lp < lineIntersect.features.length; lp++) {
            const lpoint = lineIntersect.features[lp];
            //判断两点距离
            if (turf.distance(lpoint, p, toleranceType) <= tolerance * 2) {
              piece.geometry.coordinates[0][c] = lpoint.geometry.coordinates;
            }
          }
        }
      }
      // 6. 过滤掉重复点
      // for (let p=0;p<pieces.length; p++) {
      //   const coords = pieces[p].geometry.coordinates[0];
      //   pieces[p].geometry.coordinates[0] = filterDuplicatePoints(coords);
      // }
      // 7. 将属性赋予每一个polygon,并处理id
      pieces.forEach((a, index) => {
        a.properties = Object.assign({}, poly.properties);
        a.properties.id += `-${index}`;
      });
    
      //获取一个或多个Feature并创建一个FeatureCollection。
      return turf.featureCollection(pieces);
    }