GuLiMmo
2024-03-19 aec00ecc093be803860c8675cbe1c4c776a7cb4e
src/utils/cesium/use-kmz-tsa.ts
@@ -1,15 +1,8 @@
import { ref, getCurrentInstance } from 'vue'
import {
  analyzeKmzFile,
  getKmlParams,
  generateKmlFormat,
  XMLToJSON,
  JSONToXML
} from '/@/utils/cesium/kmz'
import { ref } from 'vue'
import { analyzeKmzFile, XMLToJSON, JSONToXML } from '/@/utils/cesium/kmz'
import _ from 'lodash'
import JSZIP from 'jszip'
import { saveAs } from 'file-saver'
const JsZip = new JSZIP()
const fileAuthor = reactive({
  name: '',
@@ -18,7 +11,7 @@
const kmlStr = ref('')
const kmzFile = ref<any>(null)
const template = ref({
const template = ref<any>({
  author: '',
  createTime: '',
  updateTime: '',
@@ -91,7 +84,7 @@
    ],
  },
})
const waylines = ref({
const waylines = ref<any>({
  missionConfig: {
    flyToWaylineMode: 'safely',
    finishAction: 'goHome',
@@ -138,34 +131,6 @@
  },
})
// 点位参数
const placemark: any = {
  Point: {
    coordinates: '',
  },
  index: 0,
  executeHeight: 80,
  height: 80,
  waypointSpeed: 10,
  waypointHeadingParam: {
    waypointHeadingMode: 'followWayline',
    waypointHeadingAngle: 0,
    waypointPoiPoint: '0.000000,0.000000,0.000000',
    waypointHeadingPathMode: 'followBadArc',
    waypointHeadingPoiIndex: 0,
  },
  waypointTurnParam: {
    waypointTurnMode: 'toPointAndStopWithDiscontinuityCurvature',
    waypointTurnDampingDist: 0.2,
  },
  useGlobalHeight: 1,
  useGlobalSpeed: 1,
  useGlobalHeadingParam: 1,
  useGlobalTurnParam: 1,
  useStraightLine: 1,
  actionGroup: {},
}
const useKmzTsa = () => {
  const init = async (fileUrl: string, fileContent?: string) => {
    const fileRes = await analyzeKmzFile(fileUrl)
@@ -176,151 +141,168 @@
      return false
    }
    kmlStr.value = kmzRes
    const tplXmlJson = XMLToJSON(kmzRes)
    template.value = tplXmlJson.Document
    return kmzRes
  }
  const create = () => {
    const nowTime = new Date().getTime()
    const str = `
    <?xml version="1.0" encoding="UTF-8"?>
    <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.5">
      <Document>
        <wpml:author>17304076412</wpml:author>
        <wpml:createTime>${nowTime}</wpml:createTime>
        <wpml:updateTime>${nowTime}</wpml:updateTime>
        <wpml:missionConfig>
        </wpml:missionConfig>
        <Folder>
        </Folder>
      </Document>
    </kml>
    `
    kmlStr.value = str
  }
  const writePoint = (settingParmas: any = {}, place: string, pointNumber: number = 0) => {
    Object.keys(settingParmas).forEach((key: string) => {
      placemark[key] = settingParmas[key]
    })
    const Placemark = `<Placemark>${generateKmlFormat(placemark)}</Placemark>`
    const points: RegExpMatchArray = getKmlParams(kmlStr.value, false, {
      name: 'Placemark',
      findRegx: '([\\s\\S]*?)',
      mode: 'g',
    }) || ['']
    if (place === 'add') {
      const lastPoint = points[points.length - 1]
      const index = kmlStr.value.indexOf(lastPoint)
      const beforeStr = kmlStr.value.slice(0, index)
      const afterStr = kmlStr.value.slice(index + lastPoint.length)
      kmlStr.value = beforeStr + lastPoint + Placemark + afterStr
    }
    if (place === 'prev') {
      const currentPoint: string = points[pointNumber]
      const index = kmlStr.value.indexOf(currentPoint)
      const beforeStr = kmlStr.value.slice(0, index)
      const afterStr = kmlStr.value.slice(index + currentPoint.length)
      kmlStr.value = beforeStr + Placemark + currentPoint + afterStr
      // 更新点位序号
      const pointIndexList = getKmlParams(kmlStr.value, true, {
        name: 'index',
        findRegx: '([\\s\\S]*?)',
        mode: 'g',
      })
      pointIndexList?.forEach((pintIndex: string, index: number) => {
        kmlStr.value.replace(pintIndex, `<wpml:index>${index}</wpml:index>`)
      })
    }
    if (place === 'next') {
      const currentPoint: string = points[pointNumber + 1]
      const index = kmlStr.value.indexOf(currentPoint)
      const beforeStr = kmlStr.value.slice(0, index)
      const currentPointLength = currentPoint?.length || 0
      const afterStr = kmlStr.value.slice(index + currentPointLength)
      kmlStr.value = beforeStr + Placemark + currentPoint + afterStr
      // 更新点位序号
      const pointIndexList = getKmlParams(kmlStr.value, true, {
        name: 'index',
        findRegx: '([\\s\\S]*?)',
        mode: 'g',
      })
      pointIndexList?.forEach((pintIndex: string, index: number) => {
        kmlStr.value.replace(pintIndex, `<wpml:index>${index}</wpml:index>`)
      })
    }
  }
  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',
          })
          const ellipsoidHeightRegx = getKmlParams(kmlStr.value, true, {
            name: 'ellipsoidHeight',
            findRegx: '([\\s\\S]*?)',
            mode: 'g',
          }) || ['']
          // 文件中的海拔高度
          const takeOffRefPointAGLHeightRegxStr = getKmlParams(kmlStr.value, true, {
            name: 'takeOffRefPointAGLHeight',
            findRegx: '([\\s\\S]*?)',
          }) || ['', '0']
          const posterHeight = Number(takeOffRefPointAGLHeightRegxStr[1])
          // 获取每个点是否使用全局高度
          const useGlobalHeightRegStr = getKmlParams(kmlStr.value, true, {
            name: 'useGlobalHeight',
            findRegx: '([\\s\\S]*?)',
            mode: 'g',
          }) || ['', '0']
          regxVal.forEach((heightStr: string, index: number) => {
            // 使用正则取值
            const getUseGlobalHeightValStr = getKmlParams(useGlobalHeightRegStr[index], true, {
              name: 'useGlobalHeight',
              findRegx: '([\\s\\S]*?)',
            }) || ['', '0']
            const isGlobalHeight = Boolean(Number(getUseGlobalHeightValStr[1]))
            if (isGlobalHeight) {
              // 替换height
              const rstr = generateKmlFormat({ height: settingParmas[key] })
              const rEllipsoidHeightStr = generateKmlFormat({ ellipsoidHeight: settingParmas[key] - posterHeight })
              kmlStr.value = kmlStr.value.replace(heightStr, rstr)
              kmlStr.value = kmlStr.value.replace(ellipsoidHeightRegx[index], rEllipsoidHeightStr)
              // 替换
            } else {
              const heightRegxVal: any = getKmlParams(heightStr, true, {
                name: 'height',
                findRegx: '([\\s\\S]*?)',
              })
            }
          })
        }
        const replaceStr = generateKmlFormat({ [key]: settingParmas[key] })
        kmlStr.value = kmlStr.value.replace(regxVal[0], replaceStr)
      } else {
        console.warn('没有找到对应的属性')
  const create = async (waylineBasicInfo: { fileName: string; droneEnumValue: string; payloadEnumValue: string }) => {
    try {
      const { fileName, droneEnumValue, payloadEnumValue } = waylineBasicInfo
      const author = window.localStorage.getItem('username') || ''
      const createTime = new Date().getTime()
      // 模板
      const droneModel: { [key: string]: string } = {
        52: '0',
        53: '1',
        66: '0',
        67: '1',
        80: '0',
        81: '1',
      } as const
      const templateJson = {
        author,
        createTime,
        updateTime: createTime,
        missionConfig: {
          flyToWaylineMode: 'safely',
          finishAction: 'goHome',
          exitOnRCLost: 'goContinue',
          executeRCLostAction: 'goBack',
          takeOffSecurityHeight: 20,
          takeOffRefPoint: '0.000000,0.000000,0.000000',
          takeOffRefPointAGLHeight: 0,
          globalTransitionalSpeed: 15,
          globalRTHHeight: 80,
          droneInfo: {
            droneEnumValue,
            droneSubEnumValue: droneModel[payloadEnumValue],
          },
          payloadInfo: {
            payloadEnumValue,
            payloadSubEnumValue: droneModel[payloadEnumValue],
            payloadPositionIndex: 0,
          },
        },
        Folder: {
          templateType: 'waypoint',
          useGlobalTransitionalSpeed: 0,
          templateId: 0,
          waylineCoordinateSysParam: {
            coordinateMode: 'WGS84',
            heightMode: 'EGM96',
            globalShootHeight: 50,
            positioningType: 'GPS',
            surfaceFollowModeEnable: 1,
            surfaceRelativeHeight: 100,
          },
          autoFlightSpeed: 7,
          gimbalPitchMode: 'usePointSetting',
          globalWaypointHeadingParam: {
            waypointHeadingMode: 'followWayline',
            waypointHeadingAngle: 0,
            waypointPoiPoint: '0.000000,0.000000,0.000000',
            waypointHeadingPathMode: 'followBadArc',
          },
          globalWaypointTurnMode: 'toPointAndStopWithDiscontinuityCurvature',
          globalUseStraightLine: 0,
          Placemark: [],
        },
      }
      template.value = templateJson
      return true
    } catch (error) {
      return error
    }
  }
  const save = () => {
    const JsZip = new JSZIP()
    const waylines = waylinesContext(template.value)
    const templateXml = JSONToXML(template.value, '', true)
    const waylinesWpml = JSONToXML(waylines, '', true)
    JsZip.file('wpmz/template.kml', templateXml)
    JsZip.file('wpmz/waylines.wpml', waylinesWpml)
    JsZip.generateAsync({ type: 'blob' }).then((blob) => {
      saveAs(blob, '新建航线.kmz')
    })
  }
  const save = () => {
    console.log('存在问题')
  const generateXML = <T>(xmlJson: T) => {
    return JSONToXML(xmlJson)
  }
  const waylinesContext = (templateJson: any) => {
    const waylinesObj: { [key: string]: any } = {
      missionConfig: {
        flyToWaylineMode: null,
        finishAction: null,
        exitOnRCLost: null,
        executeRCLostAction: null,
        takeOffSecurityHeight: null,
        globalTransitionalSpeed: null,
        globalRTHHeight: null,
        droneInfo: null,
        payloadInfo: null,
      },
      Folder: {
        templateId: null,
        executeHeightMode: null,
        waylineId: null,
        autoFlightSpeed: null,
        Placemark: null,
      },
    }
    Object.keys(waylinesObj).forEach((key: string) => {
      if (Object.prototype.toString.call(waylinesObj[key]) === '[object Object]') {
        Object.keys(waylinesObj[key]).forEach((item) => {
          waylinesObj[key][item] = templateJson[key][item]
          if (item === 'executeHeightMode') {
            waylinesObj[key][item] = templateJson[key].waylineCoordinateSysParam.heightMode
          }
          if (item === 'waylineId') {
            waylinesObj[key][item] = templateJson[key].templateId
          }
          if (item === 'Placemark') {
            const placemarks = _.cloneDeep(templateJson[key][item])
            placemarks.forEach(
              (placemark: {
                executeHeight: { '#text': string }
                ellipsoidHeight?: { [x: string]: string }
                height?: { [x: string]: string }
              }) => {
                placemark.executeHeight = { '#text': placemark.ellipsoidHeight?.['#text'] || '' }
                delete placemark.ellipsoidHeight
                delete placemark.height
              },
            )
            waylinesObj[key][item] = placemarks
          }
        })
      } else {
        waylinesObj[key] = templateJson[key]
      }
    })
    return waylinesObj
  }
  // 将wpmz/template.kml解析传来json转换回去,重新复制以便于后续绘制
  watch(
    () => template.value,
    (newobj) => {
      const xmlString = JSONToXML(newobj)
      kmlStr.value = xmlString
    },
    {
      deep: true,
    },
  )
  return {
    init,
    create,
    // write,
    writePoint,
    edit,
    save,
    generateXML,
  }
}
export { kmlStr, fileAuthor }
export { kmlStr, fileAuthor, template, waylines }
export default useKmzTsa