jihongshun
8 天以前 c954cdb51f93585b58b761c2663688c36e6b044f
src/views/system/project/components/addPorjectDialog.vue
@@ -12,9 +12,11 @@
                <div class="chooseModel">
                  <div class="fontJust">设备列表</div>
                   <el-button @click="addDevice"> 新增</el-button>
                   <el-button @click="lineSet"> 航线设置</el-button>
                  <el-table
                    :data="tableData"
                    max-height = '180'
                    :row-key="getRowKeys"
                    style="width: 100%">
                    <el-table-column
                      prop="deviceName"
@@ -45,6 +47,7 @@
                  <div class="fontJust">巡检点目录</div>
                  <el-tree
                    class="filter-tree"
                    node-key="id"
                    :data="treeData"
                    :props="defaultProps"
                    default-expand-all
@@ -64,6 +67,77 @@
    </el-dialog>
     <chooseDeviceDialog v-if="showDevice" @cancel ='cancel' @dealChooseArr="dealChooseArr" ></chooseDeviceDialog>
     <chooseModelDialog v-if="showModel" @cancelModel ='cancelModel' @receiveModel="receiveModel" :deviceId="deviceId"></chooseModelDialog>
     <el-drawer
      title="航线设置"
      :visible.sync="drawer"
      direction="rtl">
      <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
        <el-form-item label="起飞爬升" prop="region">
          <el-select v-model="ruleForm.region" placeholder="请选择起飞爬升">
            <el-option label="垂直" value="垂直"></el-option>
            <el-option label="倾斜" value="倾斜"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="全局航线速度" prop="region">
          <div class="speed-control">
            <el-input-number
              v-model="ruleForm.speed"
              :min="0"
              :max="50"
              :step="1"
              controls-position="both"
              @change="handleChange"
            />
            <span class="unit">m/s</span>
          </div>
        </el-form-item>
        <el-form-item label="起飞速度" prop="fly">
          <div class="speed-control">
            <el-input-number
              v-model="ruleForm.flySpeed"
              :min="0"
              :max="50"
              :step="1"
              controls-position="both"
              @change="handleChange"
            />
            <span class="unit">m/s</span>
          </div>
        </el-form-item>
        <el-form-item label="航点类型" prop="region1">
          <el-select v-model="ruleForm.region1" placeholder="请选择航点类型">
            <el-option label="协调转弯,不过点,提前转弯" value="协调转弯,不过点,提前转弯"></el-option>
            <el-option label="直线飞行,飞行器到点停" value="直线飞行,飞行器到点停"></el-option>
            <el-option label="平滑过点,提前转弯" value="平滑过点,提前转弯"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="飞行器偏航角模式" prop="region2">
          <el-select v-model="ruleForm.region2" placeholder="请选择飞行器偏航角模式">
            <el-option label="沿航线方向" value="沿航线方向"></el-option>
            <el-option label="手动控制" value="手动控制"></el-option>
            <el-option label="锁定当前偏航角" value="锁定当前偏航角"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="航点间云台俯仰角控制模式" prop="region3">
          <el-select v-model="ruleForm.region3" placeholder="请选择航点间云台俯仰角控制模式">
            <el-option label="手动控制" value="手动控制"></el-option>
            <el-option label="依照每个航点设置" value="依照每个航点设置"></el-option>
          </el-select>
        </el-form-item>
         <el-form-item label="完成动作" prop="region4">
          <el-select v-model="ruleForm.region4" placeholder="请选择完成动作">
            <el-option label="自动返航" value="自动返航"></el-option>
            <el-option label="返回航线起始点悬停" value="返回航线起始点悬停"></el-option>
            <el-option label="退出航线模式" value="退出航线模式"></el-option>
            <el-option label="原地降落" value="原地降落"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm('ruleForm')">保存</el-button>
          <el-button @click="resetForm('ruleForm')">取消</el-button>
        </el-form-item>
      </el-form>
    </el-drawer>
  </div>
</template>
<script>
@@ -71,7 +145,8 @@
import chooseDeviceDialog from './chooseDeviceDialog.vue';
import chooseModelDialog from './chooseModelDialog.vue';
import { obtainRealData ,buildKmz} from "@/api/system/template"
let rotationAngle = Cesium.Math.toRadians(0)
let lastConnectPolyline
export  default{
  components: {
    CesiumMap,
@@ -90,7 +165,13 @@
        showDevice:false,
        multipleSelection: [],
        showModel:false,
        deviceId:null
        deviceId:null,
        drawer:false,
        ruleForm:{
          speed:14,
          flySpeed:15
        },
    }
  },
  methods:{
@@ -99,9 +180,9 @@
      this.$emit('close')
    },
    flyToLocal(row){
      console.log(row)
       const position = Cesium.Cartesian3.fromDegrees(row.longitude,row.latitude, row.altitude);
       const position = Cesium.Cartesian3.fromDegrees(row.longitude,row.latitude, row.deviceHeight);
      // rotationAngle  = Cesium.Math.toRadians(row.face)  ||  Cesium.Math.toRadians(0)
      rotationAngle  = Cesium.Math.toRadians(row.face)  ||  Cesium.Math.toRadians(0)
      // 设置模型方向(可选)
      const heading = Cesium.Math.toRadians(row.face); // 朝东南方向
      const pitch = 0;
@@ -178,14 +259,60 @@
      }));
    },
    deleteData(row){
      console.log(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
      const indexTree = this.treeData.findIndex(item => item.id === row.id);
      // 如果找到了,删除该元素
      if (index !== -1) {
        this.treeData.splice(indexTree, 1);
      }
      if(this.treeData?.length >=2 && this.treeData[0]?.children?.length > 0 && this.treeData[1]?.children?.length > 0 ) {
          this.dealAddHeight()
      } else if(this.treeData?.length ==1) {
        this.treeData.map((device,index) => {
          // 确保设备有children数组
          if(index == 0) {
            //第一个数据
            if (device.children && Array.isArray(device.children) && device.children.length > 0) {
                // 获取最后一个空中点
                const lastChild = device.children[device.children.length - 1];
                const firstChild = device.children[0];
                // 深拷贝最后一个元素(包括嵌套的children)
                const newChildJson = JSON.parse(JSON.stringify(lastChild));
                // 深拷贝最一一个元素(包括嵌套的children)
                const firstChildJson = JSON.parse(JSON.stringify(firstChild));
                if(newChildJson && newChildJson.label.includes('加高')){
                  device.children?.pop(newChild);
                }else if(firstChildJson && firstChildJson.label.includes('加高')) {
                    device.children?.shift(firstChildJson);
                }
                // 添加到children数组末尾
            }
          }
        })
      }
      const entitiesToRemove = [];
      viewer.entities.values.forEach(entity => {
        if (entity.id && entity.id.includes(row.id)) {
          entitiesToRemove.push(entity.id);
        }
      });
      entitiesToRemove.forEach(id => {
        viewer.entities.removeById(id);
      });
      this.drawConnectionsWithLabels(this.treeData)
      // console.log(this.tableData)
      console.log(this.treeData)
      // const dealTreeData = this.dealTee()
      // console.log(dealTreeData)
      // this.treeData = dealTreeData
      // this.drawConnectionsWithLabels(this.treeData)
    },
    chooseModel(row){
      this.deviceId = row.id
@@ -196,7 +323,6 @@
    },
    receiveModel(obj){
      //deal逻辑
      console.log(obj)
      let flightTemplateId =obj.modelObj.id
      let deviceId = obj.deviceId
      this.dealTableTemplate(obj)
@@ -206,13 +332,87 @@
        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.rotateAllPoints(this.treeData || [],res.data.longitude,res.data.latitude,res.data.height)
        console.log(this.treeData)
        if(this.treeData?.length >=2 && this.treeData[0]?.children?.length > 0 && this.treeData[1]?.children?.length > 0 ) {
            this.dealAddHeight()
        }
        console.log(this.treeData)
        this.drawConnectionsWithLabels(this.treeData)
      })
      // this.dealTreeMerge(obj)
    },
    dealAddHeight(){
      let currentLength = this.treeData.filter(item=>item.children)?.length || 0
      console.log(this.treeData)
      console.log(currentLength)
      this.treeData.map((device,index) => {
          // 确保设备有children数组
          if(index == 0) {
            //第一个数据
            if (device.children && Array.isArray(device.children) && device.children.length > 0) {
                // 获取最后一个空中点
                const lastChild = device.children[device.children.length - 1];
                // 深拷贝最后一个元素(包括嵌套的children)
                const newChild = JSON.parse(JSON.stringify(lastChild));
                if(newChild.label.includes('加高')) {
                }else {
                  newChild.label = newChild.label + '-加高'
                  // 高度增加20
                  // newChild.height += 20;
                  //塔高 - 高度  + 往上飞多少米
                  newChild.height += (device.ardTowerModel?.modelHeight  - newChild.height +  20) ;
                  console.log('push11111111111111')
                  // 添加到children数组末尾
                  device.children.push(newChild);
                }
            }
          }
          else if(index == currentLength -1) {
            if (device.children && Array.isArray(device.children) && device.children.length > 0) {
                // 获取最后一个空中点
                const lastChild = device.children[0];
                // 深拷贝最一一个元素(包括嵌套的children)
                const newChild = JSON.parse(JSON.stringify(lastChild));
                if(newChild.label.includes('加高')) {
                }else {
                  newChild.label = newChild.label + '-加高第一个点'
                  newChild.height += (device.ardTowerModel?.modelHeight  - newChild.height +  20) ;
                  // 添加到children数组末尾
                  device.children.unshift(newChild);
                }
            }
          } else {
            if (device.children && Array.isArray(device.children) && device.children.length > 0) {
                // 获取最后一个空中点
                const firstChild = device.children[0];
                const lastChild = device.children[device.children.length - 1];
                // 深拷贝最一一个元素(包括嵌套的children)
                const newFirstChild = JSON.parse(JSON.stringify(firstChild));
                const newLastChildChild = JSON.parse(JSON.stringify(lastChild));
                //高度增加20
                if(newFirstChild.label.includes('加高')) {
                }else {
                    newFirstChild.label = newFirstChild.label + '-加高'
                    newFirstChild.height += (device.ardTowerModel?.modelHeight  - newFirstChild.height +  20) ;
                    device.children.unshift(firstChild);
                }
                if(newLastChildChild.label.includes('加高')) {
                }else {
                    newLastChildChild.label = newLastChildChild.label + '-加高'
                    newLastChildChild.height += (device.ardTowerModel?.modelHeight  - newLastChildChild.height +  20) ;
                    device.children.push(newLastChildChild);
                }
            }
          }
      })
    },
    //返回数据转换树结构
    transformFlightData(data) {
      console.log(data)
      const result = [];
      data.forEach(item => {
@@ -259,12 +459,29 @@
        }
      });
    },
    generateId() {
      return 'id_' + Math.random().toString(36).substring(2, 10);
    },
    drawConnectionsWithLabels(devices) {
      const airPoints = [];
      if(lastConnectPolyline) {
        viewer.entities.remove(lastConnectPolyline)
        lastConnectPolyline = null
      }
        // 直接操作EntityCollection(推荐)
      const entitiesToRemove = [];
      viewer.entities.values.forEach(entity => {
        if (entity.id && entity.id.includes(this.deviceId)) {
          entitiesToRemove.push(entity.id);
        }
      });
      entitiesToRemove.forEach(id => {
        viewer.entities.removeById(id);
      });
      const airPoints = [];
      console.log(devices)
      devices.forEach(device => {
        if (!Array.isArray(device.children)) return;
        device.children.forEach(airPoint => {
          // 空中点位置
          const airPos = Cesium.Cartesian3.fromDegrees(
@@ -276,6 +493,7 @@
          // ✅ 添加空中点实体和 label
          viewer.entities.add({
            position: airPos,
            id:device.id +'airpoint' + this.generateId(),
            point: {
              pixelSize: 6,
              color: Cesium.Color.YELLOW
@@ -305,6 +523,7 @@
              // ✅ 添加地面点实体和 label
              viewer.entities.add({
                id:device.id +'groundpoint' + this.generateId(),
                position: groundPos,
                point: {
                  pixelSize: 6,
@@ -324,6 +543,7 @@
              // ✅ 蓝色虚线连接:空中点 ➜ 地面点
              viewer.entities.add({
                id:device.id +'polyline' + this.generateId(),
                polyline: {
                  positions: [airPos, groundPos],
                  width: 2,
@@ -337,10 +557,10 @@
          }
        });
      });
      console.log(airPoints)
      // ✅ 黄色实线连接所有空中点
      if (airPoints.length > 1) {
        viewer.entities.add({
        lastConnectPolyline = viewer.entities.add({
          polyline: {
            positions: airPoints,
            width: 3,
@@ -351,43 +571,44 @@
    },
    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
        if(!item.isDeal) {
          const towerPoint = Cesium.Cartesian3.fromDegrees(towerLongitude, towerLatitude, towerhHight);
          const newGround = {
            ...item,
          };
        });
        return newGround;
          if(item.id == this.deviceId ){
            item.isDeal = true
          }
          // 处理子空中点
          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);
            child.longitude = Cesium.Math.toDegrees(rotatedAirCarto.longitude)
            child.latitude = Cesium.Math.toDegrees(rotatedAirCarto.latitude)
            child.height = rotatedAirCarto.height
            child.children = child.children?.map(sonChild => {
              const groundPoint = Cesium.Cartesian3.fromDegrees(sonChild.longitude, sonChild.latitude, sonChild.height);
              const newGroundPoint = this.rotateAroundPoint( groundPoint,towerPoint, rotationAngle);
              const newGroundCarto = Cesium.Cartographic.fromCartesian(newGroundPoint);
              return {
                ...sonChild,
                longitude: Cesium.Math.toDegrees(newGroundCarto.longitude),
                latitude: Cesium.Math.toDegrees(newGroundCarto.latitude),
                height: newGroundCarto.height
              };
            });
          });
          console.log(newGround.children)
          return newGround;
        }
      });
    },
    // 计算点A绕点B逆时针旋转指定角度后的新位置
    //  空中点或者地面点笛卡尔坐标 塔的笛卡尔坐标    塔的朝向值
    rotateAroundPoint(startPoint,pivotPoint,rotationAngle) {
      console.log(rotationAngle)
      // 创建一个从B点到本地坐标系的转换矩阵(东方向为X轴,北方向为Y轴,垂直方向为Z轴)
     const transformationMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(pivotPoint);
      // 获取世界坐标系到本地坐标系的转换矩阵
@@ -401,6 +622,10 @@
      // 将旋转后的局部坐标转换回世界坐标系
     return Cesium.Matrix4.multiplyByPoint(transformationMatrix, new Cesium.Cartesian3(rotatedX, rotatedY, rotatedZ), new Cesium.Cartesian3());
    },
    getRowKeys(row){
      console.log(row)
      return row.id +this.generateId()
    },
    submit(){
      console.log(this.treeData)
@@ -412,7 +637,13 @@
            routePointIndex: routePointList.length,
            longitude: airPoint.longitude,
            latitude: airPoint.latitude,
            height: airPoint.height,
            isStartAndEndPoint: false,
            coordinatePointReq: {
                height: airPoint.children[0].height,
                latitude:airPoint.children[0].latitude,
                longitude: airPoint.children[0].longitude
              }
          });
        });
      });
@@ -436,6 +667,9 @@
            })
        }
      })
    },
    lineSet(){
      this.drawer =true
    }
  }
}