jihongshun
2025-09-13 32d4167c093317c16cd67af5277e11a2f08809db
航线模拟功能完成 待优化
已修改7个文件
221 ■■■■■ 文件已修改
src/components/common/cesiumMapNoSelect.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/common/cesiumMapSelctPoint.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/components/cesium-map.vue 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/flightRouteSimulation/index.vue 141 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/project/components/addPorjectDialog.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/shootPoint/components/chooseModelDialog.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/common/cesiumMapNoSelect.vue
@@ -58,6 +58,7 @@
  },
  methods: {
    clearMap () {
      let viewer = window['cesiumContainer'].viewer
      this.showCard = false
      this.form.longitude = ''
      this.form.latitude = ''
@@ -67,6 +68,7 @@
      viewer.entities.removeById("drawPointEntity")
    },
    handlePickMapPoint() {
      let viewer = window['cesiumContainer'].viewer
      let options = {
        viewer: viewer,
        pointcolor: Cesium.Color.BLUE,
@@ -74,8 +76,6 @@
        text: '新',
        size: 36,
      };
      //开启监听拾取地图点位
      viewer = window.viewer
      CesiumDraw.drawPoint(options, () => {
        this.camPosition = document.getElementById('AttributePoi').value;
        let pois = this.camPosition.split(",");
@@ -103,6 +103,7 @@
      this.drawPoint(Cesium.Cartesian3.fromDegrees(point.longitude,point.latitude,point.altitude))
    },
    drawPoint(point) {
      let viewer = window['cesiumContainer'].viewer
      var drawPointEntity = viewer.entities.getById("drawPointEntity");
      if (drawPointEntity) {
        drawPointEntity.position = point.clone();
@@ -138,6 +139,7 @@
      this.form[key] = arr.join('')
    },
    handleFocus(key) {
      let viewer = window['cesiumContainer'].viewer
      this.form[key] = ''
      viewer.entities.removeById("drawPointEntity")
    }
src/components/common/cesiumMapSelctPoint.vue
@@ -58,6 +58,7 @@
  },
  methods: {
    clearMap () {
      let viewer = window['cesiumContainer'].viewer
      this.showCard = false
      this.form.longitude = ''
      this.form.latitude = ''
@@ -67,6 +68,7 @@
      viewer.entities.removeById("drawPointEntity")
    },
    handlePickMapPoint() {
      let viewer = window['cesiumContainer'].viewer
      let options = {
        viewer: viewer,
        pointcolor: Cesium.Color.BLUE,
@@ -75,7 +77,6 @@
        size: 36,
      };
      //开启监听拾取地图点位
      viewer = window.viewer
      CesiumDraw.drawPoint(options, () => {
        this.camPosition = document.getElementById('AttributePoi').value;
        let pois = this.camPosition.split(",");
@@ -103,6 +104,7 @@
      this.drawPoint(Cesium.Cartesian3.fromDegrees(point.longitude,point.latitude,point.altitude))
    },
    drawPoint(point) {
      let viewer = window['cesiumContainer'].viewer
      var drawPointEntity = viewer.entities.getById("drawPointEntity");
      if (drawPointEntity) {
        drawPointEntity.position = point.clone();
@@ -138,6 +140,7 @@
      this.form[key] = arr.join('')
    },
    handleFocus(key) {
      let viewer = window['cesiumContainer'].viewer
      this.form[key] = ''
      viewer.entities.removeById("drawPointEntity")
    }
src/utils/components/cesium-map.vue
@@ -1,7 +1,7 @@
<template>
  <div :style="{height: cesiumContainer}">
    <div id="cesiumContainer"></div>
     <CesiumCompass v-if="viewer" :viewer="viewer" />
    <div :id="cesiumId"></div>
     <CesiumCompass v-if="viewer  && showAnimation" :viewer="viewer" />
  </div>
</template>
@@ -30,6 +30,20 @@
export default {
  name: "cesium-map",
  components: { CesiumCompass },
  props: {
    showAnimation: {
      type: Boolean,
      default: false,
    },
    showCesiumCompass: {
      type: Boolean,
      default: false,
    },
    cesiumId: {
      type: String,
      default: 'cesiumContainer',
    }
  },
  data() {
    return {
      // 日期范围
@@ -124,7 +138,7 @@
        "TRjZWYtODJhOS1jZTk5ZmI4ZDg5ZTIiLCJpZCI6ODI1MCwic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU1MTU3M" +
        "DU1Mn0.yfJ_i4EPiunFj_qUftuv1ksx4pUNgnPC16vQCBGrM08";
      //初始化三维场景
      viewer = new Cesium.Viewer("cesiumContainer", {
      viewer = new Cesium.Viewer(this.cesiumId, {
        fullscreenButton: false,
        homeButton: false,
        timeline: false,
@@ -140,9 +154,9 @@
        // animation: false,
        // timeline: false,
        // fullscreenButton: false,
        animation: true,
        timeline: true,
        fullscreenButton: true,
        animation:this.showAnimation ?  true :false,
        timeline: this.showAnimation ? true : false,
        fullscreenButton: this.showAnimation ? true : false,
        vrButton: false,
//         terrainProvider: new Cesium.CesiumTerrainProvider({
//             url : Cesium.IonResource.fromAssetId(1),
@@ -171,12 +185,13 @@
      })
      console.log(viewer)
      this.viewer  = viewer
      window.viewer = viewer;
      // window.viewer = viewer;
      window[this.cesiumId].viewer = viewer
      this.$emit('mapReady');
    },
    resizeMap() {
      let winHeight = Number(document.documentElement.clientWidth);
      document.getElementById("cesiumContainer").style.height =
      document.getElementById(this.cesiumId).style.height =
        winHeight + "px";
    },
  },
src/views/system/flightRouteSimulation/index.vue
@@ -1,13 +1,14 @@
<template>
   <div class="app-container">
    <el-button type="primary" @click="showGZ">显示视锥体</el-button>
    <a @click="showGZ">显示视锥体</a>
    <input @change="handleKMZUpload" type="file" id="kmzFile" accept=".kmz" class="block w-full text-sm text-gray-500
    file:mr-4 file:py-2 file:px-4
    file:rounded-md file:border-0
    file:text-sm file:font-semibold
    file:bg-blue-50 file:text-blue-700
    hover:file:bg-blue-100">
    <CesiumMap style="height: 790px;"></CesiumMap>
    <CesiumMap style="height: 790px;" :showAnimation = true :showCesiumCompass = true :cesiumId="'cesiumContainer'"></CesiumMap>
    <CesiumMap style="height: 324px;width: 576px;" :showAnimation = false :showCesiumCompass = false :cesiumId="'cesiumContainerYY'" class="eagleye"></CesiumMap>
   </div>
</template>
@@ -119,21 +120,19 @@
        this.waypoints = await this.parseKMZ(arrayBuffer);
        //加点逻辑 比如向第2-n-1中插入元素  经纬度为当前的  heading pitch roll 下一个的
        const dealArr = [];
        // console.log(">> this.waypoints:", this.waypoints);
        console.log(">> this.waypoints:", this.waypoints);
        for (let i = 0; i < this.waypoints.length - 1; i++) {
            dealArr.push(this.waypoints[i]); // Push the current element
            const current = this.waypoints[i];
            const next = this.waypoints[i + 1];
            // Create a new element with the current lng, lat and next heading, pitch, roll
            dealArr.push({
                "lng": current.lng,
                "lat": current.lat,
                "alt": current.alt,
                "lng": next.lng,
                "lat": next.lat,
                "alt": next.alt,
                'flyHeading':next.flyHeading,
                "heading": next.heading,
                "pitch": next.pitch,
                "roll": next.roll
                "heading": current.heading,
                "pitch": current.pitch,
                "roll": current.roll
            });
        }
@@ -170,7 +169,8 @@
            heading:item.heading|| 0,
            pitch:item.pitch|| 0,
            roll:item.roll || 0,
            speed: speeds[index] || 0,
            // speed: speeds[index] || 0,
            speed: 80,
            // flyHeading:item.flyHeading
          };
        });
@@ -259,6 +259,7 @@
      console.log("Total Heading:", totalHeading);
        if (coords) {
          coords.trim().split(" ").forEach(coord => {
            console.log(coord)
            const [lng, lat] = coord.split(",").map(Number);
            points.push({ lng, lat, alt: height,heading:totalHeading  || 0,pitch:totalPitch || 0,roll:totalRoll|| 0 ,flyHeading:flyHeadingData});
          });
@@ -299,6 +300,7 @@
      return R * c;
    },
    showFlightPath() {
      let viewer = window['cesiumContainer'].viewer
      console.log(">> this.waypoints:", this.waypoints);
      if (this.waypoints.length === 0) return alert('请先上传KMZ文件');
      // 转换坐标
@@ -355,6 +357,7 @@
      })
    },
    createModel(data){
      let viewer = window['cesiumContainer'].viewer
      viewer.entities.add({
        id: data.id,
        position: Cesium.Cartesian3.fromDegrees(data.longitude, data.latitude, data.altitude),
@@ -378,26 +381,55 @@
          disableDepthTestDistance: 100000000
        }
      });
      window['cesiumContainerYY'].viewer.entities.add({
        id:data.id+ 'yytower',
        position: Cesium.Cartesian3.fromDegrees(data.longitude, data.latitude, data.altitude),
        model: {
          uri: data?.ardTowerModel?.modelRoute,
          scale: 1,
        },
        label: {
          show: true,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          font: '28px Helvetica',
          outlineColor: Cesium.Color.RED,
          outlineWidth: 3,
          fillColor: Cesium.Color.fromCssColorString('#FFFFFF'), //44c3cc
          text: data.deviceName,
          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
          pixelOffset: new Cesium.Cartesian2(0.0, -56.0),
          scaleByDistance: new Cesium.NearFarScalar(1000, 0.6, 10000, 0.4),
          pixelOffsetScaleByDistance: new Cesium.NearFarScalar(1000, 0.4, 10000, 0.4),
          disableDepthTestDistance: 100000000
        }
      });
    },
    loadTimeLine(){
      let viewer = window['cesiumContainer'].viewer
      // 设置时间范围
      console.log(this.trajectoryData)
      const allTimes = this.trajectoryData.map(item => Cesium.JulianDate.fromIso8601(item.time))
      // 获取所有时间,并减去8小时
      // const allTimes = this.trajectoryData.map(item => {
      //     const time = Cesium.JulianDate.fromIso8601(item.time)
      //     return Cesium.JulianDate.addHours(time, +8, new Cesium.JulianDate())
      // })
      console.log(allTimes)
      const startTime = allTimes[0]
      const stopTime = allTimes[allTimes.length - 1]
      console.log(startTime)
      console.log(stopTime)
      // const startTime = Cesium.JulianDate.minimum(...allTimes)
      // const stopTime = Cesium.JulianDate.maximum(...allTimes)
      viewer.clock.startTime = startTime.clone()
      viewer.clock.stopTime = stopTime.clone()
      viewer.clock.currentTime = startTime.clone()
      viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP
      viewer.clock.clockRange = Cesium.ClockRange.CLAMPED
      viewer.timeline.zoomTo(startTime, stopTime)
      const duration = Cesium.JulianDate.secondsDifference(stopTime, startTime);
      console.log(`时间轴总时长: ${duration} 秒`)
      // 创建位置和速度属性
      const speedProperty = new Cesium.SampledProperty(Number)
@@ -406,6 +438,7 @@
      // 添加采样点
      this.trajectoryData.forEach(data => {
        const time = Cesium.JulianDate.fromIso8601(data.time)
        console.log("存储的时间:", Cesium.JulianDate.toDate(time))
        const position = Cesium.Cartesian3.fromDegrees(
          data.position.longitude,
          data.position.latitude,
@@ -425,7 +458,6 @@
            Cesium.Math.toRadians(0)
        );
        const quaternion = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
        console.log(Cesium.JulianDate.toDate(time))
        // // 添加飞机朝向采样
        this.orientation.addSample(time, quaternion);
        //云台
@@ -434,9 +466,13 @@
            Cesium.Math.toRadians(data.pitch),
            Cesium.Math.toRadians(data.roll)
        );
        console.log(szthpr)
        // console.log( Cesium.Math.toRadians(data.heading))
        const sztquaternion = Cesium.Transforms.headingPitchRollQuaternion(position, szthpr);
        console.log(sztquaternion)
        this.sztOrientation.addSample(time, sztquaternion);
        console.log(this.sztOrientation)
        // console.log(this.orientation)
      })
      // console.log(">> positionProperty:",this.positionProperty );
@@ -488,9 +524,22 @@
      } else {
        console.warn('Frustum outline is not initialized');
      }
      let yyDestination = this.c3Position
      window['cesiumContainerYY'].viewer.camera.setView(
        {
          destination: yyDestination,
          orientation: {
            // 指向
            heading: Cesium.Math.toRadians(Number(this.heading)),
            // 视角
            pitch: Cesium.Math.toRadians(Number(this.pitch)),
            roll: Cesium.Math.toRadians(Number(this.roll))
          }
        }
      )
    },
    listenChange() {
      let viewer =  window.viewer;
      let viewer =  window['cesiumContainer'].viewer;
      viewer.clock.onTick.addEventListener(() => {
        if (viewer.clock.shouldAnimate) {
          this.getCurrentPosition()
@@ -504,14 +553,17 @@
      });
    },
    getCurrentPosition() {
      let viewer =  window['cesiumContainer'].viewer;
      console.log(this.sztOrientation)
      // 获取当前时间
      const currentTime = viewer.clock.currentTime;
      console.log(Cesium.JulianDate.toDate(currentTime))
      console.log('start:', Cesium.JulianDate.toDate(this.positionProperty._property._times[0]));
      console.log('stop:', Cesium.JulianDate.toDate(this.positionProperty._property._times.slice(-1)[0]));
      console.log("当前时间:", Cesium.JulianDate.toDate(currentTime));
      // console.log(Cesium.JulianDate.toDate(currentTime))
      // console.log('start:', Cesium.JulianDate.toDate(this.positionProperty._property._times[0]));
      // console.log('stop:', Cesium.JulianDate.toDate(this.positionProperty._property._times.slice(-1)[0]));
      // const currentTime = Cesium.JulianDate.addHours(currentTime, -8, new Cesium.JulianDate());
      
      console.log(currentTime)
      // console.log(currentTime)
      // 从 positionProperty 中获取当前位置
      const currentPosition = this.positionProperty.getValue(currentTime);
      
@@ -523,12 +575,9 @@
        // 将经纬度从弧度转换为度
        this.currentLongitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
        console.log(Cesium.Math.toDegrees(cartographicPosition.longitude))
        console.log(Cesium.Math.toDegrees(cartographicPosition.latitude))
        this.currentLatitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
        this.currentHeight = cartographicPosition.height;
        this.c3Position = Cesium.Cartesian3.fromDegrees(this.currentLongitude, this.currentLatitude,this.currentHeight)
        // console.log(`当前位置 - 经度: ${this.currentLongitude}, 纬度: ${this.currentLatitude}, 高度: ${this.currentHeight}`);
        //相机变化
        const quaternion = this.orientation.getValue(currentTime)
        // if(quaternion) {
@@ -541,11 +590,12 @@
        if (sztquaternion) {
          const hpr = Cesium.HeadingPitchRoll.fromQuaternion(sztquaternion)
          console.log(hpr)
          this.heading = Cesium.Math.toDegrees(hpr.heading).toFixed(2)
          this.heading = (Cesium.Math.toDegrees(hpr.heading).toFixed(2)-143.32384000000002 )
          // this.heading = 180
          this.pitch = Cesium.Math.toDegrees(hpr.pitch).toFixed(2)
          this.roll = Cesium.Math.toDegrees(hpr.roll).toFixed(2)
          console.log('当前位置 - heading ' + this.heading)
          this.pitch = (Cesium.Math.toDegrees(hpr.pitch).toFixed(2) - 14.33)
          // this.roll = Cesium.Math.toDegrees(hpr.roll).toFixed(2)
          this.roll = 0
          // console.log('当前位置 - heading ' + this.heading)
          console.log(`当前位置 - heading: ${this.heading}, pitch: ${this.pitch}, roll: ${this.roll}`);
        }
        
@@ -554,13 +604,35 @@
        console.log("无法获取当前位置");
      }
    },
    quaternionToHeadingPitchRoll(quaternion) {
        const x = quaternion.x;
        const y = quaternion.y;
        const z = quaternion.z;
        const w = quaternion.w;
        // 构建旋转矩阵元素
        const m11 = 1 - 2 * (y * y + z * z);
        const m12 = 2 * (x * y - w * z);
        const m13 = 2 * (x * z + w * y);
        const m21 = 2 * (x * y + w * z);
        const m22 = 1 - 2 * (x * x + z * z);
        const m23 = 2 * (y * z - w * x);
        const m31 = 2 * (x * z - w * y);
        const m32 = 2 * (y * z + w * x);
        const m33 = 1 - 2 * (x * x + y * y);
        const heading = Math.atan2(m21, m11);
        const pitch = Math.asin(-m31);
        const roll = Math.atan2(m32, m33);
        return new Cesium.HeadingPitchRoll(heading, pitch, roll);
    },
    showGZ(){
       let viewer = window.viewer;
      let viewer = window['cesiumContainer'].viewer;
      this.camera = new Cesium.Camera(viewer.scene)
      // 视锥体参数
      this.camera.frustum = new Cesium.PerspectiveFrustum({
        // fov: Cesium.Math.PI_OVER_THREE,
        fov: Cesium.Math.toRadians(10),
        fov: Cesium.Math.PI_OVER_THREE,
        // aspectRatio: this.aspectRatio,
        aspectRatio: 1920 / 1080,
      });
@@ -588,3 +660,10 @@
  }
}
</script>
<style>
.eagleye{
  position: absolute;
  right: 30px;
  bottom: 50px;
}
</style>
src/views/system/project/components/addPorjectDialog.vue
@@ -250,7 +250,7 @@
      this.$emit('close')
    },
    flyToLocal(row){
      let viewer = window['cesiumContainer'].viewer
      console.log(row)
       const position = Cesium.Cartesian3.fromDegrees(row.longitude,row.latitude, row.deviceHeight);
      // rotationAngle  = Cesium.Math.toRadians(row.face)  ||  Cesium.Math.toRadians(0)
@@ -331,6 +331,7 @@
      }));
    },
    deleteData(row){
      let viewer = window['cesiumContainer'].viewer
      console.log(row)
      // 找到 id 为 "1" 的元素索引
      const index = this.tableData.findIndex(item => item.id === row.id);
@@ -536,6 +537,7 @@
      return 'id_' + Math.random().toString(36).substring(2, 10);
    },
    drawConnectionsWithLabels(devices) {
      let viewer = window['cesiumContainer'].viewer
      if(lastConnectPolyline) {
        viewer.entities.remove(lastConnectPolyline)
        lastConnectPolyline = null
src/views/system/shootPoint/components/chooseModelDialog.vue
@@ -71,38 +71,6 @@
        this.$emit('cancel')
        this.$emit('getRowData',row)
      },  
      clickRow(row){
        console.log(row)
        this.showMap =true
        setTimeout(()=>{
          const position = Cesium.Cartesian3.fromDegrees(0, 0, 0);
          // 设置模型方向(可选)
          // const heading = Cesium.Math.toRadians(135); // 朝东南方向
          let model = viewer.entities.getById("modelList");
          const heading = Cesium.Math.toRadians(120); // 朝东南方向
          const pitch = 0;
          const roll = 0;
          const orientation = Cesium.Transforms.headingPitchRollQuaternion(
            position,
            new Cesium.HeadingPitchRoll(heading, pitch, roll)
          );
          if(!model) {
            // 加载 glTF 模型
            const entity = viewer.entities.add({
              id: "modelList",
              name: "modelList",
              position: position,
              orientation: orientation,
              model: {
                uri: row.modelRoute, // 替换成你的模型路径
              },
            });
            viewer.flyTo(entity)
          }else {
            model.orientation = orientation
          }
        },1000)
      },
    }
  };
</script>
vue.config.js
@@ -9,7 +9,7 @@
const name = process.env.VUE_APP_TITLE || '电力巡检航线规划'; // 网页标题
const baseUrl = 'http://192.168.1.25:7070'; // 后端接口
const baseUrl = 'http://47.104.204.210:7070'; // 后端接口
// const baseUrl = 'http://192.168.1.13:8080'; // 后端接口
const port = process.env.port || process.env.npm_config_port || 80; // 端口