GuLiMmo
2024-03-06 52a426373c619415f876952b0de04af82564dd96
update:航线全局设置编辑、新增航点、事件编辑等

航线全局设置编辑(并体现在地图上)、新增航点、事件编辑等
6 files modified
3 files added
752 ■■■■ changed files
.prettierrc 21 ●●●●● patch | view | raw | blame | history
src/pages/page-web/projects/components/route-edit/components/enums.ts 8 ●●●●● patch | view | raw | blame | history
src/pages/page-web/projects/components/route-edit/components/setting.vue 344 ●●●● patch | view | raw | blame | history
src/pages/page-web/projects/components/route-edit/index.vue 11 ●●●● patch | view | raw | blame | history
src/pages/page-web/projects/components/route-edit/types/index.ts 28 ●●●●● patch | view | raw | blame | history
src/utils/cesium/kmz.ts 46 ●●●●● patch | view | raw | blame | history
src/utils/cesium/types/kml.ts 129 ●●●●● patch | view | raw | blame | history
src/utils/cesium/use-kmz-tsa.ts 57 ●●●● patch | view | raw | blame | history
src/utils/cesium/use-map-draw.ts 108 ●●●●● patch | view | raw | blame | history
.prettierrc
New file
@@ -0,0 +1,21 @@
{
    "arrowParens": "always",
    "bracketSameLine": true,
    "bracketSpacing": true,
    "semi": false,
    "experimentalTernaries": false,
    "singleQuote": true,
    "jsxSingleQuote": false,
    "quoteProps": "as-needed",
    "trailingComma": "all",
    "singleAttributePerLine": false,
    "htmlWhitespaceSensitivity": "css",
    "vueIndentScriptAndStyle": false,
    "proseWrap": "preserve",
    "insertPragma": false,
    "printWidth": 120,
    "requirePragma": false,
    "tabWidth": 2,
    "useTabs": false,
    "embeddedLanguageFormatting": "auto"
}
src/pages/page-web/projects/components/route-edit/components/enums.ts
@@ -5,4 +5,12 @@
                  安全起飞高度:是相对起飞点的高度值。\n
                  飞行器起飞后,会先上升至"安全起飞高度",再飞向航线起始点
                  `,
  EGM96 = '绝对高度:航点高度值相对于海拔面/椭球面高度保持不变。',
  relativeToStartPoint = '相对起飞点高度(ALT):航点高度值相对起飞点的高度保持不变。'
}
export enum heightModeEnums {
  'WGS84',
  'relativeToStartPoint',
  'realTimeFollowSurface',
}
src/pages/page-web/projects/components/route-edit/components/setting.vue
@@ -1,21 +1,27 @@
<template>
  <div class="setting">
    <a-popover
      placement="bottom"
      trigger="click"
      :getPopupContainer="(triggerNode: any) => triggerNode.parentNode">
    <a-popover placement="bottom" trigger="click" :getPopupContainer="(triggerNode: any) => triggerNode.parentNode">
      <template #content>
        <div class="setting-content">
          <div class="start-point common">
            <div class="title">起飞点</div>
            <div class="value">{{ missionConfigSetting.takeOffRefPoint ? '已设置' : '未设置' }}</div>
          </div>
          <div class="photo-setting common">
            <div class="title">拍照设置</div>
            <ul class="select-box">
              <li class="select-item">广角照片</li>
              <li class="select-item">变焦照片</li>
              <li
                class="select-item"
                :style="{
                  '--settingColor': folderSetting.payloadParam.imageFormat.includes(item.value) ? '#409eff' : '#3c3c3c',
                }"
                v-for="item in photoSetting"
                :key="item.value"
                @click="selectPhotoSetting(item.value)">
                {{ item.title }}照片
              </li>
            </ul>
            <div class="auto-low-light">
            <!-- <div class="auto-low-light">
              <div class="title">自动低光</div>
              <a-tooltip
                placement="right"
@@ -25,17 +31,13 @@
                  checkedValue="lowLightSmartShooting"
                  unCheckedValue="normalPhoto" />
              </a-tooltip>
            </div>
            </div> -->
          </div>
          <!-- 爬升 -->
          <div class="climb-mode common">
            <a-tooltip
              placement="right"
              :title="tipDescriptionEnums.climbModeTip">
            <a-tooltip placement="right" :title="tipDescriptionEnums.climbModeTip">
              <div class="mode-box">
                <a-radio-group
                  v-model:value="setting.flyToWaylineMode"
                  button-style="solid">
                <a-radio-group v-model:value="missionConfigSetting.flyToWaylineMode" button-style="solid">
                  <a-radio-button value="safely">垂直爬升</a-radio-button>
                  <a-radio-button value="pointToPoint">倾斜爬升</a-radio-button>
                </a-radio-group>
@@ -45,59 +47,67 @@
                  <img :src="climbImage" alt="climb-img" />
                </div>
                <ul class="parameter-btn">
                  <li>+100</li>
                  <li>+10</li>
                  <li @click="numberControls(true, 100, 'takeOffSecurityHeight')">+100</li>
                  <li @click="numberControls(true, 10, 'takeOffSecurityHeight')">+10</li>
                  <li>
                    <span>{{ setting.takeOffSecurityHeight }}</span
                    <span>{{ missionConfigSetting.takeOffSecurityHeight }}</span
                    >m
                  </li>
                  <li>-100</li>
                  <li>-10</li>
                  <li @click="numberControls(false, 100, 'takeOffSecurityHeight')">-100</li>
                  <li @click="numberControls(false, 10, 'takeOffSecurityHeight')">-10</li>
                </ul>
              </div>
            </a-tooltip>
          </div>
          <!-- 高度模式 -->
          <div class="height-mode common">
            <div class="title">航线高度模式</div>
            <div class="mode-box">
              <a-radio-group
                v-model:value="setting.executeHeightMode"
                button-style="solid">
                <a-radio-button value="WGS84">绝对高度</a-radio-button>
                <a-radio-button value="relativeToStartPoint"
                  >相对起飞高度</a-radio-button
                >
                <a-radio-button value="realTimeFollowSurface"
                  >相对地面高度</a-radio-button
                >
              </a-radio-group>
            </div>
            <div class="parameter-tool">
              <div class="example-img">
                <img :src="imgs[0]" alt="height-img" />
            <a-tooltip
              placement="right"
              :title="tipDescriptionEnums[folderSetting.waylineCoordinateSysParam.heightMode]">
              <div class="title">航线高度模式</div>
              <div class="mode-box">
                <a-radio-group v-model:value="folderSetting.waylineCoordinateSysParam.heightMode" button-style="solid">
                  <a-radio-button v-for="item in heightModeSetting" :key="item.value" :value="item.value">{{
                    item.title
                  }}</a-radio-button>
                </a-radio-group>
              </div>
              <div class="parameter-btn">
                <li>+100</li>
                <li>+10</li>
                <li>
                  <span>{{ setting.executeHeight }}</span> m
                </li>
                <li>-100</li>
                <li>-10</li>
              <div class="parameter-tool">
                <div class="example-img">
                  <img
                    :src="
                      folderSetting.waylineCoordinateSysParam.heightMode === heightModeSetting[0].value
                        ? heightModeSetting[0].img
                        : heightModeSetting[1].img
                    "
                    alt="height-img" />
                </div>
                <div class="parameter-btn">
                  <li @click="numberControls(true, 100, 'globalHeight')">+100</li>
                  <li @click="numberControls(true, 10, 'globalHeight')">+10</li>
                  <li>
                    <span>{{ Number(folderSetting.globalHeight) }}</span> m
                  </li>
                  <li @click="numberControls(false, 100, 'globalHeight')">-100</li>
                  <li @click="numberControls(false, 10, 'globalHeight')">-10</li>
                </div>
              </div>
            </div>
            </a-tooltip>
          </div>
          <!-- 航线速度 -->
          <div class="speed-setting common">
            <div class="title">全局航线速度</div>
            <div class="speed-box">
              <div class="subtract">-</div>
              <div class="subtract" @click="numberControls(false, 1, 'autoFlightSpeed')">-</div>
              <div class="text">
                <a-input-number :min="1" :max="15" class="value" v-model:value="setting.autoFlightSpeed">30</a-input-number>
                <a-input-number
                  :min="1"
                  :max="15"
                  class="value"
                  v-model:value="folderSetting.autoFlightSpeed"></a-input-number>
                m / s
              </div>
              <div class="add">+</div>
              <div class="add" @click="numberControls(true, 1, 'autoFlightSpeed')">+</div>
            </div>
          </div>
        </div>
@@ -108,8 +118,24 @@
</template>
<script setup lang="ts">
import { min } from 'lodash'
import { reactive, defineProps } from 'vue'
import { tipDescriptionEnums } from './enums'
import useKmzTsa, { kmlStr } from '/@/utils/cesium/use-kmz-tsa'
import useMapDraw from '/@/utils/cesium/use-map-draw'
import { getKmlParams } from '/@/utils/cesium/kmz'
import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
import type { missionConfig, payloadParam as payloadParamConfig, Folder } from '/@/utils/cesium/types/kml'
const { appContext }: any = getCurrentInstance()
const global = appContext.config.globalProperties
const mapDraw = useMapDraw('', '', '', global)
const { removeAllDataSource, removeAllPoint } = cesiumOperation()
const kmzUtils = useKmzTsa()
const props = defineProps({
  loadCompleted: Boolean,
})
const getResource = (name: string) => {
  return new URL(`/src/assets/icons/${name}`, import.meta.url).href
@@ -119,17 +145,178 @@
}
const climbImage = getSvgResource('climb.svg')
const imgs = [getSvgResource('xddm.svg')]
const imgs = []
const setting = reactive({
const missionConfigSetting = reactive<missionConfig | any>({
  flyToWaylineMode: 'safely',
  takeOffSecurityHeight: 80,
  executeHeightMode: 'WGS84',
  executeHeight: 80,
  // normal: normalPhoto row-light: lowLightSmartShooting
  orientedPhotoMode: 'normalPhoto',
  autoFlightSpeed: 10
  // 航线结束动作
  finishAction: 'goHome',
  // 失控是否继续执行航线
  exitOnRCLost: 'goContinue',
  // 失控动作
  executeRCLostAction: 'goBack',
  // 安全起飞高度
  takeOffSecurityHeight: 20,
  // 全局航线速度
  globalTransitionalSpeed: 10,
  // 参考起飞点
  takeOffRefPoint: '',
  // 参考起飞点海拔高度
  takeOffRefPointAGLHeight: 0,
  // 全局返航高度
  globalRTHHeight: 100,
  droneInfo: {
    droneEnumValue: 67,
    droneSubEnumValue: 0,
  },
  payloadInfo: {
    payloadEnumValue: 52,
    payloadSubEnumValue: 1,
    payloadPositionIndex: 0,
  },
})
// 拍照设置
const photoSetting = reactive([
  { title: '广角', value: 'wide' },
  { title: '变焦', value: 'zoom' },
  { title: '红外', value: 'ir' },
])
// 高度模式
const heightModeSetting = reactive([
  {
    title: '绝对高度',
    value: 'EGM96',
    img: getSvgResource('jdgd.svg'),
  },
  {
    title: '相对起飞高度',
    value: 'relativeToStartPoint',
    img: getSvgResource('xdqfd.svg'),
  },
])
// folder设置
const folderSetting = reactive<Folder | any>({
  templateType: 'waypoint',
  templateId: 0,
  waylineCoordinateSysParam: {
    coordinateMode: 'WGS84',
    heightMode: 'EGM96',
  },
  autoFlightSpeed: 10,
  globalHeight: 100,
  payloadParam: {
    payloadPositionIndex: 0,
    imageFormat: '',
  },
  caliFlightEnable: 0,
  gimbalPitchMode: 'manual',
})
// 计算
const numberControls = (isAdd: boolean, computeVal: number, key: string) => {
  if (isAdd) {
    if (missionConfigSetting[key]) {
      missionConfigSetting[key] += computeVal
    } else {
      folderSetting[key] += computeVal
    }
  } else {
    if (missionConfigSetting[key]) {
      missionConfigSetting[key] -= computeVal
    } else {
      folderSetting[key] -= computeVal
    }
  }
  if (key === 'globalHeight') {
    const entities = mapDraw.kmlEntities.value
    removeAllDataSource()
    removeAllPoint()
    mapDraw.drawWayline(entities, kmlStr.value)
  }
}
// 获取机场默认值
watch(
  () => props.loadCompleted,
  (val) => {
    if (val) {
      getDefaultValue(missionConfigSetting)
      getDefaultValue(folderSetting)
    }
  },
)
const getDefaultValue = (setting: any) => {
  Object.keys(setting).forEach((key: string) => {
    const param: RegExpMatchArray | any = getKmlParams(kmlStr.value, true, {
      name: key,
      findRegx: '([\\s\\S]*?)',
    })
    if (Object.prototype.toString.call(setting[key]) === '[object Object]') {
      const value: RegExpMatchArray | any = getKmlParams(param[0], true, {
        name: key,
        findRegx: '([\\s\\S]*?)',
      })
      Object.keys(setting[key]).forEach((v) => {
        const keyValue: RegExpMatchArray | any = getKmlParams(value[1], true, {
          name: v,
          findRegx: '([\\s\\S]*?)',
        })
        if (!Number(keyValue[1])) {
          setting[key][v] = keyValue[1]
        } else {
          setting[key][v] = Number(keyValue[1])
        }
      })
    } else {
      if (!Number(param[1])) {
        setting[key] = param[1]
      } else {
        setting[key] = Number(param[1])
      }
    }
  })
  return setting
}
// 全局设置写入kmz文件
watch(
  () => missionConfigSetting,
  (settingVal) => {
    if (!props.loadCompleted) return
    kmzUtils.edit(settingVal, 'missionConfig', true)
  },
  {
    deep: true,
  },
)
// folder设置写入kmz文件
watch(
  () => folderSetting,
  (newVal) => {
    if (!props.loadCompleted) return
    kmzUtils.edit(newVal, 'Folder', true)
  },
  {
    deep: true,
  },
)
// 拍照设置
const selectPhotoSetting = (value: string) => {
  const arr: string[] = folderSetting.payloadParam.imageFormat.split(',')
  const index: number = arr.findIndex((item) => item === value)
  if (index !== -1) {
    arr.splice(index, 1)
  } else {
    arr.push(value)
  }
  folderSetting.payloadParam.imageFormat = arr.join(',')
}
</script>
<style lang="scss" scoped>
@@ -139,51 +326,71 @@
    max-height: 80vh;
    overflow-y: auto;
    color: #fff;
    .common {
      background-color: #232323;
      border-radius: 10px;
      padding: 15px;
      margin-bottom: 16px;
      .title {
        font-weight: bold;
      }
      &:last-child {
        margin: 0;
      }
    }
    .start-point {
      display: flex;
      justify-content: flex-start;
      .value {
        margin-left: auto;
        color: #409eff;
      }
    }
    .photo-setting {
      .select-box {
        padding: 0;
        display: flex;
        margin-top: 10px;
        li {
          list-style-type: none;
          padding: 3px 15px;
          margin-left: 10px;
          background-color: #409eff;
          background-color: var(--settingColor);
          border-radius: 9999px;
          font-weight: bold;
          cursor: pointer;
          &:first-child {
            margin: 0;
          }
        }
      }
      .auto-low-light {
        display: flex;
        .title {
          font-weight: bold;
          margin-right: auto;
        }
      }
    }
    .height-mode,
    .climb-mode {
      .mode-box {
        margin-top: 10px;
        :deep() {
          .ant-radio-group {
            display: flex;
            .ant-radio-button-wrapper {
              flex: 1;
              text-align: center;
@@ -192,9 +399,11 @@
              color: #fff;
              font-weight: bold;
              border: 0;
              &::before {
                background-color: #101010;
              }
              &-checked {
                background-color: #409eff !important;
              }
@@ -202,19 +411,23 @@
          }
        }
      }
      .parameter-tool {
        margin-top: 15px;
        display: flex;
        .example-img {
          flex: 3;
          flex-shrink: 0;
          display: flex;
          justify-content: center;
          align-items: center;
          img {
            width: 100%;
          }
        }
        .parameter-btn {
          flex: 1;
          padding: 0;
@@ -223,6 +436,7 @@
          display: flex;
          flex-direction: column;
          align-items: center;
          li {
            width: 50px;
            border-radius: 3px;
@@ -234,10 +448,12 @@
            text-align: center;
            font-weight: bold;
            transition: all 0.3s ease-in-out;
            &:nth-child(3) {
              width: 100%;
              background-color: transparent;
              cursor: auto;
              span {
                color: #409eff;
                font-size: 23px;
@@ -245,6 +461,7 @@
                margin-right: 5px;
              }
            }
            &:not(:nth-child(3)) {
              &:hover {
                background-color: #5d5f61;
@@ -254,24 +471,29 @@
        }
      }
    }
    .speed-setting {
      .speed-box {
        margin-top: 10px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        .text {
          font-weight: bolder;
          .value {
            color: #409eff;
            width: 60px;
            font-size: 30px;
            background-color: transparent;
            border: 0;
            :deep() {
              .ant-input-number-handler-wrap {
                display: none;
              }
              .ant-input-number-input-wrap {
                input {
                  font-weight: bolder;
@@ -280,6 +502,7 @@
            }
          }
        }
        .subtract,
        .add {
          width: 32px;
@@ -291,6 +514,7 @@
          background-color: #3c3c3c;
          border-radius: 3px;
          cursor: pointer;
          &:hover {
            background-color: #5d5f61;
          }
@@ -306,12 +530,15 @@
    .ant-popover-inner {
      background-color: #101010;
    }
    .ant-popover-arrow {
      border-top-color: #101010 !important;
      border-left-color: #101010 !important;
    }
    .ant-popover-inner {
      border-radius: 15px;
      .ant-popover-inner-content {
        padding: 16px;
      }
@@ -319,3 +546,4 @@
  }
}
</style>
../../../../../../utils/cesium/types/kml
src/pages/page-web/projects/components/route-edit/index.vue
@@ -10,7 +10,7 @@
      <div class="save-button">
        <SaveOutlined />
      </div>
      <setting>
      <setting v-model:loadCompleted="loadCompleted">
        <template #show>
          <a-button type="text" class="setting-btn">
            <div class="router-setting">
@@ -66,6 +66,7 @@
import _ from 'lodash'
import * as Cesium from 'cesium'
import setting from './components/setting.vue'
import useKmzTsa from '/@/utils/cesium/use-kmz-tsa'
import { ref, reactive, defineEmits, defineProps, watch, onMounted } from 'vue'
import { ArrowLeftOutlined, CaretDownOutlined, SaveOutlined } from '@ant-design/icons-vue'
import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
@@ -129,6 +130,8 @@
// 样式
const kmlEntities = ref<Cesium.Entity[]>([])
const loadCompleted = ref<boolean>(false)
const initDrawRoute = () => {
  const options = {
    camera: global.$viewer.scene.camera,
@@ -148,12 +151,16 @@
        waylineDetails: details,
        waylinePointsEvent,
        kmlEntities: entities,
        clearWaylineData
      } = mapDraw
      clearWaylineData()
      drawWayline()
      useKmzTsa().init(filePath.value).then(kmlRes => {
        loadCompleted.value = true
      })
      waylineDetails.value = details
      tragetPointArr.value = waylinePointsEvent.value
      kmlEntities.value = entities.value
      if (!mouseRightClickEvent) {
        // 添加右键事件
        addMapPointEvent()
src/pages/page-web/projects/components/route-edit/types/index.ts
New file
@@ -0,0 +1,28 @@
export interface globalSetting {
  flyToWaylineMode: string
  // 航线结束动作
  finishAction: string
  // 失控是否继续执行航线
  exitOnRCLost: string
  // 失控动作
  executeRCLostAction: string
  // 安全起飞高度
  takeOffSecurityHeight: 20
  // 全局航线速度
  globalTransitionalSpeed: number
  // 参考起飞点
  takeOffRefPoint: string
  // 参考起飞点海拔高度
  takeOffRefPointAGLHeight: number
  // 全局返航高度
  globalRTHHeight: number
}
export interface waylineSettingTypes {
    // 航线高度模式
  executeHeightMode: string,
  executeHeight: number,
  // normal: normalPhoto row-light: lowLightSmartShooting
  // 拍照模式
  orientedPhotoMode: number
}
src/utils/cesium/kmz.ts
@@ -22,31 +22,47 @@
export const getKmlParams = (
  source: string,
  isWpml: boolean,
  params: { name: string; findRegx: string; mode?: string },
  params: { name: string | undefined; findRegx: string; mode?: string },
) => {
  let regx = null
  if (isWpml) {
    if (params.mode) {
      regx = new RegExp(
        `<wpml:${params.name}>${params.findRegx}<\\/wpml:${params.name}>`,
        params.mode,
      )
      regx = new RegExp(`<wpml:${params.name}>${params.findRegx}<\\/wpml:${params.name}>`, params.mode)
    } else {
      regx = new RegExp(
        `<wpml:${params.name}>${params.findRegx}<\\/wpml:${params.name}>`,
      )
      regx = new RegExp(`<wpml:${params.name}>${params.findRegx}<\\/wpml:${params.name}>`)
    }
  } else {
    if (params.mode) {
      regx = new RegExp(
        `<${params.name}>${params.findRegx}<\\/${params.name}>`,
        params.mode,
      )
      regx = new RegExp(`<${params.name}>${params.findRegx}<\\/${params.name}>`, params.mode)
    } else {
      regx = new RegExp(
        `<${params.name}>${params.findRegx}<\\/${params.name}>`,
      )
      regx = new RegExp(`<${params.name}>${params.findRegx}<\\/${params.name}>`)
    }
  }
  return source?.match(regx)
}
export const generateKmlFormat = (settingParmas: any) => {
  let paramGroup = ''
  Object.keys(settingParmas).forEach((key: string) => {
    if (Object.prototype.toString.call(settingParmas[key]) === '[object Object]') {
      let parmaStr = ''
      Object.keys(settingParmas[key]).forEach((v) => {
        parmaStr += `<wpml:${v}>${settingParmas[key][v]}</wpml:${v}>`
      })
      paramGroup += `<wpml:${key}>${parmaStr}</wpml:${key}>`
    } else {
      paramGroup += `<wpml:${key}>${settingParmas[key]}</wpml:${key}>`
    }
  })
  return paramGroup
}
export const insertChar = (str: string, index: number, char: string) => {
  if (index > str.length) {
    return str + char
  } else if (index < 0) {
    return char + str
  } else {
    return str.slice(0, index) + char + str.slice(index)
  }
}
src/utils/cesium/types/kml.ts
New file
@@ -0,0 +1,129 @@
export interface droneInfo {
  // 飞行器机型主类型
  droneEnumValue: string | number
  // 飞行器机型子类型
  droneSubEnumValue: string | number
}
export interface payloadInfo {
  payloadEnumValue: string | number
  payloadSubEnumValue: string | number
  payloadPositionIndex: string | number
}
export interface missionConfig {
  // 飞向首航点模式
  flyToWaylineMode: string
  // 航线结束动作
  finishAction: string
  // 失控是否继续执行航线
  exitOnRCLost: string
  // 失控动作类型
  executeRCLostAction?: string
  // 安全起飞高度
  takeOffSecurityHeight: string | number
  // 全局航线过渡速度
  globalTransitionalSpeed: string | number
  // 全局返航高度
  globalRTHHeight: string | number
  // 参考起飞点
  takeOffRefPoint?: string
  // 参考起飞点海拔高度
  takeOffRefPointAGLHeight?: string | number
  // 飞行器机型信息
  droneInfo: droneInfo
  // 负载机型信息
  payloadInfo: payloadInfo
}
export interface Placemark {
  // 是否开启标定飞行
  caliFlightEnable?: boolean | number
  // 是否开启高程优化
  elevationOptimizeEnable: boolean | number
  // 是否开启智能摆拍
  smartObliqueEnable: boolean | number
  // 智能摆拍拍摄俯仰角
  smartObliqueGimbalPitch: number
  // 拍照模式(定时或定距
  shootType: string
  // 航线方向
  direction: string | number
  // 测区外扩距离
  margin?: number
  //   重叠率参数
  overlap?: any
  // 全局航线高度(椭球高)
  ellipsoidHeight: number
  // 全局航线高度
  height: number
  // 测区多边形
  Polygon?: any
  // 建图航拍飞行器朝向参数
  mappingHeadingParam?: any
  // 云台俯仰角模式
  gimbalPitchMode?: string
  // 云台俯仰角度
  gimbalPitchAngle?: any
}
export interface payloadParam {
  // 负载挂载位置
  payloadPositionIndex: number
  // 负载对焦模式
  focusMode?: string
  // 负载测光模式
  meteringMode?: string
  // 是否开启畸变矫正
  dewarpingEnable?: boolean | number
  // 激光雷达回波模式
  returnMode?: string
  // 负载采样率
  samplingRate?: number
  // 负载扫描模式
  scanningMode?: number
  // 真彩上色
  modelColoringEnable?: boolean | number
  // 图片格式列表
  imageFormat: string
}
export interface waylineCoordinateSysParam {
  // 经纬度坐标系
  coordinateMode?: string
  // 航点高程参考平面
  heightMode?: string
  // 经纬度与高度数据源
  positioningType?: string
  // 飞行器离被摄面高度(相对地面高)
  globalShootHeight?: string
  // 是否开启仿地飞行
  surfaceFollowModeEnable?: boolean | number
  // 仿地飞行离地高度(相对地面高)
  surfaceRelativeHeight?: number
}
export interface Folder {
  // 预定义模板类型
  templateType: string
  //   模板ID
  templateId: number
  //   全局航线飞行速度
  autoFlightSpeed: number
  //   坐标系参数
  waylineCoordinateSysParam?: waylineCoordinateSysParam
  //   负载设置
  payloadParam?: payloadParam
  //   全局航点类型(全局航点转弯模式)
  globalWaypointTurnMode?: string
  //   全局航段轨迹是否尽量贴合直线
  globalUseStraightLine?: boolean | number
  //   云台俯仰角控制模式
  gimbalPitchMode?: string
  //   全局航线高度(相对起飞点高度)
  globalHeight?: number
  //   全局偏航角模式参数
  globalWaypointHeadingParam?: number
  //   航点信息(包括航点经纬度和高度等)
  Placemark?: Placemark
}
src/utils/cesium/use-kmz-tsa.ts
@@ -1,16 +1,17 @@
import { ref } from 'vue'
import { analyzeKmzFile, getKmlParams } from '/@/utils/cesium/kmz'
import { analyzeKmzFile, getKmlParams, generateKmlFormat } from '/@/utils/cesium/kmz'
const useKMLTsa = () => {
  const kmzStr = ref('')
const kmlStr = ref('')
  const init = async (fileUrl: string, fileContent ?: string) => {
const useKmzTsa = () => {
  const init = async (fileUrl: string, fileContent?: string) => {
    const kmzRes: string = await analyzeKmzFile(fileUrl)
    if (fileContent) {
      kmzStr.value = fileContent
      kmlStr.value = fileContent
      return false
    }
    kmzStr.value = kmzRes
    kmlStr.value = kmzRes
    return kmzRes
  }
  const create = () => {
@@ -29,22 +30,54 @@
      </Document>
    </kml>
    `
    kmzStr.value = str
    kmlStr.value = str
  }
  const write = () => {}
  const write = (settingParmas: any = {}, name?: string, isWpml?: boolean = false) => {}
  const del = () => {}
  const del = () => {
  }
  const edit = () => {}
  const edit = (settingParmas: any = {}, keyName?: string, isKeyWpml: boolean = false) => {
    Object.keys(settingParmas).forEach((key: string) => {
      const regxVal: any = getKmlParams(kmlStr.value, true, {
        name: key,
        findRegx: '([\\s\\S]*?)',
      })
      const str = regxVal[1]
      if (str) {
        if (key === 'globalHeight') {
          const regxVal: any = getKmlParams(kmlStr.value, true, {
            name: 'height',
            findRegx: '([\\s\\S]*?)',
            mode: 'g'
          })
          regxVal.forEach((heightStr: string) => {
            const rstr = generateKmlFormat({ height: settingParmas[key] })
            kmlStr.value = kmlStr.value.replace(heightStr, rstr)
          })
        }
        const replaceStr = generateKmlFormat({ [key]: settingParmas[key] })
        kmlStr.value = kmlStr.value.replace(regxVal[0], replaceStr)
      } else {
        console.warn('没有找到对应的属性')
      }
    })
  }
  const save = () => {}
  const save = () => {
    console.log(kmlStr.value)
  }
  return {
    init,
    create,
    write,
    del,
    edit,
    save
    save,
  }
}
export { kmlStr }
export default useKmzTsa
src/utils/cesium/use-map-draw.ts
@@ -86,6 +86,29 @@
  },
]
const waylinePointsEvent = ref<tragetPoint[]>([])
// 路线详情
const waylineDetails = reactive<waylineDetails[]>([
  {
    title: '航线长度',
    value: '0',
  },
  {
    title: '预计执行时间',
    value: '0',
  },
  {
    title: '航点',
    value: 0,
  },
  {
    title: '照片',
    value: 0,
  },
])
// kml中的全部实体
const kmlEntities = ref<Cesium.Entity[]>([])
const useMapDraw = (
  dataSource: Cesium.DataSource | any,
  entitiesList: Cesium.Entity[] | any,
@@ -93,43 +116,29 @@
  global: any,
) => {
  const ellipsoid = global.$viewer.scene.globe.ellipsoid
  const waylinePointsEvent = ref<tragetPoint[]>([])
  // 路线详情
  const waylineDetails = reactive<waylineDetails[]>([
    {
      title: '航线长度',
      value: '0',
    },
    {
      title: '预计执行时间',
      value: '0',
    },
    {
      title: '航点',
      value: 0,
    },
    {
      title: '照片',
      value: 0,
    },
  ])
  // kml中的全部实体
  const kmlEntities = ref<Cesium.Entity[]>([])
  //   kml文件中点位string
  let kmlPoints: string[] | any = []
  //   记录点位信息
  const cartesianArr: Cesium.Cartesian3[] = []
  //  记录点位信息
  let cartesianArr: Cesium.Cartesian3[] = []
  //   绘制路线
  const drawWayline = async () => {
    dataSource.show = false
    let kmlEntityArr = [...entitiesList]
  const drawWayline = async (entities: Cesium.Entity[], kmlStr: string) => {
    if (!entities && !kmlStr) {
      dataSource.show = false
    }
    let kmlEntityArr = entities || [...entitiesList]
    if (dataSource) {
      kmlEntityArr = dataSource.entities.values[0]._children
      kmlEntities.value = kmlEntityArr
    }
    // 获取所有点位
    const kmlRes = await analyzeKmzFile(fileUrl)
    let kmlRes = ''
    if (kmlStr) {
      kmlRes = kmlStr
    } else {
      kmlRes = await analyzeKmzFile(fileUrl)
    }
    // 所有航点
    kmlPoints = getKmlParams(kmlRes, false, {
      name: 'Placemark',
@@ -138,6 +147,11 @@
    })
    // 起飞点
    let btmStartPoint = null
    // 判断是否存在实体集
    if (entities) {
      cartesianArr = []
      waylinePointsEvent.value = []
    }
    // 修改点位样式
    for (let i = 0; i < kmlEntityArr.length; i++) {
      const entity: any = kmlEntityArr[i]
@@ -148,21 +162,17 @@
      const latitude = Cesium.Math.toDegrees(c2Postion.latitude)
      // 获取当前航点中的值
      const point = kmlPoints[i]
      const getPointHeight: any = getKmlParams(point, true, {
      const getHaeHeight: any = getKmlParams(point, true, {
        name: 'ellipsoidHeight',
        findRegx: '([\\s\\S]*?)',
      })
      const getHaeHeight: any = getKmlParams(point, true, {
      const getPointHeight: any = getKmlParams(point, true, {
        name: 'height',
        findRegx: '([\\s\\S]*?)',
      })
      const AslHeight = Number(getPointHeight[1])
      const HeaHeight = Number(getHaeHeight[1])
      entity.position = Cesium.Cartesian3.fromDegrees(
        longitude,
        latitude,
        AslHeight,
      )
      entity.position = Cesium.Cartesian3.fromDegrees(longitude, latitude, AslHeight)
      if (i === 0) {
        btmStartPoint = Cesium.Cartesian3.fromDegrees(longitude, latitude, 0)
      }
@@ -191,6 +201,9 @@
        color: Cesium.Color.GHOSTWHITE,
        outlineColor: Cesium.Color.BLACK,
      })
      if (entities) {
        global.$viewer.entities.add(entity)
      }
      // 创建虚线
      addPolyline({
        id: 'dashLine' + i,
@@ -244,7 +257,9 @@
    })
    // 获取航线详情
    getWaylineDetails(kmlRes)
    dataSource.show = true
    if (!entities && !kmlStr) {
      dataSource.show = true
    }
    global.$viewer.flyTo(getEntityById('entityLine'), {
      offset: new Cesium.HeadingPitchRange(0, -90, 600),
    })
@@ -267,15 +282,19 @@
    const sportTime = polylineLength / speed
    // 判断有没有超过一分钟
    const time = sportTime / 60
    waylineDetails[1].value =
      Math.trunc(time) + ' m ' + Math.round((time % 1) * 60) + ' s'
    waylineDetails[1].value = Math.trunc(time) + ' m ' + Math.round((time % 1) * 60) + ' s'
    // 获取事件
    getPointEvent()
    getPointEvent(kmlStr || null)
  }
  // 获取航线点位事件
  const getPointEvent = async () => {
    const kmlRes = await analyzeKmzFile(fileUrl)
  const getPointEvent = async (kmlStr: string | null) => {
    let kmlRes = ''
    if (kmlStr) {
      kmlRes = kmlStr
    } else {
      await analyzeKmzFile(fileUrl)
    }
    // 所有航点
    const points = getKmlParams(kmlRes, false, {
      name: 'Placemark',
@@ -347,6 +366,10 @@
      }
    })
  }
  const clearWaylineData = () => {
    kmlEntities.value = []
    waylinePointsEvent.value = []
  }
  return {
    waylinePointsEvent,
@@ -354,6 +377,9 @@
    kmlEntities,
    drawWayline,
    getWaylineDetails,
    clearWaylineData,
  }
}
export { waylinePointsEvent, waylineDetails, kmlEntities }
export default useMapDraw