cesium绘制区域编辑

npm 安装也是可以的 

#默认安装最新的
yarn add cesium
 
#卸载插件
yarn remove cesium
 
#安装指定版本的
yarn add cesium@1.96.0
 
#安装指定版本到测试环境
yarn add cesium@1.96.0 -D
yarn install @turf/turf

<template>
  <div id="cesiumContainer"></div>
  <div class="but" >
    <div  :class="tableDataObj.drawList.length===0?'zoomIn animated_three':'wobble animated_eight'" @click="drawPlane">开始绘制</div>
    <div  :class="tableDataObj.drawList.length===0?'fadeOut animated_two':'fadeInDown animated'"  @click="echoEditing">回显编辑</div>
    <div  :class="tableDataObj.drawList.length===0?'fadeOutDownBig animated_six':'fadeInUpBig animated_four'"  @click="clean">清除</div>
    <div  :class="tableDataObj.drawList.length===0?'rotateOut animated_seven':'rotateIn animated_five'"  @click="thoroughClean">彻底清除</div>
     
  </div>
</template>
  <!-- 绘制面并且编辑 -->
  <script setup lang="ts">
import * as Cesium from "cesium";
import { onMounted, reactive, ref } from "vue";
import * as turf from "@turf/turf";

 
 
 

// 地图实例
let viewer: any;
// 存点数组,里面对象是这个{
//       lon: '',
//       lat: '',
//       hei: '',
//     };
const points: any = ref([]);
// 区域面积
const area = ref(0);
// 实体
let handler: any = null;
// 是否点击
let mouseClick = false;
// 是否移动
let mouseMove = false;
// 取消绘制
let startPicking = ref(false);
let deleteState=ref(false)
interface PositionsList {
  x: number;
  y: number;
  z: number;
}
// 存储绘制点
let  tableDataObj   = reactive({
  drawList:[]
});
onMounted(() => {
  // 初始化Cesium并创建viewer
  Cesium.Ion.defaultAccessToken =
    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmMGU1MDc1Yy0zZTMyLTQ0ODEtYjcxYi0yYjAyNDgyZGY1MjQiLCJpZCI6MjAxMDQ3LCJpYXQiOjE3MTAxNjM4NjF9.b9qwNlQbvo49RJTHEMpjIiOS-mOvf9MF8ZHSYTdf6CI";
  viewer = new Cesium.Viewer("cesiumContainer", {
    infoBox: false, // 禁用沙箱,解决控制台报错
    selectionIndicator: false, //选择指示器
    timeline: false, // 时间轴
    animation: false, // 动画小组件
    geocoder: false, // 地理编码(搜索)组件
    homeButton: false, // 首页,点击之后将视图跳转到默认视角
    sceneModePicker: false, // 投影方式,切换2D、3D 和 Columbus View (CV) 模式。
    baseLayerPicker: false, // 底图组件,选择三维数字地球的底图(imagery and terrain)。
    navigationHelpButton: false, // 帮助按钮
    fullscreenButton: false, // 全屏按钮

    // vrButton: false, // VR模式
    // shouldAnimate: true, // 自动播放动画控件
    // shadows: true, // 是否显示光照投射的阴影
    // terrainShadows: Cesium.ShadowMode.RECEIVE_ONLY, // 地质接收阴影`

    // imageryProvider: esri, //自定义图层,默认是谷歌的影响图层
    scene3DOnly: true, // 每个几何实例将只能以3D渲染以节省GPU内存
    sceneMode: 3, // 初始场景模式 1 2D模式 2 2D循环模式 3 3D模式  Cesium.SceneMode
  });
  viewer._cesiumWidget._creditContainer.style.display = "none"; //隐藏logo版权
  let destination = Cesium.Cartesian3.fromDegrees(116.3974, 39.9087, 10000); // 北京天安门广场的经纬度坐标及高度
  pointerdefault();
  viewer.camera.flyTo({
    destination: destination,
    duration: 2, // 飞行动画持续时间(单位:秒)
  });
});

//开始绘制
const drawPlane = () => {
  console.log(handler, "handler");

  if (handler != null) {
    clean();
  }

  points.value = [];
  startPicking.value = false;
  // 点位存储
  let positions: any = [];
  area.value = 0;
  let polygon = new Cesium.PolygonHierarchy();
  let dynamicPolygon: any = new Cesium.Entity();
  let polyObj: any = null;
  let polyId = "planBy" + buildUUID();

  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

  handler.setInputAction(
    (movement: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {
      let pick: any = pickEllisoidPosition(viewer, movement.position);
      mouseClick = true;
      if (
        Cesium.defined(pick) &&
        Cesium.defined(pick.cartesian) &&
        pick.cartesian.x
      ) {
        positions.push(pick.cartesian.clone());
        polygon.positions.push(pick.cartesian.clone());
        if (!polyObj) {
          dynamicPolygon = {
            id: polyId,
            polyline: {
              width: 7,
              // ...lineStyle,
              material: new Cesium.PolylineOutlineMaterialProperty({
                color: Cesium.Color.AQUA.withAlpha(0.7), // 线的颜色
                outlineWidth: 4,
                outlineColor: Cesium.Color.WHITE.withAlpha(0.6),
              }),
              show: true,
              clampToGround: true,
              positions: new Cesium.CallbackProperty(function () {
                return positions;
              }, false),
            },
            polygon: {
              hierarchy: new Cesium.CallbackProperty(function () {
                return polygon;
              }, false),
              // 绘制区域颜色
              material: Cesium.Color.STEELBLUE.withAlpha(0.4),
              clampToGround: true,
            },
          };
          polyObj = viewer.entities.add(dynamicPolygon);
        }
        let ray = viewer.camera.getPickRay(movement.position);
        let cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
        let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
        viewer.entities.add({
          id: "editPoint" + buildUUID(),
          name: "点",
          point: {
            pixelSize: 15,
            color: Cesium.Color.WHITE,
            // ...lineStyle,
            show: true,
            clampToGround: true,
            // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
          },
          distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
            0,
            3000
          ), // 可视范围
          position: Cesium.Cartesian3.fromDegrees(lng, lat, 0),
        });
      }
    },
    Cesium.ScreenSpaceEventType.LEFT_CLICK
  );

  handler.setInputAction(
    (movement: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {
      if (mouseClick) {
        let pick: any = pickEllisoidPosition(viewer, movement?.endPosition);
        if (positions.length >= 0 && Cesium.defined(pick)) {
          if (mouseMove) {
            positions.pop();
            polygon.positions.pop();
          }
          if (pick.cartesian && pick.cartesian.x) {
            positions.push(pick.cartesian);
            polygon.positions.push(pick.cartesian);
            mouseMove = true;
          }
        }
      }
    },
    Cesium.ScreenSpaceEventType.MOUSE_MOVE
  );
  handler.setInputAction((movement) => {
    if (mouseClick && mouseMove) {
      positions.pop();
      polygon.positions.pop();
    }
    if (positions.length < 3) {
      alert("必须绘制三个点以上,请重新绘制");
      // 再次开启
      drawPlane();
      return;
    }
   
    // 计算面积
    getCalculateArea(positions);
    positions.push(positions[0]);
    mouseMove = false;
    mouseClick = false;
    points.value = [];

    for (let i = 0; i < positions.length; i++) {
      const tmp = cartesian3ToGps(viewer, positions[i]);
      const tmpPoint: object = {
        lon: tmp[0],
        lat: tmp[1],
        hei: tmp[2],
      };
      points.value.push(tmpPoint);
    }

    const arr = points.value.map((item) => [item.lon, item.lat]);
    area.value = turf.area(turf.polygon([arr])).toFixed(2) as any;

    // let pick =  viewer.scene.pick(movement.position);
    // console.log("右键:",pick.id.id)
    pickClear(polyObj);
    // 停止绘制
    stopDraw();

    handlePolyClick();
    // 右键删除
    handlePolyRightClick();
  }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
};

// 计算面积
function getCalculateArea(positions: PositionsList) {
  tableDataObj.drawList = positions as any;
   console.log("cesium坐标:",tableDataObj.drawList.length)
  var areaCenter = getAreaAndCenter(positions);
  var calculatearea = areaCenter.area;
  var center = areaCenter.center;
  var text = formateArea(calculatearea, "m");
  // console.log("calculatearea面积:",calculatearea)
  // console.log("text面积",text)
  let labelId = viewer.entities.add({
    id: "label_" + buildUUID(),
    position: center,
    label: {
      text: "面积:" + text,
      // 字体大小
      font: "18px sans-serif",
      // FILL填充/OUTLINE描边/FILL_AND_OUTLINED填充描边
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      // 描边颜色
      outlineColor: Cesium.Color.WHITE,
      // 描边宽度
      outlineWidth: 5,
      // 字体颜色
      fillColor: Cesium.Color.BLUE,
    },
  });
}

// 添加小手
function pointerdefault() {
  // 添加小手
  viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
    const pickedObject = viewer.scene.pick(movement.endPosition);
    if (pickedObject && pickedObject.id) {
      viewer.container.style.cursor = "pointer";
    } else {
      viewer.container.style.cursor = "default";
    }
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}

// 创建完面之后监听事件
const handlePolyClick = () => {
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
  let pickData: any;
  handler.setInputAction((event: any) => {
    let windowPosition = event.position;
    // 通过屏幕坐标获取当前位置的实体信息
    let pickedObject = viewer.scene.pick(windowPosition);
    if (Cesium.defined(pickedObject)) {
      if (/planBy/.test(pickedObject.id._id)) {
        if (pickData && pickData._id == pickedObject._id) {
          return;
        }
        pickData = pickedObject.id; //获取编辑的事件
        editPlane(pickData, handler);
      }
    } else {
      if (!pickData) {
        return;
      }
      pickClear(pickData);
      pickData = undefined;
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
};
// 右键删除
const handlePolyRightClick = () => {
  console.log("触发了么");
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

  handler.setInputAction((event: any) => {
    let windowPosition = event.position;
    // 通过屏幕坐标获取当前位置的实体信息
    let pickedObject = viewer.scene.pick(windowPosition);
    let pick = viewer.scene.pick(event.position);
    // 通过屏幕坐标获取当前位置的实体信息
    let pickData: any;
    if (Cesium.defined(pickedObject)) {
      pickData = pickedObject.id; //获取编辑的事件

      pickClear(pickData);
      pickData = undefined;
      
      if(!deleteState.value){
        //右键删除
        createDelteDom(event.position, pick.id.id);
      }else{
         return
      }
    
    }  
  }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
};

// 删除
function createDelteDom(px, objId) {
  deleteState.value=true
   if (!objId) return;
  let deleteDom = window.document.createElement("span");
  deleteDom.style.background = "red";
  deleteDom.style.position = "absolute";
  deleteDom.style.color = "white";
  deleteDom.style.left = px.x + 10 + "px";
  deleteDom.style.top = px.y + 10 + "px";
  deleteDom.style.padding = "6px";
  deleteDom.style.borderRadius = "6px";
  deleteDom.style.cursor = "pointer";
  deleteDom.id = "easy3d-plot-delete";
  deleteDom.setAttribute("objId", objId);
  deleteDom.innerHTML = `删除`;
  let mapDom = window.document.getElementById(viewer.container.id);
  mapDom.appendChild(deleteDom);

  const clsBtn = window.document.getElementById("easy3d-plot-delete");
  if (!clsBtn) return;

  clsBtn.addEventListener("click", (e) => {
    let id = deleteDom.getAttribute("objId");
    removeByObjId(id);
  });
  document.addEventListener("click", function () {
    clsBtn.remove();
    deleteState.value=false
  });
}
/**
 * 根据id移除创建的对象
 * @param {String | Number} id 对象id
 */
function removeByObjId(id) {
  console.log("查看写ID", id);
  if (!id) return;
  let entity = viewer.entities.getById(id);
  if (entity) {
    viewer.entities.remove(entity);
  }

  // 删除面积label
  let label_id = viewer.entities.values[0].id;
  var reg = new RegExp("label_");
  if (reg.test(label_id)) {
    viewer.entities.removeById(label_id);
  }
}

// 创建完面之后编辑事件
const editPlane = (pick: any, handler: any) => {
  if (!pick) {
    return;
  }
  // const view = viewer.entities.getById(polyId)
  pick.polyline.width = 7;
  pick.polyline.material.outlineWidth = 4;
  pick.polyline.material.outlineColor = Cesium.Color.WHITE.withAlpha(0.6);
  removeEntities(viewer, {
    filterType: "id",
    filterReg: /(editPoint)|labelPoy_/,
  });
  let pointId: any = [];
  let downStatus = false;
  let currentPoint: any; //当前编辑点
  console.log(pick.polygon.hierarchy.getValue(), "pick.polygon.hierarchy");
  let positions = pick.polygon.hierarchy.getValue(
    Cesium.JulianDate.now()
  ).positions;
  // 生成编辑点
  for (let i = 0; i < positions.length; i++) {
    let ID = "editPoint" + buildUUID();

    let point = viewer.entities.add({
      id: ID,
      position: positions[i],
      vertexIndex: i,
      point: {
        pixelSize: 15,
        color: Cesium.Color.WHITE,
        // ...lineStyle,
        show: true,
        clampToGround: true,
        // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
      },
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 3000), // 可视范围
    });
    // 保存点的ID以便删除
    pointId.push(ID);
  }
  const resp = positions.map((item) => {
    let cartographic = Cesium.Cartographic.fromCartesian(item);
    let longitude = Cesium.Math.toDegrees(cartographic.longitude);
    let latitude = Cesium.Math.toDegrees(cartographic.latitude);
    return {
      longitude: longitude,
      latitude: latitude,
      height: cartographic.height,
    };
  });
  resp.push(resp[0]);
  resp.forEach((item, index) => {
    if (resp[index + 1]?.longitude) {
      let longitude = (+item.longitude + +resp[index + 1].longitude) / 2;
      let latitude = (+item.latitude + +resp[index + 1].latitude) / 2;
      let height = (+item.height + +resp[index + 1].height) / 2;
      let position = [+longitude, +latitude, +height];
      let text = distanceApi(item, resp[index + 1]).toFixed(1) + "m";
      labelApis(`labelPoy_${buildUUID()}`, position, text);
    }
  });
  handler.setInputAction((event) => {
    // 获取屏幕坐标
    let windowPosition = event.position;
    // 通过屏幕坐标获取当前位置的实体信息
    let pickedObject = viewer.scene.pick(windowPosition);
    if (Cesium.defined(pickedObject)) {
      if (/editPoint/.test(pickedObject.id._id)) {
        downStatus = true;
        viewer.scene.screenSpaceCameraController.enableRotate = false;
        viewer.scene.screenSpaceCameraController.enableZoom = false;
        currentPoint = pickedObject.id;
        console.log(currentPoint);
      } else {
        viewer.scene.screenSpaceCameraController.enableRotate = true;
        viewer.scene.screenSpaceCameraController.enableZoom = true;
        return false;
      }
    } else {
      viewer.scene.screenSpaceCameraController.enableRotate = true;
      viewer.scene.screenSpaceCameraController.enableZoom = true;
      return false;
    }
  }, Cesium.ScreenSpaceEventType.LEFT_DOWN);
  handler.setInputAction((event) => {
    if (!downStatus) {
      return;
    }
    removeEntities(viewer, {
      filterType: "id",
      filterReg: /labelPoy_|label_/,
    });
    let windowPosition = event.startPosition;
    // 将屏幕坐标转为笛卡尔坐标
    let ellipsoid = viewer.scene.globe.ellipsoid;
    let cartesian = viewer.camera.pickEllipsoid(windowPosition, ellipsoid);
    // 如果点击到地球外,那么返回
    if (!cartesian) {
      return;
    }
    // 更新编辑点的位置
    // console.log(currentPoint, cartesian);
    currentPoint.position._value = cartesian;
    let point: any = []; // 线的定位
    let polyData: any = [];
    for (let id of pointId) {
      // console.log(viewer.entities.getById(id), "0");
      point.push(viewer.entities.getById(id).position._value);
      polyData.push(viewer.entities.getById(id).position._value);
    }
    // const data = viewer.entities.getById(polyId)
    positions = point;

    point.push({ x: point[0]["x"], y: point[0]["y"], z: point[0]["z"] });

    const resp = point.map((item) => {
      let cartographic = Cesium.Cartographic.fromCartesian(item);
      let longitude = Cesium.Math.toDegrees(cartographic.longitude);
      let latitude = Cesium.Math.toDegrees(cartographic.latitude);
      return {
        lon: longitude,
        lat: latitude,
        height: cartographic.height,
      };
    });

    points.value = resp;
    const resps = points.value.map((item) => {
      return {
        longitude: item.lon,
        latitude: item.lat,
        height: item.height,
      };
    });
    // resp.push(resp[0])
    resps.forEach((item, index) => {
      if (resps[index + 1]?.longitude) {
        let longitude = (+item.longitude + +resps[index + 1].longitude) / 2;
        let latitude = (+item.latitude + +resps[index + 1].latitude) / 2;
        let height = (+item.height + +resps[index + 1].height) / 2;
        let position = [+longitude, +latitude, +height];
        let text = distanceApi(item, resps[index + 1]).toFixed(1) + "m";
        labelApis(`labelPoy_${buildUUID()}`, position, text);
      }
    });
    pick.polyline.positions = point;
    pick.polygon.hierarchy = polyData;
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  handler.setInputAction(() => {
    if (!downStatus) {
      return;
    }
    // removeEntities(viewer, {
    //   filterType: "id",
    //   filterReg: /label_/,
    // });
    console.log(points.value, "value");
    console.log("positions", positions);
    // 重新计算面积
    getCalculateArea(positions);

    viewer.scene.screenSpaceCameraController.enableRotate = true;
    viewer.scene.screenSpaceCameraController.enableZoom = true;
    downStatus = false;
    currentPoint = undefined;
  }, Cesium.ScreenSpaceEventType.LEFT_UP);
  // }
};
const pickClear = (pickData: any) => {
  pickData.polyline.width = 5;
  pickData.polyline.material.outlineWidth = 2;
  pickData.polyline.material.outlineColor = Cesium.Color.WHITE.withAlpha(0.4);
  removeEntities(viewer, {
    filterType: "id",
    filterReg: /(editPoint)|labelPoy_/,
  });
};
//结束绘制
const stopDraw = () => {
  if (handler) {
    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN);
    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP);
    handler?.destroy();
    startPicking.value = true;
    handler = null;
  }
};
// 随机数字
const buildUUID = () => {
  const hexList: string[] = [];
  for (let i = 0; i <= 15; i++) {
    hexList[i] = i.toString(16);
  }
  let uuid = "";
  for (let i = 1; i <= 36; i++) {
    if (i === 9 || i === 14 || i === 19 || i === 24) {
      uuid += "-";
    } else if (i === 15) {
      uuid += 4;
    } else if (i === 20) {
      uuid += hexList[(Math.random() * 4) | 8];
    } else {
      uuid += hexList[(Math.random() * 16) | 0];
    }
  }
  return uuid.replace(/-/g, "");
};
/**
 * @description: cesium获取两点之间距离 (m)
 * @param {*} root 当前组件的根实例
 * @param {*} point1 坐标1
 * @param {*} point2  坐标2
 * @return {*} 距离
 */
const distanceApi = (position1: any, position2: any) => {
  let cartesian1 = Cesium.Cartesian3.fromDegrees(
    position1.longitude,
    position1.latitude,
    position1.height
  );
  let cartesian2 = Cesium.Cartesian3.fromDegrees(
    position2.longitude,
    position2.latitude,
    position2.height
  );

  var point1cartographic = Cesium.Cartographic.fromCartesian(cartesian1);
  var point2cartographic = Cesium.Cartographic.fromCartesian(cartesian2);

  /**根据经纬度计算出距离**/
  var geodesic = new Cesium.EllipsoidGeodesic();
  geodesic.setEndPoints(point1cartographic, point2cartographic);
  var distance = geodesic.surfaceDistance;
  //返回两点之间的距离
  return (distance = Math.sqrt(
    Math.pow(distance, 2) +
      Math.pow(point2cartographic.height - point1cartographic.height, 2)
  ));
};
/**
 * 删除地图上的实体
 * @param viewer
 * @param option
 */
const removeEntities = (viewer: Cesium.Viewer, option: any) => {
  if (!viewer) {
    return;
  }
  const removedId: string[] = [];
  viewer.entities.values.map((item) => {
    if (option.filterType == "id") {
      if (option.filterReg.test(item.id)) {
        removedId.push(item.id);
      }
    }
  });
  removedId.sort(function (a, b) {
    return b.indexOf("measureLineXL") !== -1 ? 1 : -1;
  });
  removedId.map(function (item) {
    viewer.entities.removeById(item);
  });
};
/**
 * cartesian3转gps
 * @param viewer
 * @param cartesian
 * @returns
 */
const cartesian3ToGps = (
  viewer: Cesium.Viewer,
  cartesian: Cesium.Cartesian3
): number[] => {
  const cartographic =
    viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
  return [
    Cesium.Math.toDegrees(cartographic.longitude),
    Cesium.Math.toDegrees(cartographic.latitude),
    cartographic.height,
  ];
};
/**
 * 拾取球面坐标
 * @param viewer  场景视图
 * @param position 屏幕坐标
 * @returns array 地理坐标数组
 */
const pickEllisoidPosition = (
  viewer: Cesium.Viewer,
  position: Cesium.Cartesian2
) => {
  const pickRay = viewer.scene.camera.getPickRay(position);
  if (pickRay) {
    const cartesian = viewer.scene.globe.pick(pickRay, viewer.scene);
    if (cartesian) {
      const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      const result = {
        geoPositon: [
          Cesium.Math.toDegrees(cartographic.longitude),
          Cesium.Math.toDegrees(cartographic.latitude),
          cartographic.height,
        ],
        cartesian: cartesian,
      };
      return result;
    }
  }
};

const labelApis = (id, position, text) => {
  viewer.entities.add({
    id: id,
    name: "labelApi",
    position: Cesium.Cartesian3.fromDegrees(...position),
    label: {
      text: text,
      showBackground: true, //显示背景
      backgroundColor: new Cesium.Color.fromCssColorString("rgba(0,0,0,0.7)"),
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER, //对齐方式
      font: "16px sans-serif",
      fillColor: Cesium.Color.MIDNIGHTBLUE,
      outlineColor: Cesium.Color.WHITE,
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      outlineWidth: 4,
      pixelOffset: new Cesium.Cartesian2(0, -10), // 视角偏移
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 400000), // 可视范围
      eyeOffset: new Cesium.Cartesian3(0, 0, -30),
    },
  });
};

const clean = () => {
  removeEntities(viewer, {
    filterType: "id",
    filterReg: /(editPoint)|planBy|labelPoy_|label_/,
  });
  // 停止绘制

  stopDraw();

  // console.log(handler, "handler");
};
// 彻底清除
function thoroughClean(){
  tableDataObj.drawList=[]
  clean()
}
const echoEditing = () => {
  let square=ref()
console.log("square",square)
  clean();
  let polyObj: any = null;
  let polyId = "planBy" + buildUUID();
  // 点位存储

  let polygon = new Cesium.PolygonHierarchy();
  let dynamicPolygon: any = new Cesium.Entity();
  let pointData: any = [];
  pointData = tableDataObj.drawList;
  let points: any = [];
// console.log("drawList",tableDataObj.drawList)
// console.log("pointData",pointData)
if(pointData.length==0){
  alert("没有点位数据,无法回显!!!")
  return
}
  for (let i = 0; i < pointData.length; i++) {
    const tmp = cartesian3ToGps(viewer, pointData[i]);
    points.push(tmp[0], tmp[1], tmp[2]);
  }
  // console.log(points, "lll");

  if (!polyObj) {
    dynamicPolygon = {
      id: polyId,
      polyline: {
        width: 7,
        // ...lineStyle,
        material: new Cesium.PolylineOutlineMaterialProperty({
          color: Cesium.Color.AQUA.withAlpha(0.7), // 线的颜色
          outlineWidth: 4,
          outlineColor: Cesium.Color.WHITE.withAlpha(0.6),
        }),
        show: true,
        clampToGround: true,
        positions: Cesium.Cartesian3.fromDegreesArrayHeights(points),
      },
      polygon: {
        hierarchy: Cesium.Cartesian3.fromDegreesArrayHeights(points),
        material: Cesium.Color.STEELBLUE.withAlpha(0.4),
        clampToGround: true,
      },
    };
    polyObj = viewer.entities.add(dynamicPolygon);
    handlePolyClick();
    // 计算面积
    getCalculateArea(pointData);
    // 右键删除
    handlePolyRightClick();
  }
};

//调用第三方插件计算面积 turf
function getAreaAndCenter(positions: any) {
  if (!positions || positions.length < 1) return;
  var cartographics = [];
  var turfPoints = [];
  for (var i = 0; i < positions.length; i++) {
    var cartesian3 = positions[i];
    var cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
    cartographics.push([
      Cesium.Math.toDegrees(cartographic.longitude),
      Cesium.Math.toDegrees(cartographic.latitude),
    ]);
    turfPoints.push(
      turf.point([
        Cesium.Math.toDegrees(cartographic.longitude),
        Cesium.Math.toDegrees(cartographic.latitude),
      ])
    );
  }
  if (!cartographics.length) return;
  cartographics = cartographics.concat([cartographics[0]]);
  var polygon = turf.polygon([cartographics]);
  var area = turf.area(polygon);
  //获取当前范围的中心点
  var features = turf.featureCollection(turfPoints);
  var turfCenter = turf.center(features);
  var center = turfCenter.geometry.coordinates;

  return {
    area: area,
    center: Cesium.Cartesian3.fromDegrees(center[0], center[1]),
  };
}
function formateArea(val: any, dw: string) {
  if (val == undefined) return;
  let dwStr = "";
  dw = dw || "m";
  if (dw == "km" || dw == "平方千米") {
    dwStr += (Number(val) / 1000000).toFixed(2) + "km²";
  } else if (dw == "m" || dw == "平方米") {
    dwStr += Number(val).toFixed(2) + "m²";
  } else {
  }
  return dwStr;
}
</script>
  
  <style scoped>
#cesiumContainer {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0px;
  left: 0px;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
.but {
  position: absolute;
  top: 50px;
  left: 100px;
  width: 200px;
  height: 20px;
  display: flex;
  justify-content: space-between;
  /* background-color: black; */
  z-index: 2;
}
.but div {
  height: 20px;
  font-size: 12px;
  z-index: 2;
  cursor: pointer;
  min-width: 100px;
  text-align: center;
  padding: 10px;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  border-radius: 5px;
  margin-left: 10px;
}


</style>
<style lang="scss" scoped>
 
.animated {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}

.animated.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}

.animated.hinge {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
}

/*the animation definition*/

@-webkit-keyframes fadeInDown {
  0% {
    opacity: 0;
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0)
  }
  100% {
    opacity: 1;
    -webkit-transform: none;
    transform: none
  }
}

@keyframes fadeInDown {
  0% {
    opacity: 0;
    -webkit-transform: translate3d(0, -100%, 0);
    -ms-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0)
  }
  100% {
    opacity: 1;
    -webkit-transform: none;
    -ms-transform: none;
    transform: none
  }
}

.fadeInDown {
  -webkit-animation-name: fadeInDown;
  animation-name: fadeInDown
}


/*base code*/
.animated_two {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.animated_two.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}
.animated_two.hinge {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
}
/*the animation definition*/
@-webkit-keyframes fadeOut {
  0% {
    opacity: 1
  }
  100% {
    opacity: 0
  }
}
@keyframes fadeOut {
  0% {
    opacity: 1
  }
  100% {
    opacity: 0
  }
}
.fadeOut {
  -webkit-animation-name: fadeOut;
  animation-name: fadeOut
}

/*base code*/
.animated_three {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.animated_three.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}
.animated_three.hinge {
  -webkit-animation-duration: 3s;
  animation-duration: 3s;
}
/*the animation definition*/
@-webkit-keyframes zoomIn {
  0% {
    opacity: 0;
    -webkit-transform: scale3d(.3, .3, .3);
    transform: scale3d(.3, .3, .3)
  }
  50% {
    opacity: 1
  }
}
@keyframes zoomIn {
  0% {
    opacity: 0;
    -webkit-transform: scale3d(.3, .3, .3);
    -ms-transform: scale3d(.3, .3, .3);
    transform: scale3d(.3, .3, .3)
  }
  50% {
    opacity: 1
  }
}
.zoomIn {
  -webkit-animation-name: zoomIn;
  animation-name: zoomIn
}


/*base code*/
.animated_four {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.animated_four.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}
.animated_four.hinge {
  -webkit-animation-duration: 3s;
  animation-duration: 3s;
}
/*the animation definition*/
@-webkit-keyframes fadeInUpBig {
  0% {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0)
  }
  100% {
    opacity: 1;
    -webkit-transform: none;
    transform: none
  }
}
@keyframes fadeInUpBig {
  0% {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    -ms-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0)
  }
  100% {
    opacity: 1;
    -webkit-transform: none;
    -ms-transform: none;
    transform: none
  }
}
.fadeInUpBig {
  -webkit-animation-name: fadeInUpBig;
  animation-name: fadeInUpBig
}

/*base code*/
.animated_six {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.animated_six.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}
.animated_six.hinge {
  -webkit-animation-duration: 3s;
  animation-duration: 3s;
}
/*the animation definition*/
@-webkit-keyframes fadeOutDownBig {
  0% {
    opacity: 1
  }
  100% {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0)
  }
}
@keyframes fadeOutDownBig {
  0% {
    opacity: 1
  }
  100% {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    -ms-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0)
  }
}
.fadeOutDownBig {
  -webkit-animation-name: fadeOutDownBig;
  animation-name: fadeOutDownBig
}


/*base code*/
.animated_five {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.animated_five.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}
.animated_five.hinge {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
}
/*the animation definition*/
@-webkit-keyframes rotateIn {
  0% {
    -webkit-transform-origin: center;
    transform-origin: center;
    -webkit-transform: rotate3d(0, 0, 1, -200deg);
    transform: rotate3d(0, 0, 1, -200deg);
    opacity: 0
  }
  100% {
    -webkit-transform-origin: center;
    transform-origin: center;
    -webkit-transform: none;
    transform: none;
    opacity: 1
  }
}
@keyframes rotateIn {
  0% {
    -webkit-transform-origin: center;
    -ms-transform-origin: center;
    transform-origin: center;
    -webkit-transform: rotate3d(0, 0, 1, -200deg);
    -ms-transform: rotate3d(0, 0, 1, -200deg);
    transform: rotate3d(0, 0, 1, -200deg);
    opacity: 0
  }
  100% {
    -webkit-transform-origin: center;
    -ms-transform-origin: center;
    transform-origin: center;
    -webkit-transform: none;
    -ms-transform: none;
    transform: none;
    opacity: 1
  }
}
.rotateIn {
  -webkit-animation-name: rotateIn;
  animation-name: rotateIn
}


/*base code*/
.animated_seven {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.animated_seven.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}
.animated_seven.hinge {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
}
/*the animation definition*/
@-webkit-keyframes rotateOut {
  0% {
    -webkit-transform-origin: center;
    transform-origin: center;
    opacity: 1
  }
  100% {
    -webkit-transform-origin: center;
    transform-origin: center;
    -webkit-transform: rotate3d(0, 0, 1, 200deg);
    transform: rotate3d(0, 0, 1, 200deg);
    opacity: 0
  }
}
@keyframes rotateOut {
  0% {
    -webkit-transform-origin: center;
    -ms-transform-origin: center;
    transform-origin: center;
    opacity: 1
  }
  100% {
    -webkit-transform-origin: center;
    -ms-transform-origin: center;
    transform-origin: center;
    -webkit-transform: rotate3d(0, 0, 1, 200deg);
    -ms-transform: rotate3d(0, 0, 1, 200deg);
    transform: rotate3d(0, 0, 1, 200deg);
    opacity: 0
  }
}
.rotateOut {
  -webkit-animation-name: rotateOut;
  animation-name: rotateOut
}


/*base code*/
.animated_eight {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.animated_eight.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}
.animated_eight.hinge {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
}
/*the animation definition*/
@-webkit-keyframes wobble {
  0% {
    -webkit-transform: none;
    transform: none
  }
  15% {
    -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
    transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg)
  }
  30% {
    -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
    transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg)
  }
  45% {
    -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
    transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg)
  }
  60% {
    -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
    transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg)
  }
  75% {
    -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
    transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg)
  }
  100% {
    -webkit-transform: none;
    transform: none
  }
}
@keyframes wobble {
  0% {
    -webkit-transform: none;
    -ms-transform: none;
    transform: none
  }
  15% {
    -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
    -ms-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
    transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg)
  }
  30% {
    -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
    -ms-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
    transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg)
  }
  45% {
    -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
    -ms-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
    transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg)
  }
  60% {
    -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
    -ms-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
    transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg)
  }
  75% {
    -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
    -ms-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
    transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg)
  }
  100% {
    -webkit-transform: none;
    -ms-transform: none;
    transform: none
  }
}
.wobble {
  -webkit-animation-name: wobble;
  animation-name: wobble
}


</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/656627.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

4.Redis之Redis的通用命令

0.Redis 实战操作 通过 redis-cli 客户端和 redis 服务器交互 涉及到很多的 redis 的命令 【redis 的命令非常非常多!!! 1.掌握常用命令(多操作多练习) 2.学会使用 redis 的文档-> 阅读文档, 是程序猿的基操!! redis 的命令非常非常多!!! 1.掌握常用命令(多操作多练习…

使用 Django 显示表中的数据

1、问题背景 当我们使用 Django 进行 Web 开发时&#xff0c;经常需要在 Web 页面上显示数据库中的数据。例如&#xff0c;我们可能需要在一个页面上显示所有用户的信息&#xff0c;或者在一个页面上显示所有文章的标题和作者。那么&#xff0c;如何使用 Django 来显示表中的数…

手机里装上好用的实用工具,生活办公更轻松

手机里装上好用的实用工具&#xff0c;生活办公才更轻松&#xff01;~ 1.一个木函 安卓手机里的“工具百宝箱”&#xff0c;应用集成了超过100种实用工具&#xff0c;包括单位和汇率换算、查询、OCR图片文字识别、自动文章摘要、图片表格识别和表情制作等等。它提供了全面的多…

防火墙技术基础篇:NAT转发之——Smart NAT(No-PAT和NAPT结合)

防火墙技术基础篇&#xff1a;NAT转发之——Smart NAT&#xff08;No-PAT和NAPT结合&#xff09; 传统的NAT技术在处理大规模网络和复杂应用场景时存在一定的局限性。为了解决这些问题&#xff0c;一种名为Smart NAT的新型网络技术应运而生。本文将详细介绍Smart NAT的概念、原…

信息标记形式 (XML, JSON, YAML)

文章目录 &#x1f5a5;️介绍&#x1f5a5;️三种形式&#x1f3f7;️XML (Extensible Markup Language)&#x1f516;规范&#x1f516;注释&#x1f516;举例&#x1f516;其他 &#x1f3f7;️JSON (JavaScript Object Notation)&#x1f516;规范&#x1f516;注释&#x…

数据恢复:手机数据恢复,盘点7个有效手机恢复方法

你知道吗&#xff0c;超过 70% 的智能手机用户都曾有过数据丢失的经历&#xff1f;如果你曾经丢失过手机中的重要文件&#xff0c;别担心&#xff0c;本文有解决办法。在本文中&#xff0c;我们将告诉你如何使用简单的步骤恢复手机中丢失的数据。无论你是不小心删除了文件还是手…

java.lang.NumberFormatException: For input string:

创建SpringBoot&#xff0c;Mybatis的项目时候&#xff0c;Service层调用Mapper层时候爆出了一个错误 发现报错是一个类型转换错误&#xff0c;经过排查后发现是因为mapper接收的实体类中没有写空参构造

Python: 使用pyotp实现OTP一次性密码验证

使用pyotp实现OTP一次性密码验证 OTP的基本原理 生成一个共享秘钥作为随机数的种子服务端通过种子计算出当前的密码客户端也通过相同的种子计算出当前的密码验证客户端生成的密码和服务端生成的密码是否匹配 服务端和客户端计算的方式一样 共享密钥 时间因子 算法 > 密…

吴恩达深度学习笔记:超 参 数 调 试 、 Batch 正 则 化 和 程 序 框 架(Hyperparameter tuning)3.8-3.9

目录 第二门课: 改善深层神经网络&#xff1a;超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)第三周&#xff1a; 超 参 数 调 试 、 Batch 正 则 化 和 程 序 框 架&#xff08;Hyperparameter …

线性插值的频域特性

1、抽取和插值的简单说明 抽取和插值是变采样过程中常用的两种手段&#xff0c;其中抽取的目的是降低数据的采样率&#xff0c;以降低对系统存储深度或计算量的要求。插值的目的是提高数据的采样率&#xff0c;以提高系统的计算精度。 M M M倍抽取通常是通过每隔 M M M…

全球首个AI代理驱动的元宇宙生态Wondra,让Web3再次伟大

前段时间&#xff0c;因为OpenAI的Sora发布、英伟达财报的发布&#xff0c;英伟达市值直逼2.5万亿美金&#xff0c;使得Crypto行业的AI赛道热度飙升&#xff0c;WLD&#xff0c;AGIX&#xff0c;FET等项目都有了不俗的表现。而这几天&#xff0c;因为大盘整体向好&#xff0c;再…

UVa1466/LA4849 String Phone

UVa1466/LA4849 String Phone 题目链接题意分析AC 代码 题目链接 本题是2010年icpc亚洲区域赛大田赛区的G题 题意 平面网格上有n&#xff08;n≤3000&#xff09;个单元格&#xff0c;各代表一个重要的建筑物。为了保证建筑物的安全&#xff0c;警察署给每个建筑物派了一名警察…

Android11 事件分发流程

在Android 11 输入系统之InputDispatcher和应用窗口建立联系一文中介绍到&#xff0c;当InputDispatcher写入数据后&#xff0c;客户端这边就会调用handleEvent方法接收数据 //frameworks\base\core\jni\android_view_InputEventReceiver.cpp int NativeInputEventReceiver::h…

Jmeter 安装教程:简单易懂

随着互联网的不断发展&#xff0c;网站和应用程序的性能测试变得越来越重要。Apache JMeter 是一款广泛使用的性能测试工具&#xff0c;它强大且使用广泛&#xff0c;适用于各种性能测试需求。不论你是刚刚接触性能测试的新手&#xff0c;还是一位有经验的测试工程师&#xff0…

总线带宽(总线系统的数据传送速率)

定义 总线上每秒钟传输的最大字节数或比特数 表示方法 通常使用“比特率”来表示&#xff0c;单位为比特每秒&#xff08;bps&#xff0c;b/s&#xff09;。 计算公式 总线带宽总线宽度/传输周期 其中&#xff0c;总线宽度是指数据总线的位数&#xff08;单位&#xff1a…

scp问题:Permission denied, please try again.

我把scp归纳三种情况&#xff1a; 源端root——》目标端root 源端root——》目标端mysql&#xff08;任意&#xff09;用户 源端&#xff08;任意用户&#xff09;——》目标端root用户 在scp传输文件的时候需要指导目标端的用户密码&#xff0c;如root用户密码、mysql用户…

solidwork3D草图案例-曲管

单位mm 3D草图 点击线&#xff0c;根据三视图&#xff0c;绘制直线&#xff0c; 圆角 半径25mm 扫描 三视图 如果觉得好的话&#xff0c;或者有疑问&#xff0c;请关注微信公众号咨询

RedHat9 | DNS剖析-配置转发DNS服务器

一、实验环境 1、转发DNS服务器 转发服务器&#xff08;Forwarding Server&#xff09;接受查询请求&#xff0c;但不直接提供DNS解析&#xff0c;而是将所有查询请求发送到另外一台DNS服务器&#xff0c;查询到结果后保存在本地缓存中。如果没有指定转发服务器&#xff0c;D…

Media Encoder 2024 for Mac媒体编码器安装教程ME2024安装包下载

安装 步骤 1&#xff0c;双击打开下载好的安装包。 2&#xff0c;选择install ame_24...双击打开启动安装程序。 3&#xff0c;点击install。 4&#xff0c;输入电脑密码。 5&#xff0c;软件安装中... 6&#xff0c;安装结束点击好。 7&#xff0c;返回打开的镜像 选择激活补…

品牌建设不迷路:系统化方法让品牌成长更高效

很多创始人才创业过程中都会发现&#xff1a; 企业越大&#xff0c;遇到的系统性的底层品牌问题就会越多&#xff0c;品牌的系统化建设底层根基如果不稳&#xff0c;后续的增长也会摇摇欲坠。 所以在当今竞争激烈的市场环境中&#xff0c;品牌的成功不仅仅依靠一个响亮的名字…