cesium+turf.js实现缓冲区分析

1.实现效果

可以在地图上绘制点,线,面,并且根据绘制的点线面绘制缓冲区。

 2.实现工具

1.用cesium的handle进行点线面绘制。

2.用turf.buffer函数对绘制的点线面进行缓冲区分析。

3.在地图上绘制缓冲区。

3.缓冲区工具类代码


import {
  buffer, point, lineString, polygon,
} from '@turf/turf';
import bus from '../../eventBus';

interface Position {
    lon: number;
    lat: number;
    alt: number;
  }

const { Cesium, }: any = window;

export default class Buffer {
    viewer: any;

    drawLayer:any;

    handler: any;

    radius = 1000;

    constructor (viewer: any | unknown, options = { basePath: '', }) {
      this.viewer = viewer;
      this.drawLayer = new Cesium.CustomDataSource('measureLayer');
      this.viewer.dataSources.add(this.drawLayer);
    }

    /**
     * 坐标转换 84转笛卡尔
     * @param {Position} position 位置
     * @param {number} alt 高度
     * @returns {any} 笛卡尔坐标
     */
    transformWGS84ToCartesian = (position: Position, alt = 0): any => (position ?
      Cesium.Cartesian3.fromDegrees(
        position.lon,
        position.lat,
        alt || position.alt,
        Cesium.Ellipsoid.WGS84
      ) :
      Cesium.Cartesian3.ZERO)

    /**
     * 坐标数组转换 笛卡尔转84
     * @param {Array} WSG84Arr {lon,lat,alt} 地理坐标数组
     * @param {Number} alt 拔高
     * @return {Array} Cartesian3 三维位置坐标数组
     */
    transformWGS84ArrayToCartesianArray (WSG84Arr: number[], alt: number): any[] {
      return WSG84Arr ?
        WSG84Arr.map((item: any) => this.transformWGS84ToCartesian(item, alt)) :
        [];
    }

    /**
     * 坐标转换 笛卡尔转84
     * @param {Object} cartesian 三维位置坐标
     * @return {Object} {lon,lat,alt} 地理坐标
     */
    transformCartesianToWGS84 = (cartesian: any | undefined): any => {
      const ellipsoid = Cesium.Ellipsoid.WGS84;
      const cartographic = ellipsoid.cartesianToCartographic(cartesian);

      return {
        lon: Cesium.Math.toDegrees(cartographic.longitude),
        lat: Cesium.Math.toDegrees(cartographic.latitude),
        alt: cartographic.height,
      };
    }

    /**
     * 坐标数组转换 笛卡尔转86
     * @param {Array} cartesianArr 三维位置坐标数组
     * @return {Array} {lon,lat,alt} 地理坐标数组
     */
    transformCartesianArrayToWGS84Array (cartesianArr: number[]): any {
      if (this.viewer) {
        return cartesianArr ?
          cartesianArr.map((item: any) => this.transformCartesianToWGS84(item)) :
          [];
      }
    }

    /**
     * 84坐标转弧度坐标
     * @param {Object} position wgs84
     * @return {Object} Cartographic 弧度坐标
     */
    transformWGS84ToCartographic = (position: Position): any => (position ?
      Cesium.Cartographic.fromDegrees(
        position.lon || position.lon,
        position.lat,
        position.alt
      ) :
      Cesium.Cartographic.ZERO)

    /**
     * 拾取位置点
     * @param {Object} px 屏幕坐标
     * @return {Object} Cartesian3 三维坐标
     */
    getCatesian3FromPX (px: any | undefined): any {
      if (this.viewer && px) {
        const picks = this.viewer.scene.drillPick(px);

        let cartesian = null;
        let isOn3dtiles = false;
        let isOnTerrain = false;
        // drillPick

        Object.keys(picks).forEach((i) => {
          const pick = picks[i];

          if (
            pick && (pick.primitive instanceof (Cesium.Cesium3DTileFeature || Cesium.Cesium3DTileset || Cesium.Model))
          ) {
            isOn3dtiles = true;
          }
          // 3dtilset
          if (isOn3dtiles) {
            this.viewer.scene.pick(px);
            cartesian = this.viewer.scene.pickPosition(px);
            if (cartesian) {
              const cartographic = Cesium.Cartographic.fromCartesian(cartesian);

              if (cartographic.height < 0) cartographic.height = 0;
              const lon = Cesium.Math.toDegrees(cartographic.longitude);
              const lat = Cesium.Math.toDegrees(cartographic.latitude);
              const { height, } = cartographic;

              cartesian = this.transformWGS84ToCartesian({ lon, lat, alt: height, });
            }
          }
        });

        // 地形
        const boolTerrain = this.viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider;
        // Terrain

        if (!isOn3dtiles && !boolTerrain) {
          const ray = this.viewer.scene.camera.getPickRay(px);

          if (!ray) return null;
          cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
          isOnTerrain = true;
        }
        // 地球
        if (!isOn3dtiles && !isOnTerrain && boolTerrain) {
          cartesian = this.viewer.scene.camera.pickEllipsoid(px, this.viewer.scene.globe.ellipsoid);
        }
        if (cartesian) {
          const position = this.transformCartesianToWGS84(cartesian);

          if (position.alt < 0) {
            cartesian = this.transformWGS84ToCartesian(position, 0.1);
          }

          return cartesian;
        }

        return false;
      }
    }

    pointBuffer ():any {
      if (this.viewer) {
        if (this.handler) {
          this.handler.destroy();
        }
        this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
        this.handler.setInputAction((movement: any) => {
          const cartesian = this.getCatesian3FromPX(movement.position);

          if (Cesium.defined(cartesian)) {
            const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
            const lon = Cesium.Math.toDegrees(cartographic.longitude);
            const lat = Cesium.Math.toDegrees(cartographic.latitude);
            const { height, } = cartographic;

            this.addPoint([lon,
              lat,
              height,]);
            this.initPointBuffer([lon,
              lat,
              height,],this.radius);
          }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.setInputAction((e: any) => {
          // 鼠标左键双击清除
          this.clear();
          bus.emit('bufferState');
        }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
      }
    }

    lineBuffer ():void {
      this.viewer.scene.globe.depthTestAgainstTerrain = true;
      if (this.viewer) {
        let positions: any[] = [];
        let linePoint: any[] = [];
        const lineEntity: any = new Cesium.Entity();

        if (this.handler) {
          this.handler.destroy();
        }
        this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

        this.handler.setInputAction((movement: any) => {
          const cartesian = this.getCatesian3FromPX(movement.position);

          if (cartesian) {
            const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
            const lon = Cesium.Math.toDegrees(cartographic.longitude);
            const lat = Cesium.Math.toDegrees(cartographic.latitude);
            const { height, } = cartographic;

            linePoint.push([lon,
              lat,
              height,]);
            if (positions.length === 0) {
              positions.push(cartesian.clone());
              linePoint.push([lon,
                lat,
                height,]);
            }
            // 添加量测信息点

            positions.push(cartesian);
          }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

        this.handler.setInputAction((movement: any) => {
          const cartesian = this.getCatesian3FromPX(movement.endPosition);

          if (cartesian && cartesian.x) {
            if (positions.length >= 2) {
              const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
              const lon = Cesium.Math.toDegrees(cartographic.longitude);
              const lat = Cesium.Math.toDegrees(cartographic.latitude);
              const { height, } = cartographic;

              linePoint.pop();
              linePoint.push([lon,
                lat,
                height,]);
              positions.pop();
              positions.push(cartesian);
            }
          }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        // right
        this.handler.setInputAction((movement: any) => {
          if (positions.length > 0) {
            this.initPolylineBuffer(linePoint, this.radius);
            this.addPolyline(positions);
            positions = [];
            linePoint = [];
          }
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

        this.handler.setInputAction((e: any) => {
          this.clear();
          bus.emit('bufferState');
        }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

        lineEntity.polyline = {
          width: 5,
          material: Cesium.Color.YELLOW.withAlpha(0.8),
          clampToGround: true,
        };
        lineEntity.polyline.positions = new Cesium.CallbackProperty(() => positions, false);

        this.drawLayer.entities.add(lineEntity);
      }
    }

    polyBuffer ():void {
      if (this.viewer) {
        this.viewer.scene.globe.depthTestAgainstTerrain = true;
        let positions: any = [];
        let polyPoint: any = [];
        const polygonHie = new Cesium.PolygonHierarchy();
        const polygonEntity: any = new Cesium.Entity();

        if (this.handler) {
          this.handler.destroy();
        }
        this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

        this.handler.setInputAction((movement: any) => {
          const cartesian = this.getCatesian3FromPX(movement.position);
          const cartographic = Cesium.Cartographic.fromCartesian(cartesian);

          if (cartesian) {
            const lon = Cesium.Math.toDegrees(cartographic.longitude);
            const lat = Cesium.Math.toDegrees(cartographic.latitude);
            const { height, } = cartographic;

            if (positions.length === 0) {
              polygonHie.positions.push(cartesian.clone());
              positions.push(cartesian.clone());
              polyPoint.push([lon,
                lat,
                height,]);
            }
            positions.push(cartesian.clone());
            polygonHie.positions.push(cartesian.clone());
            polyPoint.push([lon,
              lat,
              height,]);
          }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        // mouse_move
        this.handler.setInputAction((movement: any) => {
          const cartesian = this.getCatesian3FromPX(movement.endPosition);
          const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
          const lon = Cesium.Math.toDegrees(cartographic.longitude);
          const lat = Cesium.Math.toDegrees(cartographic.latitude);
          const { height, } = cartographic;

          if (positions.length >= 2) {
            if (cartesian) {
              positions.pop();
              positions.push(cartesian);
              polygonHie.positions.pop();
              polygonHie.positions.push(cartesian);
              polyPoint.pop();
              polyPoint.push([lon,
                lat,
                height,]);
            }
          }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        // left结束绘制
        this.handler.setInputAction((movement: any) => {
          if (positions.length > 2) {
            positions.push(positions[0]);
            polyPoint.push(polyPoint[0]);
            console.log(polyPoint);
            this.addPolygon(positions);
            this.initPolygonBuffer(polyPoint,this.radius);
            positions = [];
            polyPoint = [];
            polygonHie.positions = [];
          }
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
        this.handler.setInputAction((e: any) => {
          this.clear();
          bus.emit('bufferState');
        }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        polygonEntity.polyline = {
          width: 3,
          material: Cesium.Color.YELLOW.withAlpha(0.8),
          clampToGround: true,
        };

        polygonEntity.polyline.positions = new Cesium.CallbackProperty(() => positions, false);
        polygonEntity.polygon = {
          hierarchy: new Cesium.CallbackProperty(() => polygonHie, false),
          material: Cesium.Color.WHITE.withAlpha(0.1),
          clampToGround: true,
        };

        this.drawLayer.entities.add(polygonEntity);
      }
    }

    initPointBuffer (drawpoint:any, distance:number|undefined):void {
      const pointF = point(drawpoint);

      console.log(distance);
      const buffered = buffer(pointF, distance, { units: 'meters', });
      const { coordinates, } = buffered.geometry;
      const points = coordinates[0];
      const degreesArray = this.pointsToDegreesArray(points);

      this.addBufferPolyogn(Cesium.Cartesian3.fromDegreesArray(degreesArray));
    }

    // 初始化线缓冲
    initPolylineBuffer (bufferLine:any, distance:number|undefined) {
      let degreesArray = this.pointsToDegreesArray(bufferLine);

      const polylineF = lineString(bufferLine);
      const buffered = buffer(polylineF, distance, { units: 'meters', });
      const { coordinates, } = buffered.geometry;

      const points = coordinates[0];

      degreesArray = this.pointsToDegreesArray(points);
      this.addBufferPolyogn(Cesium.Cartesian3.fromDegreesArray(degreesArray));
    }

    // 初始化面缓冲
    initPolygonBuffer (bufferPolyogn:any, distance:number|undefined) {
      let degreesArray = this.pointsToDegreesArray(bufferPolyogn);

      const polygonF = polygon([bufferPolyogn,]);
      const buffered = buffer(polygonF, distance, { units: 'meters', });
      const { coordinates, } = buffered.geometry;

      const points = coordinates[0];

      degreesArray = this.pointsToDegreesArray(points);
      this.addBufferPolyogn(Cesium.Cartesian3.fromDegreesArray(degreesArray));
    }

    // 添加点
    addPoint (drawpoint:any):any {
      this.drawLayer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(drawpoint[0], drawpoint[1], drawpoint[2]),
        point: {
          pixelSize: 10,
          color: Cesium.Color.YELLOW,
          outlineWidth: 3,
          outlineColor: Cesium.Color.YELLOW.withAlpha(0.5),
          clampToGround: true,
        },
      });
    }

    // 添加线
    addPolyline (positions:any) :void {
      this.drawLayer.entities.add({
        polyline: {
          positions,
          width: 2,
          material: Cesium.Color.YELLOW,
          clampToGround: true,
        },
      });
    }

    // 添加缓冲面
    addBufferPolyogn (positions:any) {
      this.drawLayer.entities.add({
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy(positions),
          material: Cesium.Color.RED.withAlpha(0.7),
          classificationType: Cesium.ClassificationType.BOTH,
          clampToGround: true,
        },
      });
    }

    // 添加面
    addPolygon (positions:any) {
      this.drawLayer.entities.add({
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy(positions),
          material: Cesium.Color.WHITE.withAlpha(0.1),
          classificationType: Cesium.ClassificationType.BOTH,
          clampToGround: true,
        },
        polyline: {
          positions,
          width: 2,
          material: Cesium.Color.YELLOW.withAlpha(0.4),
          clampToGround: true,
        },
      });
    }

    // 坐标点格式转换
    pointsToDegreesArray (points:any):any {
      const degreesArray: any[] = [];

      points.map((item:any) => {
        degreesArray.push(item[0]);
        degreesArray.push(item[1]);
      });

      return degreesArray;
    }

    changeRadius (changeDis:number) :void {
      this.radius = changeDis;
    }
    // 地图绘制要素清除
    clear = (): void => {
      this.drawLayer.entities.removeAll();

      return this.handler && this.handler.destroy();
    }
}

4.工具类使用方法

import BufferImpl from './BufferImpl';


const bufferImpl = new BufferImpl(this.viewer);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Cesium是一个基于Web技术的地理信息可视化工具,其中包括了强大的绘图工具。Cesium TurfCesium中的一种工具,用于绘制地形等值线。 使用Cesium Turf绘制等值线,需要首先获取地形数据。可以使用刚才提到的另一个Cesium工具TinTerrain,以及其他在线资源(如USGS的高程数据)。获取到数据后,可以使用Cesium Turf提供的函数将数据导入。 接下来,使用Cesium的绘图工具将等值线绘制出来。绘制等值线时,首先需要确定等值线的间隔和范围,然后按照不同的高程值绘制出各个等值线。这里需要注意的是,在绘制等值线时,需要使用Cesium Turf提供的Adaptive Sobel算法,以便更好地处理较大的高度变化。 绘制完成后,可以使用Cesium提供的相关工具进行操作和调整。比如可以添加标签、调整颜色和透明度等等。 总之,使用Cesium Turf绘制等值线可以帮助我们更好地了解地形和地貌的变化,从而更好地理解自然地理背景下的人类活动和社会发展。 ### 回答2: Cesium turf是一个基于Cesium的三维地球可视化平台,可以在浏览器中展示地球的不同方面。等值线是用来展示连续变量分布的一种图像形式。在cesium turf中绘制等值线可以通过以下步骤实现: 1. 数据准备:要想绘制等值线,首先需要有一个数据集。数据集通常包含一个二维矩阵,每个单元格都有一个值。 2. 等值线绘制:等值线的绘制需要使用第三方库,比如d3-contour。该库可以将数据集转换为等值线的GeoJSON格式数据。这些数据可以直接添加到Cesium地图中。 3. 符号化处理:需要为等值线添加颜色和样式以使其更容易阅读,同时也需要给每个等值线添加标注,以标识其对应的值。 4. 动态效果:通过CSS动画或者Cesium的动画效果,可以为等值线添加一些动态效果,使其更加生动。 总的来说,在cesium turf中绘制等值线需要进行数据准备、等值线绘制、符号化处理以及添加动态效果等步骤。这些步骤的实现需要综合运用地理信息技术和数据可视化技术,从而实现更生动、更具信息量的地球可视化展示效果。 ### 回答3: Cesium Turf是一款地理信息Web应用程序,具有强大的可视化能力。它可以通过等值线(isoline)来展示地形高度数据。等值线是一种将地形高度信息通过线条展示出来的方法,通常可以用来表示山脉、高原等自然环境的高度。 Cesium Turf可以通过将地形高度数据通过Cesium Terrain Builder处理后添加到场景中进行展示,使用Terrain Contour插件可以将高度数据转换成等值线。用户可以在该插件中设置等值线的间隔距离、绘制颜色等参数,最终生成等值线图。 除了Terrain Contour插件,Cesium Turf还支持使用Turfs插件绘制等值线。Turfs是一款Cesium的插件,它支持使用多种算法(如Hachure, bevel, tint)绘制等值线,并可以通过调整等值线颜色、宽度等属性来实现更加美观和易读的效果。 综上所述,通过Cesium Turf的地形高度数据渲染功能,用户可以方便地绘制出自己所需的等值线图,并通过调整参数和算法来定制化自己的可视化方案,满足用户的需求和视觉效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值