大赵传奇

GIS解决方案,webgis , 桌面、数据、服务--QQ276605216

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

我的是Vue3 + vite + javascript ,了解到的信息是

1、jsts没有类型声明文件,npm引用时有问题。据说有方法:

我是在index.html中直接引用在线的

<script src="https://unpkg.com/jsts@1.6.1/dist/jsts.min.js"></script>

2、JSTS是一个符合OGC标准的,包含空间拓扑功能的JavaScript类库。

JSTS是通过原始JTS Java 源代码翻译来的,保留了JTSAPI;

3、可以直接适用OpenLayers(以下简称OL)的几何对象

4\数据代码里也有,来自这里zd4---.json:

{"type":"FeatureCollection", "features": [
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[40492442.5521,3588310.519099999],[40492442.5521,3588133.6675000004],[40493429.9736,3588133.6675000004],[40493429.9736,3588310.519099999],[40492442.5521,3588310.519099999]]]},"properties":{"BSM":0,"YSDM":"","DJZQDM":"","BDCDYH":"","YBZDDM":"","ZDDM":"","ZDTZM":"","DJH":"","ZT":"","BZ":"","YWH":"","SFYX":"","XMMC":"","XMBH":"","ID":"","CJR":"","CJRMC":"","CJSJ":"1899-11-30T00:00:00.000Z","ZHXGR":"","ZHXGRMC":"","ZHXGSJ":"1899-11-30T00:00:00.000Z","SFDYZ":"","SFDYZ3":"","QLRMC":"","ZL":"","TDYT":"","QLLX":"","QLXZ":"","FZMJ":0,"LSID":"","MJDW":0,"ZDMJ":0,"YT":"","JG":0,"CREATED_US":"","CREATED_DA":"1899-11-30T00:00:00.000Z","LAST_EDITE":"","LAST_EDI_1":"1899-11-30T00:00:00.000Z","LFY":0,"SFFZ":"","JZZDMJ":0,"SYNCFLAG":"","DELFLAG":0,"QXDM":"","JZXG":0,"SFMD":"","MDQK":"","Z":0,"SHAPE_AREA":174627.072149,"SHAPE_LEN":2328.5462}},
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[40492991.905961156,3588538.3426410276],[40493341.905961156,3587932.124858383],[40493441.905961156,3587932.124858383],[40493091.905961156,3588538.3426410276],[40492991.905961156,3588538.3426410276]]]},"properties":{"BSM":0,"YSDM":"","DJZQDM":"","BDCDYH":"","YBZDDM":"","ZDDM":"","ZDTZM":"","DJH":"","ZT":"","BZ":"","YWH":"","SFYX":"","XMMC":"","XMBH":"","ID":"","CJR":"","CJRMC":"","CJSJ":"1899-12-30T00:00:00.000Z","ZHXGR":"","ZHXGRMC":"","ZHXGSJ":"1899-12-30T00:00:00.000Z","SFDYZ":"","SFDYZ3":"","QLRMC":"","ZL":"","TDYT":"","QLLX":"","QLXZ":"","FZMJ":0,"LSID":"","MJDW":0,"ZDMJ":0,"YT":"","JG":0,"CREATED_US":"","CREATED_DA":"1899-12-30T00:00:00.000Z","LAST_EDITE":"","LAST_EDI_1":"1899-12-30T00:00:00.000Z","LFY":0,"SFFZ":"","JZZDMJ":0,"SYNCFLAG":"","DELFLAG":0,"QXDM":"","JZXG":0,"SFMD":"","MDQK":"","Z":0,"SHAPE_AREA":0,"SHAPE_LEN":0}},
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[40492647.99226973,3588253.3539021313],[40492647.99226973,3588203.353902133],[40492747.99226973,3588203.353902133],[40492747.99226973,3588253.3539021313],[40492647.99226973,3588253.3539021313]]]},"properties":{"BSM":22,"YSDM":"","DJZQDM":"","BDCDYH":"","YBZDDM":"","ZDDM":"","ZDTZM":"","DJH":"","ZT":"","BZ":"","YWH":"","SFYX":"","XMMC":"","XMBH":"","ID":"","CJR":"","CJRMC":"","CJSJ":"1899-12-30T00:00:00.000Z","ZHXGR":"","ZHXGRMC":"","ZHXGSJ":"1899-12-30T00:00:00.000Z","SFDYZ":"","SFDYZ3":"","QLRMC":"","ZL":"","TDYT":"","QLLX":"","QLXZ":"","FZMJ":0,"LSID":"","MJDW":0,"ZDMJ":0,"YT":"","JG":0,"CREATED_US":"","CREATED_DA":"1899-12-30T00:00:00.000Z","LAST_EDITE":"","LAST_EDI_1":"1899-12-30T00:00:00.000Z","LFY":0,"SFFZ":"","JZZDMJ":0,"SYNCFLAG":"","DELFLAG":0,"QXDM":"","JZXG":0,"SFMD":"","MDQK":"","Z":0,"SHAPE_AREA":0,"SHAPE_LEN":0}},
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[40492259.70328914,3588401.7665791605],[40492359.70328914,3588401.7665791605],[40492359.70328914,3588601.7665791586],[40492259.70328914,3588601.7665791586],[40492259.70328914,3588401.7665791605]]]},"properties":{"BSM":11,"YSDM":"","DJZQDM":"","BDCDYH":"","YBZDDM":"","ZDDM":"","ZDTZM":"","DJH":"","ZT":"","BZ":"","YWH":"","SFYX":"","XMMC":"","XMBH":"","ID":"","CJR":"","CJRMC":"","CJSJ":"1899-12-30T00:00:00.000Z","ZHXGR":"","ZHXGRMC":"","ZHXGSJ":"1899-12-30T00:00:00.000Z","SFDYZ":"","SFDYZ3":"","QLRMC":"","ZL":"","TDYT":"","QLLX":"","QLXZ":"","FZMJ":0,"LSID":"","MJDW":0,"ZDMJ":0,"YT":"","JG":0,"CREATED_US":"","CREATED_DA":"1899-12-30T00:00:00.000Z","LAST_EDITE":"","LAST_EDI_1":"1899-12-30T00:00:00.000Z","LFY":0,"SFFZ":"","JZZDMJ":0,"SYNCFLAG":"","DELFLAG":0,"QXDM":"","JZXG":0,"SFMD":"","MDQK":"","Z":0,"SHAPE_AREA":0,"SHAPE_LEN":0}}
]}

 

xxx.vue文件import 及 方法里:

  import {Polygon, LineString, LinearRing, MultiPoint, MultiLineString, MultiPolygon} from 'ol/geom';
  import Point from "ol/geom/Point";



  const originalPolygon = new Feature(
      new Polygon([[
        [40492442.5521, 3588310.519099999],
        [40492442.5521, 3588133.6675000004],
        [40493429.9736, 3588133.6675000004],
        [40493429.9736, 3588310.519099999],
        [40492442.5521, 3588310.519099999] // 闭合环
      ]])
  );
  //倾斜的面,与初始的面相交
  const polygonFea3 = new Feature(
      new Polygon([[
        [40492991.905961156,3588538.3426410276],
        [40493341.905961156,3587932.124858383],
        [40493441.905961156,3587932.124858383],
        [40493091.905961156,3588538.3426410276],
        [40492991.905961156,3588538.3426410276]
      ]])
  );
  //在originPolygon内部的,完全被包含的
  const polygonFea22 = new Feature(
      new Polygon([[[40492647.99226973,3588253.3539021313],
        [40492647.99226973,3588203.353902133],
        [40492747.99226973,3588203.353902133],
        [40492747.99226973,3588253.3539021313],
        [40492647.99226973,3588253.3539021313]]])
  );
  //分离不相交的
  const polygonFea11 = new Feature(
      new Polygon([[[40492259.70328914,3588401.7665791605],
        [40492359.70328914,3588401.7665791605],
        [40492359.70328914,3588601.7665791586],
        [40492259.70328914,3588601.7665791586],
        [40492259.70328914,3588401.7665791605]]])
  );
  // 分割线
  const line = new LineString([
    [40492655.54599426, 3588549.311891992],
    [40492986.11216243, 3587904.8227127804]
  ]);
  let lineFeature = new Feature({
    geometry: line,
    style: new Style({
      stroke: new Stroke({ color: 'red', width: 3 })
    })
  });






    //ol geometry:
    const originalPolygonGeo = originalPolygon.getGeometry();
    const polygonGeo3 = polygonFea3.getGeometry();
    const polygonGeo11 = polygonFea11.getGeometry();//分离的那个
    const polygonGeo22 = polygonFea22.getGeometry();//完全被包含的那个
    const splitLineGeo = lineFeature.getGeometry();




    //面缓冲
    // let ret = getBuffer(originalPolygonGeo, 20);
    // console.log('ret',ret)
    // let fea1 = new Feature(ret)
    // fea1.setStyle(new Style({
    //           fill: new Fill({ color: 'rgba(2,31,194,1)' }),
    //           stroke: new Stroke({ color: 'green', width: 2 })
    //         }));
    // source.addFeature(fea1)
    //source.addFeature(new Feature(ret))  //test ok

    //线缓冲
    // let ret = getBuffer(splitLineGeo, 20);
    // console.log('ret',ret)
    // source.addFeature(new Feature(ret))  //test ok


    // let lineBuf = getBuffer(splitLineGeo, 20);
    // let ret = intersects(originalPolygonGeo, lineBuf);
    // console.log('ret',ret)
    // let fea1 = new Feature(ret)
    // fea1.setStyle(new Style({
    //           fill: new Fill({ color: 'rgba(2,31,194,1)' }),
    //           stroke: new Stroke({ color: 'green', width: 2 })
    //         }));
    // source.addFeature(fea1)  //test ok


    //线缓冲之后,再与 polygon1 Diff, 即是挖空相交的部分。然后再multipolygon 是哪几个,打算再分解出来,判断哪个是切剩下的polygon
    // let lineBuf = getBuffer(splitLineGeo, 20);
    // console.log('line-wkt,', geometryToWKT(lineBuf))
    // let ret = symDifference(originalPolygonGeo, lineBuf);
    // console.log('ret',ret,ret.getCoordinates()[1][0])  //结果为multiPolygon,这里输出第一个polygon的环
    // source.addFeature(fea1)  //test ok

    //从 ret.getCoordinates()[1][0] 坐标,手动在arcmap中添加xy 点中以判断出来是 倾斜的面上裁剪剩余的。
    // let ret = symDifference(originalPolygonGeo, polygonGeo3);
    // console.log('ret',ret,ret.getCoordinates()[1][0])  //结果为multiPolygon,这里输出第一个polygon的环
    // let fea1 = new Feature(ret)
    // fea1.setStyle(new Style({
    //   fill: new Fill({ color: 'rgba(2,31,194,1)' }),
    //   stroke: new Stroke({ color: 'green', width: 2 })
    // }));
    // source.addFeature(fea1)  //test ok

    //初始面与 11相交吗 ?
    // let retGeo = intersects(originalPolygonGeo, polygonGeo11);
    // console.log('ret',retGeo, isGeometryEmpty(retGeo))  //结果要判断,可能是POLYGON,也可能是multiPolygon,按前面数据,这里ret.getCoordinates()[0].length == 0
    // let fea1 = new Feature(retGeo)
    // fea1.setStyle(new Style({
    //   fill: new Fill({ color: 'rgba(2,31,194,1)' }),
    //   stroke: new Stroke({ color: 'green', width: 2 })
    // }));
    // source.addFeature(fea1)  //test ok

    //初始面与 22相交吗 ?
    let retGeo = intersects(originalPolygonGeo, polygonGeo22);
    if(!isGeometryEmpty(retGeo)){
      console.log('ret 有图形')  //结果要判断,可能是POLYGON,也可能是multiPolygon,按前面数据,这里ret.getCoordinates()[0].length == 0
      let fea1 = new Feature(retGeo)
      fea1.setStyle(new Style({
        fill: new Fill({ color: 'rgba(2,31,194,1)' }),
        stroke: new Stroke({ color: 'green', width: 2 })
      }));
      source.addFeature(fea1)  //test ok
    }
// 实例化OL解析类
const OLParser = new jsts.io.OL3Parser();
// 注入OL几何对象
OLParser.inject(Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon);

函数:

  const getBuffer = (geom, len) => {
    const jstsGeom = OLParser.read(geom);
    if (!jstsGeom.isValid()) {
      console.error("几何对象出现拓扑错误,请检查修复");
      return null;
    }

    const buffered = jstsGeom.buffer(len);
    return OLParser.write(buffered);
  };



  /**
   * import Polygon from 'ol/geom/Polygon';
   * import LineString from 'ol/geom/LineString';
   * OL 中检查几何坐标是否为空
   * @param {ol/geom/Geometry} geometry - OpenLayers几何对象
   * @returns {boolean} 是否为空
   */
  function isGeometryEmpty(geometry) {
    if (!geometry) return true;

    const coords = geometry.getCoordinates();

    switch (geometry.getType()) {
      case 'Point':
        return coords.length === 0 || coords.some(isNaN);

      case 'LineString':
        return coords.length === 0;

      case 'Polygon':
        // 多边形需检查外环是否为空
        return coords.length === 0 || coords[0].length === 0;

      case 'MultiPolygon':
        // 检查所有子多边形
        return coords.length === 0 || coords[0][0].length === 0;

      default:
        return coords.length === 0;
    }
  }
  /**
   * 取交
   * @param geom
   * @param geomB
   * @returns
   */
  const intersects = (geom, geomB) => {
    const jstsGeom = OLParser.read(geom);
    const jstsGeomB = OLParser.read(geomB);

    if (!jstsGeom.isValid() || !jstsGeomB.isValid()) {
      console.error("几何对象出现拓扑错误,请检查修复");
      return null;
    }

    const difference = jstsGeom.intersection(jstsGeomB);
    return OLParser.write(difference);
  };

  /**
   * 取geom中geomB的补集
   * @param geom
   * @param geomB
   * @returns
   */
  const getDifference = (geom, geomB) => {
    const jstsGeom = OLParser.read(geom);
    const jstsGeomB = OLParser.read(geomB);

    if (!jstsGeom.isValid() || !jstsGeomB.isValid()) {
      console.error("几何对象出现拓扑错误,请检查修复");
      return null;
    }

    const difference = jstsGeom.difference(jstsGeomB);
    return OLParser.write(difference);
  };
  /**
   * 融合
   * @param geom
   * @param geomB
   * @returns
   */
  const union = (geom, geomB) => {
    const jstsGeom = OLParser.read(geom);
    const jstsGeomB = OLParser.read(geomB);

    if (!jstsGeom.isValid() || !jstsGeomB.isValid()) {
      console.error("几何对象出现拓扑错误,请检查修复");
      return null;
    }
    const difference = jstsGeom.union(jstsGeomB);
    return OLParser.write(difference);
  };
  /**
   * 对等差分
   * @param geom
   * @param geomB
   * @returns
   */
  const symDifference = (geom, geomB) => {
    const jstsGeom = OLParser.read(geom);
    const jstsGeomB = OLParser.read(geomB);

    if (!jstsGeom.isValid() || !jstsGeomB.isValid()) {
      console.error("几何对象出现拓扑错误,请检查修复");
      return null;
    }

    const difference = jstsGeom.symDifference(jstsGeomB);
    return OLParser.write(difference);
  };

  /**
   * 手动转wkt 格式
   * 将OpenLayers几何对象转换为WKT格式
   * @param {ol/geom/Geometry} geom - OpenLayers几何对象
   * @returns {string} WKT字符串
   */
  function geometryToWKT(geom) {
    const type = geom.getType();

    switch (type) {
      case 'Point':
        return `POINT(${coordToWKT(geom.getCoordinates())})`;

      case 'LineString':
        return `LINESTRING(${geom.getCoordinates().map(coordToWKT).join(', ')})`;

      case 'Polygon':
        const rings = geom.getCoordinates();
        // 外环 + 内环(孔洞)
        return `POLYGON(${rings.map(ring => `(${ring.map(coordToWKT).join(', ')})`).join(', ')})`;

      case 'MultiPolygon':
        return `MULTIPOLYGON(${geom.getCoordinates().map(poly =>
            `(${poly.map(ring => `(${ring.map(coordToWKT).join(', ')})`).join(', ')})`
        ).join(', ')})`;

      default:
        throw new Error(`未支持的几何类型: ${type}`);
    }
  }

  // 辅助函数:坐标数组转WKT格式
  function coordToWKT(coord) {
    return coord.join(' ');
  }

学习自这里 

JSTS介绍和功能简单示例-CSDN博客

https_://blog.csdn.net/Neuromancerr/article/details/123345148

posted on 2025-04-02 16:25  赵长青  阅读(107)  评论(0)    收藏  举报