8464c92f4dac083c94aa53d10daebf6c475b7702..49f8e3361f43becf44e0c7509e622054633f171e
2025-09-24 jihongshun
时间轴悬停
49f8e3 对比 | 目录
2025-09-24 jihongshun
解决读取kmz问题
1b179a 对比 | 目录
已添加1个文件
已修改5个文件
12122 ■■■■■ 文件已修改
public/CesiumNavigation.js 11901 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/index.html 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/components/cesium-map.vue 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/flightRouteSimulation/index.vue 145 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/project/components/addPorjectDialog.vue 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/shootPoint/components/shootPointDialog.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/CesiumNavigation.js
¶Ô±ÈÐÂÎļþ
ÎļþÌ«´ó
public/index.html
@@ -219,3 +219,4 @@
<script src="CesiumPlus/CesiumTools.js"></script>
<script src="CesiumPlus/CesiumVideo/xbsjCameraVideoMixin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>
<script src="./CesiumNavigation.js"></script>
src/utils/components/cesium-map.vue
@@ -1,23 +1,23 @@
<template>
  <div :style="{height: cesiumContainer}">
    <div :id="cesiumId"></div>
     <CesiumCompass v-if="viewer  && showAnimation" :viewer="viewer" />
     <!-- <CesiumCompass v-if="viewer  && showAnimation" :viewer="viewer" /> -->
     <div id="crosshair" 
      v-if="showCrosshair"
      style="
        position:absolute;
        left:50%;
        top:50%;
        transform:translate(-50%,-50%);
        pointer-events:none;  /* ä¸é˜»æŒ¡é¼ æ ‡äº‹ä»¶ */
        v-if="showCrosshair"
        style="
          position:absolute;
          left:50%;
          top:50%;
          transform:translate(-50%,-50%);
          pointer-events:none;  /* ä¸é˜»æŒ¡é¼ æ ‡äº‹ä»¶ */
      ">
        <svg viewBox="0 0 24 24" width="32" height="32" style="color:red;">
          <path d="M12 2v6M12 16v6M2 12h6M16 12h6"
                stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
          <circle cx="12" cy="12" r="1.5" fill="currentColor"/>
        </svg>
  </div>
        ">
          <svg viewBox="0 0 24 24" width="32" height="32" style="color:red;">
            <path d="M12 2v6M12 16v6M2 12h6M16 12h6"
                  stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
            <circle cx="12" cy="12" r="1.5" fill="currentColor"/>
          </svg>
    </div>
  </div>
</template>
@@ -233,6 +233,13 @@
      this.viewer  = viewer
      // window.viewer = viewer;
      window[this.cesiumId].viewer = viewer
      window['cesiumContainer'].viewer.extend(Cesium.viewerCesiumNavigationMixin, {});
      // window['cesiumContainer'].viewer.camera.changed.addEventListener(function() {
      //     var currentHeading = Cesium.Math.toDegrees(window['cesiumContainer'].viewer.camera.heading);
      //     var currentPitch = Cesium.Math.toDegrees(window['cesiumContainer'].viewer.camera.pitch);
      //     console.log("实时朝向:", currentHeading, currentPitch);
      //     // åœ¨è¿™é‡Œæ›´æ–°ä½ çš„UI或变量
      // });
      this.$emit('mapReady');
    },
    resizeMap() {
@@ -267,4 +274,14 @@
.cesium-viewer-bottom{
  display: none;
}
#cesiumContainerYY{
  height: 100% !important;
}
#distanceLegendDiv{
  width: 200px;
  height: 200px;
  position: absolute;
  top: 20px;
  right: 20px;
}
</style>
src/views/system/flightRouteSimulation/index.vue
@@ -147,11 +147,22 @@
        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];
            dealArr.push({
                "lng": current.lng,
                "lat": current.lat,
                "alt": current.alt,
                'flyHeading':current.flyHeading,
                "heading": current.heading,
                "pitch": current.pitch,
                "roll": current.roll,
                "zoom":current.zoom || 1,
                'wait' : 5
            });
            dealArr.push({
                "lng": next.lng,
                "lat": next.lat,
@@ -160,13 +171,16 @@
                "heading": current.heading,
                "pitch": current.pitch,
                "roll": current.roll,
                "zoom":next.zoom || 1
                "zoom":current.zoom || 1,
                'wait':1
            });
        }
        // Push the last element without any change
        dealArr.push(this.waypoints[this.waypoints.length - 1]);
        this.waypoints = dealArr
        console.log(dealArr)
        this.fileInfo = `
          èˆªç‚¹:${this.waypoints.length}个 <br/>
          è·ç¦»:${this.calculateTotalDistance(this.waypoints).toFixed(2)}公里
@@ -187,10 +201,19 @@
        }
        // const startDate = new Date("2025-04-01T13:00:00Z");
        const startDate = new Date(date.toISOString());
        console.log(dealArr)
          let nowTime
        const result = dealArr.map((item, index) => {
          console.log(index)
        // const result = this.waypoints.map((item, index) => {
          // æ¯æ¬¡åР䏀天
          const time = new Date(startDate.getTime() + index * 60 * 1000).toISOString();
          // const time = new Date(startDate.getTime() + index * 60 *1000 + (item.wait ? item.wait :1 ) * 60 * 1000).toISOString();
          if(index == 0) {
             nowTime = startDate.getTime() + 1  *1000
          }else{
            nowTime = nowTime + (item.wait ? item.wait :1 )  *1000
          }
          const time  = new Date(nowTime).toISOString()
          // const time = Cesium.JulianDate.addSeconds(startDate, 3600, new Cesium.JulianDate());
          return {
            time,
@@ -208,7 +231,7 @@
          };
        });
        this.trajectoryData = result
        // console.log(this.trajectoryData)
        console.log(this.trajectoryData)
        this.loadTimeLine()
      } catch (error) {
        console.error(error);
@@ -237,9 +260,63 @@
        reader.readAsArrayBuffer(file);
      });
    },
    azimuthtwopoi(x1, y1, x2, y2) {
      let result;
      let a = Math.abs(Math.atan((y2 - y1) / (x2 - x1))) * 180 / Math.PI;
      if ((x2 - x1) < 0) {
        if ((y2 - y1) > 0) {
          result = a + 270;
        } else {
          result = 90 - a + 180;
        }
      } else {
        if ((y2 - y1) > 0) {
          result = 90 - a;
        } else {
          result = a + 90;
        }
      }
      return result;
    },
    dealdDirection(x1, y1, x2, y2){
      // å®šä¹‰ç‚¹1和点2的经纬度(单位:度)
      const point1 = Cesium.Cartesian3.fromDegrees(x1,y1); // ä¾‹å¦‚:点1的经纬度
      const point2 = Cesium.Cartesian3.fromDegrees(x2, y2);      // ä¾‹å¦‚:点2的经纬度
      // è®¡ç®—方向向量
      const direction = Cesium.Cartesian3.subtract(point2, point1, new Cesium.Cartesian3());
      // å½’一化方向向量
      Cesium.Cartesian3.normalize(direction, direction);
      // è®¡ç®—航向、俯仰和滚转角
      const headingPitchRoll = Cesium.HeadingPitchRoll.fromCartesian3(direction);
      // æ˜¾ç¤ºç»“æžœ
      console.log('Heading:', Cesium.Math.toDegrees(headingPitchRoll.heading));
      console.log('Pitch:', Cesium.Math.toDegrees(headingPitchRoll.pitch));
      console.log('Roll:', Cesium.Math.toDegrees(headingPitchRoll.roll));
    },
    Bearing(from, to){
      from = Cesium.Cartographic.fromCartesian(from)
      to = Cesium.Cartographic.fromCartesian(to)
      let lat1 = from.latitude
      let lon1 = from.longitude
      let lat2 = to.latitude
      let lon2 = to.longitude
      let angle = -Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2))
      if (angle < 0) {
        angle += Math.PI * 2.0
      }
      let degreesPerRadian = 180.0 / Math.PI // å¼§åº¦è½¬åŒ–为角度
      angle = angle * degreesPerRadian // è§’度
      return angle
    },
    // è§£æžKMZ文件
    async parseKMZ(kmzData) {
      // âš ï¸ è¿™é‡Œç›´æŽ¥ä½¿ç”¨å…¨å±€ JSZip å’Œ xml2js(通过CDN引入)
      const zip = await JSZip.loadAsync(kmzData);
      const kmlFile = Object.keys(zip.files).find(name =>
@@ -259,9 +336,39 @@
        result.kml.Document[0].Folder[0].Placemark || [];
      const points = [];
      var  lastZoom =1
      placemarks.forEach(placemark => {
        const coords = placemark.Point?.[0]?.coordinates?.[0];
        const height = placemark["wpml:height"]?.[0];
      let lastHeading = 0
      for(let i=0;i<placemarks.length;i++){
        const coords = placemarks[i].Point?.[0]?.coordinates?.[0];
        const height = placemarks[i]["wpml:height"]?.[0];
        if(i<placemarks.length-1){
          // console.log(placemarks[i])
          // console.log( placemarks[i].Point?.[0]?.coordinates?.[0].split(',')[0])
          // console.log( placemarks[i].Point?.[0]?.coordinates?.[0].split(',')[1])
          // console.log( placemarks[i+1].Point?.[0]?.coordinates?.[0].split(',')[0])
          // console.log( placemarks[i+1].Point?.[0]?.coordinates?.[0].split(',')[1])
          let lon1 = placemarks[i].Point?.[0]?.coordinates?.[0].split(',')[0]
          let lat1 = placemarks[i].Point?.[0]?.coordinates?.[0].split(',')[1]
          let lon2 = placemarks[i+1].Point?.[0]?.coordinates?.[0].split(',')[0]
          let lat2 = placemarks[i+1].Point?.[0]?.coordinates?.[0].split(',')[1]
          // console.log(this.azimuthtwopoi(lon1,lat1,lon2,lat2))
          // lastHeading =  this.azimuthtwopoi(lon1,lat1,lon2,lat2)
          var nowHeading = this.azimuthtwopoi(lon1,lat1,lon2,lat2)
          if(!nowHeading){
            nowHeading = lastHeading
          }else {
            let p1 = {"lng": lon1, "lat": lat1, "alt": height};
            let p2 = {"lng": lon2, "lat": lat2, "alt": height};
          let c1 = Cesium.Cartesian3.fromDegrees(p1.lng,p1.lat,p1.height);
          let c2 = Cesium.Cartesian3.fromDegrees(p2.lng,p2.lat,p2.height);
          lastHeading = this.Bearing(c1, c2);
            // lastHeading = this.azimuthtwopoi(lon1,lat1,lon2,lat2)
          }
          // console.log(lastHeading)
          //   console.log('+++++++++++++++++++++++++')
        }
        // æå– aircraftHeading
        // æå– action é‡Œçš„参数
        // åˆå§‹åŒ– Pitch, Roll å’Œ Heading
@@ -269,24 +376,31 @@
        let totalRoll = 0;
        let totalHeading = 0;
        let flyHeadingData = 0;
        if (placemark["wpml:actionGroup"]?.[0]?.["wpml:action"]) {
          placemark["wpml:actionGroup"][0]["wpml:action"].forEach(action => {
        if (placemarks[i]["wpml:actionGroup"]?.[0]?.["wpml:action"]) {
          placemarks[i]["wpml:actionGroup"][0]["wpml:action"].forEach(action => {
            // å¤„理 gimbalRotate å’Œ rotateYaw å‡½æ•°
            if (action['wpml:actionActuatorFunc'].includes("gimbalRotate")) {
                // èŽ·å–æ¯ä¸ªè§’åº¦å€¼
                const gimbalPitch = parseFloat(action['wpml:actionActuatorFuncParam'][0]["wpml:gimbalPitchRotateAngle"][0]);
                const gimbalRoll = parseFloat(action['wpml:actionActuatorFuncParam'][0]["wpml:gimbalRollRotateAngle"][0]);
                const gimbalYaw = parseFloat(action['wpml:actionActuatorFuncParam'][0]["wpml:gimbalYawRotateAngle"][0]);
                if(gimbalYaw < 0 ){
                  gimbalYaw += 360
                }
                // ç´¯åŠ  Pitch, Roll å’Œ Heading
                totalPitch += gimbalPitch;
                totalRoll += gimbalRoll;
                totalHeading += gimbalYaw;
                // totalHeading += gimbalYaw;
            }
            // å¤„理 rotateYaw å‡½æ•°
            if (action['wpml:actionActuatorFunc'].includes("rotateYaw")) {
                // èŽ·å– aircraftHeading
                const aircraftHeading = parseFloat(action['wpml:actionActuatorFuncParam'][0]["wpml:aircraftHeading"][0]);
                var aircraftHeading = parseFloat(action['wpml:actionActuatorFuncParam'][0]["wpml:aircraftHeading"][0]);
                if(aircraftHeading <0) {
                  aircraftHeading+=360
                }
                flyHeadingData = aircraftHeading
                // å°† aircraftHeading ç´¯åŠ åˆ° totalHeading
                totalHeading += aircraftHeading;
@@ -302,11 +416,11 @@
        if (coords) {
          coords.trim().split(" ").forEach(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,zoom :lastZoom});
            points.push({ lng, lat, alt: height,heading:totalHeading ?totalHeading:lastHeading ,pitch:totalPitch || 0,roll:totalRoll|| 0 ,flyHeading:flyHeadingData,zoom :lastZoom});
          });
        }
      });
      }
      console.log(points)
      if (points.length === 0) throw new Error("未找到有效航点");
      return points;
    },
@@ -582,6 +696,7 @@
        const holderYtHeading = this.holderHeadingProperty.getValue(currentTime)
        const holderYtPitch = this.holderPitchProperty.getValue(currentTime)
        const holderYtRoll = this.holderRollProperty.getValue(currentTime)
        console.log(holderYtHeading)
        if(holderYtHeading) {
          this.heading = holderYtHeading
          this.pitch = holderYtPitch
src/views/system/project/components/addPorjectDialog.vue
@@ -444,7 +444,8 @@
                  newChild.height += (device.ardTowerModel?.modelHeight  - newChild.height +  20) ;
                  console.log('push11111111111111')
                  // æ·»åŠ åˆ°children数组末尾
                  device.children.push(newChild);
                  console.log(newChild)
                  device.children.push(newChild);
                }
            }
          }
@@ -456,7 +457,7 @@
                const newChild = JSON.parse(JSON.stringify(lastChild));
                if(newChild.label.includes('加高')) {
                }else {
                  newChild.label = newChild.label + '-加高第一个点'
                  newChild.label = newChild.label + '-加高'
                  newChild.height += (device.ardTowerModel?.modelHeight  - newChild.height +  20) ;
                  // æ·»åŠ åˆ°children数组末尾
                  device.children.unshift(newChild);
@@ -711,22 +712,34 @@
      console.log(this.ruleForm)
      const routePointList = [];
      this.treeData.forEach(item => {
        // éåŽ†æ¯ä¸ªè®¾å¤‡ä¸­çš„ children
        item.children.forEach(child => {
          // åˆ¤æ–­ label æ˜¯å¦åŒ…含 '加高'
          if (child.label.includes( '加高')) {
            // åˆ é™¤ children ä¸­çš„æ‰€æœ‰åœ°é¢ç‚¹
            // child.children = child.children.filter(subChild => !subChild.label.includes("地面点"));
            child.children = []
          }
        });
      })
      console.log(this.treeData)
      this.treeData.forEach(device => {
        device.children.forEach((airPoint, index) => {
          console.log(airPoint)
          routePointList.push({
            routePointIndex: routePointList.length,
            longitude: airPoint.longitude,
            latitude: airPoint.latitude,
            height: airPoint.height,
            isStartAndEndPoint: false,
            actions:airPoint.children[0].actions || [],
            actions:airPoint.children?.length !=0 ? airPoint.children[0]?.actions || [] : [],
            waypointName: airPoint.label,
            coordinatePointReq: {
            coordinatePointReq: airPoint.children?.length !=0 ? {
                height: airPoint.children[0].height,
                latitude:airPoint.children[0].latitude,
                longitude: airPoint.children[0].longitude
              }
              } : null
          });
        });
      });
src/views/system/shootPoint/components/shootPointDialog.vue
@@ -530,7 +530,8 @@
      console.log(this.treeData)
    },
    //数组 å¡”的精度 å¡”的纬度  å¡”的高度  åŠå¾„
    insertRaisedPoints(data, centerLon, centerLat, centerHeight, radius = 1) {
    insertRaisedPoints(data, centerLon, centerLat, centerHeight, radius = 15) {
    // insertRaisedPoints(data, centerLon, centerLat, centerHeight, radius = 1) {
      const center = Cesium.Cartesian3.fromDegrees(centerLon, centerLat, centerHeight);
      const result = JSON.parse(JSON.stringify(data)); // æ·±æ‹·è´é¿å…æ±¡æŸ“原数据
      const inserts = []; // ç”¨äºŽå­˜å‚¨æ’入项及其目标位置