From ca62ae43d7614216e5d43dd905fde1fd4a260158 Mon Sep 17 00:00:00 2001
From: jihongshun <1151753686@qq.com>
Date: 星期一, 28 七月 2025 17:25:33 +0800
Subject: [PATCH] 视锥体支持变倍

---
 src/views/system/project/components/addPorjectDialog.vue |  307 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 288 insertions(+), 19 deletions(-)

diff --git a/src/views/system/project/components/addPorjectDialog.vue b/src/views/system/project/components/addPorjectDialog.vue
index cf5606f..d7fdb06 100644
--- a/src/views/system/project/components/addPorjectDialog.vue
+++ b/src/views/system/project/components/addPorjectDialog.vue
@@ -10,7 +10,6 @@
           <el-col :span=6>
               <el-card class="noScroll">
                 <div class="chooseModel">
-                  <!-- <el-button type="primary" @click='chooseModel'>娣诲姞璁惧</el-button> -->
                   <div class="fontJust">璁惧鍒楄〃</div>
                    <el-button @click="addDevice"> 鏂板</el-button>
                   <el-table
@@ -23,15 +22,16 @@
                       width="150">
                     </el-table-column>
                     <el-table-column
-                      prop="muban"
+                      prop="mode"
                       label="妯℃澘"
-                      width="150">
+                      width="120">
                     </el-table-column>
                     <el-table-column
                       fixed="right"
                       label="鎿嶄綔"
-                      width="100">
+                      width="130">
                       <template slot-scope="scope">
+                        <el-button type="text" size="small" @click="chooseModel(scope.row)">妯℃澘</el-button>
                         <el-button type="text" size="small" @click="flyToLocal(scope.row)">瀹氫綅</el-button>
                         <el-button type="text" size="small" @click="deleteData(scope.row)">绉婚櫎</el-button>
                       </template>
@@ -47,7 +47,6 @@
                     class="filter-tree"
                     :data="treeData"
                     :props="defaultProps"
-                    draggable  
                     default-expand-all
                     ref="tree">
                   </el-tree>
@@ -63,16 +62,21 @@
         <el-button type="primary" @click="submit()" >鐢熸垚鑸嚎浠诲姟</el-button>
       </span>
     </el-dialog>
-     <chooseDeviceDialog v-if="showModel" @cancel ='cancel' @dealChooseArr="dealChooseArr" ></chooseDeviceDialog>
+     <chooseDeviceDialog v-if="showDevice" @cancel ='cancel' @dealChooseArr="dealChooseArr" ></chooseDeviceDialog>
+     <chooseModelDialog v-if="showModel" @cancelModel ='cancelModel' @receiveModel="receiveModel" :deviceId="deviceId"></chooseModelDialog>
   </div>
 </template>
 <script>
 import CesiumMap from "../../../../utils/components/cesium-map.vue";
 import chooseDeviceDialog from './chooseDeviceDialog.vue';
+import chooseModelDialog from './chooseModelDialog.vue';
+import { obtainRealData ,buildKmz} from "@/api/system/template"
+
 export  default{
   components: {
     CesiumMap,
-    chooseDeviceDialog
+    chooseDeviceDialog,
+    chooseModelDialog
   },
   data(){
     return{
@@ -83,20 +87,20 @@
           children: 'children',
           label: 'label'
         },
+        showDevice:false,
+        multipleSelection: [],
         showModel:false,
-        multipleSelection: []
+        deviceId:null
     }
   },
   methods:{
     handleClose(){
-      console.log("close")
       this.dialogVisible = false
       this.$emit('close')
     },
     flyToLocal(row){
       console.log(row)
-      console.log(viewer)
-       const position = Cesium.Cartesian3.fromDegrees(row.longitude,row.latitude, row.altitude);
+       const position = Cesium.Cartesian3.fromDegrees(row.longitude,row.latitude, row.deviceHeight);
 
       // 璁剧疆妯″瀷鏂瑰悜锛堝彲閫夛級
       const heading = Cesium.Math.toRadians(row.face); // 鏈濅笢鍗楁柟鍚�
@@ -113,19 +117,35 @@
         position: position,
         orientation: orientation,
         model: {
-          uri: "http://192.168.1.5:9000/tower/2025/07/01/tower_20250701145739A004.glb", // 鏇挎崲鎴愪綘鐨勬ā鍨嬭矾寰�
-          scale: 1000,
+          uri: row?.ardTowerModel.modelRoute, // 鏇挎崲鎴愪綘鐨勬ā鍨嬭矾寰�
+          scale: 1,
         },
+        label: {
+          show: true,
+          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+          font: '28px Helvetica',
+          outlineColor: Cesium.Color.BLUE,
+          outlineWidth: 3,
+          fillColor: Cesium.Color.fromCssColorString('#FFFFFF'), //44c3cc
+          text: row.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
+        }
       });
       console.log(entity)
       // 椋炶鍒版ā鍨嬩綅缃�
+      console.log(this.treeData)
       viewer.flyTo(entity)
     },
     addDevice(){
-      this.showModel = true
+      this.showDevice = true
     },
     cancel(){
-      this.showModel = false
+      this.showDevice = false
     },
     hasSameId(array1, array2) {
       const ids1 = new Set(array1.map(item => item.id));
@@ -145,29 +165,278 @@
             type: 'warning'
           })
         }
-        this.tableData = this.tableData.concat(arr)
+        this.tableData = this.treeData.concat(arr)
       }
       const dealTreeData =this.dealTee()
       this.treeData = dealTreeData
-      console.log(this.treeData)
     },
     dealTee(){
+      console.log(this.tableData)
      return  this.tableData.map(item => ({
         ...item,
         label: item.deviceName,
-        children: []
       }));
     },
     deleteData(row){
       // 鎵惧埌 id 涓� "1" 鐨勫厓绱犵储寮�
       const index = this.tableData.findIndex(item => item.id === row.id);
-
       // 濡傛灉鎵惧埌浜嗭紝鍒犻櫎璇ュ厓绱�
       if (index !== -1) {
         this.tableData.splice(index, 1);
       }
       const dealTreeData = this.dealTee()
       this.treeData = dealTreeData
+    },
+    chooseModel(row){
+      this.deviceId = row.id
+      this.showModel = true
+    },
+    cancelModel(){
+      this.showModel = false
+    },
+    receiveModel(obj){
+      //deal閫昏緫
+      console.log(obj)
+      let flightTemplateId =obj.modelObj.id
+      let deviceId = obj.deviceId
+      this.dealTableTemplate(obj)
+      // let 
+      obtainRealData(flightTemplateId,deviceId).then(res=>{
+        console.log(res)
+        let treeDealData = this.transformFlightData(res.data?.coordinateSystemVoS || [])
+        console.log(treeDealData)
+        this.dealTreeMerge(obj,treeDealData)
+        // const aaa = this.rotateAllPoints(this.treeData || [],res.data.longitude,res.data.latitude,res.data.height)
+         this.drawConnectionsWithLabels(this.treeData)
+      })
+      // this.dealTreeMerge(obj)
+    },
+    //杩斿洖鏁版嵁杞崲鏍戠粨鏋�
+    transformFlightData(data) {
+      const result = [];
+
+      data.forEach(item => {
+        // 鎵惧埌绗竴涓� groundPoint锛屼綔涓轰唬琛�
+        const groundPoint = item.groundPointVo?.[0];
+
+        // 鐢熸垚 children 鑺傜偣
+        const children = groundPoint ? [{
+          id: groundPoint.id,
+          label: groundPoint.targetName,
+          longitude: groundPoint.longitude,
+          latitude: groundPoint.latitude,
+          height: groundPoint.height
+        }] : [];
+
+        // 鐢熸垚绌轰腑鐐�
+        result.push({
+          id: item.id,
+          label: item.targetName,
+          longitude: item.longitude,
+          latitude: item.latitude,
+          height: item.altitude,
+          children
+        });
+      });
+
+      return result;
+    },
+    dealTableTemplate(obj){
+      const targetTableData = this.tableData.find(item => item.id === obj.deviceId)
+      const targetTreeData = this.treeData.find(item => item.id === obj.deviceId)
+      if (targetTableData) {
+        this.$set(targetTableData, 'mode', obj.modelObj.templateName) // 鉁� Vue2 闇�瑕佷娇鐢� $set 浠ョ‘淇濆搷搴斿紡
+      }
+      if (targetTreeData) {
+        this.$set(targetTreeData, 'mode', obj.modelObj.templateName) // 鉁� Vue2 闇�瑕佷娇鐢� $set 浠ョ‘淇濆搷搴斿紡
+      }
+    },
+    dealTreeMerge(obj,data){
+      this.treeData.forEach(item => {
+        if(item.id == obj.deviceId) {
+          // 鏇挎崲绗竴灞傛瘡涓妭鐐圭殑 children
+          this.$set(item, 'children', JSON.parse(JSON.stringify(data)));
+        }
+      });
+    },
+    drawConnectionsWithLabels(devices) {
+      const airPoints = [];
+
+      devices.forEach(device => {
+        if (!Array.isArray(device.children)) return;
+
+        device.children.forEach(airPoint => {
+          // 绌轰腑鐐逛綅缃�
+          const airPos = Cesium.Cartesian3.fromDegrees(
+            airPoint.longitude,
+            airPoint.latitude,
+            airPoint.height
+          );
+
+          // 鉁� 娣诲姞绌轰腑鐐瑰疄浣撳拰 label
+          viewer.entities.add({
+            position: airPos,
+            point: {
+              pixelSize: 6,
+              color: Cesium.Color.YELLOW
+            },
+            label: {
+              text: airPoint.label || '',
+              font: '14px sans-serif',
+              fillColor: Cesium.Color.YELLOW,
+              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+              outlineColor: Cesium.Color.BLACK,
+              outlineWidth: 2,
+              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+              pixelOffset: new Cesium.Cartesian2(0, -12)
+            }
+          });
+
+          airPoints.push(airPos);
+
+          // 閬嶅巻鍦伴潰鐐癸紙瀛愰」锛�
+          if (Array.isArray(airPoint.children)) {
+            airPoint.children.forEach(groundPoint => {
+              const groundPos = Cesium.Cartesian3.fromDegrees(
+                groundPoint.longitude,
+                groundPoint.latitude,
+                groundPoint.height
+              );
+
+              // 鉁� 娣诲姞鍦伴潰鐐瑰疄浣撳拰 label
+              viewer.entities.add({
+                position: groundPos,
+                point: {
+                  pixelSize: 6,
+                  color: Cesium.Color.BLUE
+                },
+                label: {
+                  text: groundPoint.label || '',
+                  font: '14px sans-serif',
+                  fillColor: Cesium.Color.WHITE,
+                  style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+                  outlineColor: Cesium.Color.BLACK,
+                  outlineWidth: 2,
+                  verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+                  pixelOffset: new Cesium.Cartesian2(0, -12)
+                }
+              });
+
+              // 鉁� 钃濊壊铏氱嚎杩炴帴锛氱┖涓偣 鉃� 鍦伴潰鐐�
+              viewer.entities.add({
+                polyline: {
+                  positions: [airPos, groundPos],
+                  width: 2,
+                  material: new Cesium.PolylineDashMaterialProperty({
+                    color: Cesium.Color.BLUE,
+                    dashLength: 8
+                  })
+                }
+              });
+            });
+          }
+        });
+      });
+
+      // 鉁� 榛勮壊瀹炵嚎杩炴帴鎵�鏈夌┖涓偣
+      if (airPoints.length > 1) {
+        viewer.entities.add({
+          polyline: {
+            positions: airPoints,
+            width: 3,
+            material: Cesium.Color.YELLOW
+          }
+        });
+      }
+    },
+    rotateAllPoints(dataList,towerLongitude,towerLatitude,towerhHight) {
+      return dataList.map(item => {
+        console.log(item)
+        console.log(towerLongitude)
+        console.log(towerLatitude)
+        console.log(towerhHight)
+        const groundPoint = Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude, item.height);
+        const towerPoint = Cesium.Cartesian3.fromDegrees(towerLongitude, towerLatitude, towerhHight);
+        let rotationAngle = Cesium.Math.toRadians(135)
+        // 鏃嬭浆鍦伴潰鐐规湰韬紙浼氬彉锛屼絾缁曡嚜韬棆杞笉浼氱Щ鍔級
+        const newGroundPoint = this.rotateAroundPoint( groundPoint,towerPoint, rotationAngle);
+        const newGroundCarto = Cesium.Cartographic.fromCartesian(newGroundPoint);
+        const newGround = {
+          ...item,
+          longitude: Cesium.Math.toDegrees(newGroundCarto.longitude),
+          latitude: Cesium.Math.toDegrees(newGroundCarto.latitude),
+          height: newGroundCarto.height
+        };
+        console.log(newGround)
+        // 澶勭悊瀛愮┖涓偣
+        newGround.children = item.children.map(child => {
+          const airPoint = Cesium.Cartesian3.fromDegrees(child.longitude, child.latitude, child.height);
+          const rotatedAirPoint = this.rotateAroundPoint( airPoint,towerPoint, rotationAngle);
+          const rotatedAirCarto = Cesium.Cartographic.fromCartesian(rotatedAirPoint);
+
+          return {
+            ...child,
+            longitude: Cesium.Math.toDegrees(rotatedAirCarto.longitude),
+            latitude: Cesium.Math.toDegrees(rotatedAirCarto.latitude),
+            height: rotatedAirCarto.height
+          };
+        });
+
+        return newGround;
+      });
+    },
+    //聽璁$畻鐐笰缁曠偣B閫嗘椂閽堟棆杞寚瀹氳搴﹀悗鐨勬柊浣嶇疆
+    //  绌轰腑鐐规垨鑰呭湴闈㈢偣绗涘崱灏斿潗鏍� 濉旂殑绗涘崱灏斿潗鏍�    濉旂殑鏈濆悜鍊�
+    rotateAroundPoint(startPoint,pivotPoint,rotationAngle) {
+      //聽鍒涘缓涓�涓粠B鐐瑰埌鏈湴鍧愭爣绯荤殑杞崲鐭╅樀锛堜笢鏂瑰悜涓篨杞达紝鍖楁柟鍚戜负Y杞达紝鍨傜洿鏂瑰悜涓篫杞达級
+     const transformationMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(pivotPoint);
+      //聽鑾峰彇涓栫晫鍧愭爣绯诲埌鏈湴鍧愭爣绯荤殑杞崲鐭╅樀
+     const inverseTransformationMatrix = Cesium.Matrix4.inverse(transformationMatrix,new Cesium.Matrix4());
+      //聽灏咥鐐硅浆鎹㈠埌灞�閮ㄥ潗鏍囩郴涓�
+     const localStartPoint = Cesium.Matrix4.multiplyByPoint(inverseTransformationMatrix, startPoint,new Cesium.Cartesian3());
+      //聽璁$畻A鐐瑰湪灞�閮ㄥ潗鏍囩郴涓�嗘椂閽堟棆杞寚瀹氳搴﹀悗鐨勬柊浣嶇疆
+     const rotatedX = localStartPoint.x * Math.cos(rotationAngle) + localStartPoint.y * Math.sin(rotationAngle);
+     const rotatedY = localStartPoint.y * Math.cos(rotationAngle) - localStartPoint.x * Math.sin(rotationAngle);
+     const rotatedZ = localStartPoint.z; //聽Z杞村潗鏍囦繚鎸佷笉鍙�
+      //聽灏嗘棆杞悗鐨勫眬閮ㄥ潗鏍囪浆鎹㈠洖涓栫晫鍧愭爣绯�
+     return Cesium.Matrix4.multiplyByPoint(transformationMatrix,聽new聽Cesium.Cartesian3(rotatedX,聽rotatedY,聽rotatedZ),聽new聽Cesium.Cartesian3());
+    },
+    submit(){
+      console.log(this.treeData)
+
+      const routePointList = [];
+
+      this.treeData.forEach(device => {
+        device.children.forEach((airPoint, index) => {
+          routePointList.push({
+            routePointIndex: routePointList.length,
+            longitude: airPoint.longitude,
+            latitude: airPoint.latitude,
+            height: airPoint.height,
+            isStartAndEndPoint: false,
+          });
+        });
+      });
+
+      // 鏍囪棣栧熬涓� true
+      if (routePointList.length > 0) {
+        routePointList[0].isStartAndEndPoint = true;
+        routePointList[routePointList.length - 1].isStartAndEndPoint = true;
+      }
+
+      console.log(routePointList);
+      let params  = {
+        routePointList:routePointList
+      }
+      console.log('鐢熸垚鑸嚎')
+      buildKmz(params).then(res=>{
+        if(res.code == 200) {
+           this.$message({
+              message: '鐢熸垚鑸嚎鎴愬姛',
+              type: 'success'
+            })
+        }
+      })
     }
   }
 }

--
Gitblit v1.9.3