update:航线全局设置编辑、新增航点、事件编辑等
航线全局设置编辑(并体现在地图上)、新增航点、事件编辑等
6 files modified
3 files added
| New file |
| | |
| | | { |
| | | "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" |
| | | } |
| | |
| | | 安全起飞高度:是相对起飞点的高度值。\n |
| | | 飞行器起飞后,会先上升至"安全起飞高度",再飞向航线起始点 |
| | | `, |
| | | EGM96 = '绝对高度:航点高度值相对于海拔面/椭球面高度保持不变。', |
| | | relativeToStartPoint = '相对起飞点高度(ALT):航点高度值相对起飞点的高度保持不变。' |
| | | } |
| | | |
| | | export enum heightModeEnums { |
| | | 'WGS84', |
| | | 'relativeToStartPoint', |
| | | 'realTimeFollowSurface', |
| | | } |
| | |
| | | <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" |
| | |
| | | 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> |
| | |
| | | <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> |
| | |
| | | </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 |
| | |
| | | } |
| | | |
| | | 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> |
| | |
| | | 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; |
| | |
| | | color: #fff; |
| | | font-weight: bold; |
| | | border: 0; |
| | | |
| | | &::before { |
| | | background-color: #101010; |
| | | } |
| | | |
| | | &-checked { |
| | | background-color: #409eff !important; |
| | | } |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | .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; |
| | |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | li { |
| | | width: 50px; |
| | | border-radius: 3px; |
| | |
| | | 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; |
| | |
| | | margin-right: 5px; |
| | | } |
| | | } |
| | | |
| | | &:not(:nth-child(3)) { |
| | | &:hover { |
| | | background-color: #5d5f61; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | .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; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | .subtract, |
| | | .add { |
| | | width: 32px; |
| | |
| | | background-color: #3c3c3c; |
| | | border-radius: 3px; |
| | | cursor: pointer; |
| | | |
| | | &:hover { |
| | | background-color: #5d5f61; |
| | | } |
| | |
| | | .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; |
| | | } |
| | |
| | | } |
| | | } |
| | | </style> |
| | | ../../../../../../utils/cesium/types/kml |
| | |
| | | <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"> |
| | |
| | | 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' |
| | |
| | | // 样式 |
| | | const kmlEntities = ref<Cesium.Entity[]>([]) |
| | | |
| | | const loadCompleted = ref<boolean>(false) |
| | | |
| | | const initDrawRoute = () => { |
| | | const options = { |
| | | camera: global.$viewer.scene.camera, |
| | |
| | | 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() |
| New file |
| | |
| | | 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 |
| | | } |
| | |
| | | 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) |
| | | } |
| | | } |
| New file |
| | |
| | | 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 |
| | | } |
| | |
| | | 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 = () => { |
| | |
| | | </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 |
| | |
| | | }, |
| | | ] |
| | | |
| | | 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, |
| | |
| | | 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', |
| | |
| | | }) |
| | | // 起飞点 |
| | | let btmStartPoint = null |
| | | // 判断是否存在实体集 |
| | | if (entities) { |
| | | cartesianArr = [] |
| | | waylinePointsEvent.value = [] |
| | | } |
| | | // 修改点位样式 |
| | | for (let i = 0; i < kmlEntityArr.length; i++) { |
| | | const entity: any = kmlEntityArr[i] |
| | |
| | | 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) |
| | | } |
| | |
| | | color: Cesium.Color.GHOSTWHITE, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | }) |
| | | if (entities) { |
| | | global.$viewer.entities.add(entity) |
| | | } |
| | | // 创建虚线 |
| | | addPolyline({ |
| | | id: 'dashLine' + i, |
| | |
| | | }) |
| | | // 获取航线详情 |
| | | getWaylineDetails(kmlRes) |
| | | dataSource.show = true |
| | | if (!entities && !kmlStr) { |
| | | dataSource.show = true |
| | | } |
| | | global.$viewer.flyTo(getEntityById('entityLine'), { |
| | | offset: new Cesium.HeadingPitchRange(0, -90, 600), |
| | | }) |
| | |
| | | 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', |
| | |
| | | } |
| | | }) |
| | | } |
| | | const clearWaylineData = () => { |
| | | kmlEntities.value = [] |
| | | waylinePointsEvent.value = [] |
| | | } |
| | | |
| | | return { |
| | | waylinePointsEvent, |
| | |
| | | kmlEntities, |
| | | drawWayline, |
| | | getWaylineDetails, |
| | | clearWaylineData, |
| | | } |
| | | } |
| | | |
| | | export { waylinePointsEvent, waylineDetails, kmlEntities } |
| | | export default useMapDraw |