|
|
<template>
|
|
|
<!-- 地图 -->
|
|
|
<div ref="vChartRef " :id="'mars3d-container_' + mapId" class="mars3d-container">
|
|
|
<!-- 航点航线 -->
|
|
|
<div
|
|
|
v-if="props.airLineForm.airLineType == 'waypoint'"
|
|
|
v-show="props.editMode != 'detail'"
|
|
|
class="air-container"
|
|
|
>
|
|
|
<airPoint
|
|
|
:airInfo="lineInfo"
|
|
|
:editModel="props.editMode"
|
|
|
:polygonAirForm="polygonAirForm"
|
|
|
:airLineForm="props.airLineForm"
|
|
|
:wayline="props.wayline"
|
|
|
:airPoints="airPoints"
|
|
|
:waylineInfo="props.waylineInfo"
|
|
|
:templateKmlConfig="props.templateKmlConfig"
|
|
|
:waylineWpmlConfig="props.waylineWpmlConfig"
|
|
|
@setTakeOffPoint="setTakeOffPoint"
|
|
|
@exitDraw="exitDraw"
|
|
|
@addAction="addAction"
|
|
|
@checkPoint="checkPoint"
|
|
|
></airPoint>
|
|
|
</div>
|
|
|
|
|
|
<!-- 航面航线 -->
|
|
|
<div v-if="props.airLineForm.airLineType == 'mapping2d'" v-show="props.editMode != 'detail'" class="airpolygon-container">
|
|
|
<airPolygon
|
|
|
:airInfo="airInfo"
|
|
|
:editModel="props.editMode"
|
|
|
:polygonAirForm="polygonAirForm"
|
|
|
:airLineForm="props.airLineForm"
|
|
|
:waylineInfo="props.waylineInfo"
|
|
|
:airPoints="airPoints"
|
|
|
:polygon="polygonGeoJson"
|
|
|
:templateKmlConfig="props.templateKmlConfig"
|
|
|
:waylineWpmlConfig="props.waylineWpmlConfig"
|
|
|
@setTakeOffPoint="setTakeOffPoint"
|
|
|
@calculatParamChange="calculatParamChange"
|
|
|
@exitDraw="exitDraw"
|
|
|
></airPolygon>
|
|
|
</div>
|
|
|
|
|
|
<!-- 航点航线配置 -->
|
|
|
<div class="airpoint-config-container" v-if="airPointConfigShow">
|
|
|
<airPointConfig
|
|
|
:currentAirPoint="currentAirPoint"
|
|
|
:airPoints="airPoints"
|
|
|
@paramChagne="paramChagne"
|
|
|
@pointChange="pointChange"
|
|
|
@positionChange="positionChange"
|
|
|
></airPointConfig>
|
|
|
</div>
|
|
|
|
|
|
<!-- 航线预览信息 -->
|
|
|
<div class="airline-preview-container" v-if="props.editMode == 'detail'">
|
|
|
<div class="info-item">
|
|
|
<div class="info-value">46461m²</div>
|
|
|
<div class="info-label">区域面积</div>
|
|
|
</div>
|
|
|
<div class="info-item">
|
|
|
<div class="info-value">46461m²</div>
|
|
|
<div class="info-label">航线长度</div>
|
|
|
</div>
|
|
|
<div class="info-item">
|
|
|
<div class="info-value">34分钟</div>
|
|
|
<div class="info-label">预计时间</div>
|
|
|
</div>
|
|
|
<div class="info-item">
|
|
|
<div class="info-value">78张</div>
|
|
|
<div class="info-label">照片数量</div>
|
|
|
</div>
|
|
|
<div class="info-item">
|
|
|
<div>
|
|
|
<a-button type="primary" danger size="small" @click="exitDraw">
|
|
|
<CloseOutlined />
|
|
|
</a-button>
|
|
|
</div>
|
|
|
<div>关闭</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 面绘制 -->
|
|
|
<div class="draw-polygon-patrol" title="绘制面区域" v-if="props.drawArea" @click="handlerDrawPolygonPatrol">
|
|
|
<EditOutlined />
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script lang="ts" setup>
|
|
|
import { ref, onMounted, defineProps, watch, defineEmits, reactive } from 'vue';
|
|
|
import { message } from 'ant-design-vue';
|
|
|
import { CloseOutlined } from '@ant-design/icons-vue';
|
|
|
import { GeojsonToWkt, WktToGeojson } from '@/components/MapboxMaps/src/WktGeojsonTransform';
|
|
|
import { buildUUID } from '@/utils/uuid';
|
|
|
import airPoint from './airPoint.vue';
|
|
|
import * as mars3d from 'mars3d';
|
|
|
import { EventBus } from '@/utils/eventBus';
|
|
|
import { airPortStore } from '@/store/modules/airport';
|
|
|
import { airPointActions } from '../waylineConfig/actionConfig';
|
|
|
import 'mars3d-space';
|
|
|
import { EditOutlined } from '@ant-design/icons-vue';
|
|
|
import * as Cesium from 'mars3d-cesium';
|
|
|
// import * as turf from '@turf/turf';
|
|
|
import airPolygon from './airPolygon.vue';
|
|
|
import airPointConfig from './airPointConfig.vue';
|
|
|
import { uuid } from '@/utils/uuid';
|
|
|
|
|
|
// const props = defineProps([
|
|
|
// 'airLineForm',
|
|
|
// 'flyToTherePosition',
|
|
|
// 'wayline',
|
|
|
// 'waylineInfo',
|
|
|
// 'workPlanFormShow',
|
|
|
// 'airPort',
|
|
|
// 'uavTrack',
|
|
|
// 'homeAirport'
|
|
|
// ]);
|
|
|
|
|
|
const mapId = ref(uuid(6, 14));
|
|
|
const props = defineProps({
|
|
|
editMode: {
|
|
|
type: String,
|
|
|
default: 'add',
|
|
|
},
|
|
|
airLineForm: {
|
|
|
type: Object,
|
|
|
default: () => ({
|
|
|
id: null,
|
|
|
airLineName: null,
|
|
|
airLineType: null,
|
|
|
uavId: null,
|
|
|
flyToFirstPointMode: null,
|
|
|
safeTakeoffAltitude: 0,
|
|
|
safeTakeoffSpeed: 0,
|
|
|
globalRouteSpeed: 0,
|
|
|
taskCompletionAction: null,
|
|
|
outOfControlOption: null,
|
|
|
typeOfOutOfControlAction: null,
|
|
|
globalWayPointType: null,
|
|
|
ptzControlMode: null,
|
|
|
aircraftYawAngleMode: null,
|
|
|
createTime: null,
|
|
|
wpml: null,
|
|
|
taskOffLng: 0,
|
|
|
taskOffLat: 0,
|
|
|
folder: null,
|
|
|
}),
|
|
|
},
|
|
|
wayline: {
|
|
|
type: Object,
|
|
|
},
|
|
|
waylineInfo: {
|
|
|
type: Object,
|
|
|
default: () => ({
|
|
|
missionConfig: {
|
|
|
flyToWaylineMode: 'safely', // 爬升模式 safely pointToPoint
|
|
|
finishAction: 'goHome', // 航线结束动作
|
|
|
exitOnRCLost: 'executeLostAction', // 失控是否继续执行航线
|
|
|
executeRCLostAction: 'goBack', // 失控动作类型
|
|
|
takeOffSecurityHeight: 20, // 安全起飞高度
|
|
|
globalTransitionalSpeed: 15, // 全局航线过渡速度
|
|
|
globalRTHHeight: 100, // 全局返航高度
|
|
|
droneInfo: {
|
|
|
// 飞行器机型信息
|
|
|
droneEnumValue: 100,
|
|
|
droneSubEnumValue: 1,
|
|
|
},
|
|
|
autoRerouteInfo: {
|
|
|
// 航线绕行
|
|
|
transitionalAutoRerouteMode: 1,
|
|
|
missionAutoRerouteMode: 1,
|
|
|
},
|
|
|
waylineAvoidLimitAreaMode: 0,
|
|
|
payloadInfo: {
|
|
|
// 负载机型信息
|
|
|
payloadEnumValue: 99, // 负载机型主类型
|
|
|
payloadSubEnumValue: 2,
|
|
|
payloadPositionIndex: 0, // 负载挂载位置
|
|
|
},
|
|
|
},
|
|
|
Folder: {
|
|
|
templateId: 0,
|
|
|
executeHeightMode: 'WGS84',
|
|
|
waylineId: 0,
|
|
|
distance: 1391.755859375,
|
|
|
duration: 200.941531419754,
|
|
|
autoFlightSpeed: 8.2, // 全局航线飞行速度
|
|
|
startActionGroup: {
|
|
|
action: [
|
|
|
{
|
|
|
actionId: 0,
|
|
|
actionActuatorFunc: 'gimbalRotate',
|
|
|
actionActuatorFuncParam: {
|
|
|
gimbalHeadingYawBase: 'aircraft',
|
|
|
gimbalRotateMode: 'absoluteAngle',
|
|
|
gimbalPitchRotateEnable: 1,
|
|
|
gimbalPitchRotateAngle: -90,
|
|
|
gimbalRollRotateEnable: 0,
|
|
|
gimbalRollRotateAngle: 0,
|
|
|
gimbalYawRotateEnable: 1,
|
|
|
gimbalYawRotateAngle: 0,
|
|
|
gimbalRotateTimeEnable: 0,
|
|
|
gimbalRotateTime: 10,
|
|
|
payloadPositionIndex: 0,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
actionId: 1,
|
|
|
actionActuatorFunc: 'hover',
|
|
|
actionActuatorFuncParam: {
|
|
|
hoverTime: 0.5,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
actionId: 2,
|
|
|
actionActuatorFunc: 'setFocusType',
|
|
|
actionActuatorFuncParam: {
|
|
|
cameraFocusType: 'manual',
|
|
|
payloadPositionIndex: 0,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
actionId: 3,
|
|
|
actionActuatorFunc: 'focus',
|
|
|
actionActuatorFuncParam: {
|
|
|
focusX: 0,
|
|
|
focusY: 0,
|
|
|
focusRegionWidth: 0,
|
|
|
focusRegionHeight: 0,
|
|
|
isPointFocus: 0,
|
|
|
isInfiniteFocus: 1,
|
|
|
payloadPositionIndex: 0,
|
|
|
isCalibrationFocus: 0,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
actionId: 4,
|
|
|
actionActuatorFunc: 'hover',
|
|
|
actionActuatorFuncParam: {
|
|
|
hoverTime: 1,
|
|
|
},
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
Placemark: [],
|
|
|
},
|
|
|
}),
|
|
|
},
|
|
|
workPlanFormShow: {
|
|
|
type: Boolean,
|
|
|
},
|
|
|
airPort: {
|
|
|
type: Object,
|
|
|
},
|
|
|
uavTrack: {
|
|
|
type: Object,
|
|
|
},
|
|
|
homeAirport: {
|
|
|
type: Object,
|
|
|
},
|
|
|
templateKmlConfig: {
|
|
|
type: Object,
|
|
|
},
|
|
|
waylineWpmlConfig: {
|
|
|
type: Object,
|
|
|
},
|
|
|
drawArea: {
|
|
|
type: Boolean,
|
|
|
default: false,
|
|
|
},
|
|
|
polygonArea: {
|
|
|
type: Object,
|
|
|
},
|
|
|
});
|
|
|
const centerObj = reactive({
|
|
|
lat: 260.9,
|
|
|
heading: 357.9,
|
|
|
pitch: -32,
|
|
|
});
|
|
|
|
|
|
watch(
|
|
|
() => props.editMode,
|
|
|
(newVal,oldVal)=>{
|
|
|
if(newVal == 'edit' || newVal == 'detail'){
|
|
|
if(props.airLineForm.airLineType == 'waypoint'){
|
|
|
handlerEditWaypointAirLine();
|
|
|
}else if(props.airLineForm.airLineType == 'mapping2d'){
|
|
|
handlerEditPolygonAirLine();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
)
|
|
|
|
|
|
|
|
|
watch(
|
|
|
() => props.polygonArea,
|
|
|
(newVal, oldVal) => {
|
|
|
if (newVal) {
|
|
|
handlerReportPolygonAirLine();
|
|
|
}
|
|
|
},
|
|
|
);
|
|
|
|
|
|
watch(
|
|
|
() => props.uavTrack,
|
|
|
(val) => {
|
|
|
setUAVPosition();
|
|
|
},
|
|
|
{ deep: true },
|
|
|
);
|
|
|
|
|
|
watch(
|
|
|
() => props.airPort,
|
|
|
(val) => {
|
|
|
setAirportPosition();
|
|
|
},
|
|
|
{ deep: true },
|
|
|
);
|
|
|
|
|
|
watch(
|
|
|
() => props.homeAirport,
|
|
|
(val) => {
|
|
|
homeSetAirportPosition();
|
|
|
},
|
|
|
{ deep: true },
|
|
|
);
|
|
|
|
|
|
watch(
|
|
|
() => props.workPlanFormShow,
|
|
|
(newVal, oldVal) => {
|
|
|
if (!newVal) {
|
|
|
clearAllLayer();
|
|
|
}
|
|
|
},
|
|
|
);
|
|
|
|
|
|
// 航线表单
|
|
|
watch(
|
|
|
() => props.airLineForm,
|
|
|
(newVal, oldVal) => {
|
|
|
// 根据编辑模式更新地图右键菜单
|
|
|
handlerBindMapMenus();
|
|
|
},
|
|
|
{
|
|
|
deep: true,
|
|
|
},
|
|
|
);
|
|
|
|
|
|
// 航线文件
|
|
|
watch(
|
|
|
() => props.wayline,
|
|
|
(newVal, oldVal) => {
|
|
|
// generatePreviewPoint(newVal?.Folder?.Placemark);
|
|
|
},
|
|
|
);
|
|
|
|
|
|
watch(
|
|
|
() => props.waylineInfo,
|
|
|
(newVal, oldVal) => {},
|
|
|
);
|
|
|
|
|
|
// 航线预览:生成点
|
|
|
const generatePreviewPoint = (placemark) => {
|
|
|
// 设置默认起飞点
|
|
|
takeOffPointPosition.value = [props.airLineForm?.taskOffLng, props.airLineForm?.taskOffLat, 70];
|
|
|
|
|
|
// 先清空所有数据
|
|
|
clearAllLayer();
|
|
|
|
|
|
placemark?.forEach((item, index) => {
|
|
|
let coordinate = item.Point.coordinates.split(',');
|
|
|
let airPointInfo = {
|
|
|
id: item.index,
|
|
|
name: '航点',
|
|
|
lng: coordinate[0],
|
|
|
lat: coordinate[1],
|
|
|
alt: item.executeHeight,
|
|
|
aircraftHorizontalAngle: 0,
|
|
|
cameraHorizontalAngle: 0,
|
|
|
cameraVerticalAngle: 0,
|
|
|
focalLength: 2,
|
|
|
};
|
|
|
airPoints.value?.push(airPointInfo);
|
|
|
});
|
|
|
|
|
|
if (props.airLineForm?.airLineType == 'waypoint') {
|
|
|
// 航点航线
|
|
|
|
|
|
airPoints.value?.forEach((item, index) => {
|
|
|
let drawPoint = {
|
|
|
_lng: item.lng,
|
|
|
_lat: item.lat,
|
|
|
_alt: item.alt,
|
|
|
};
|
|
|
preViewPointWayLine(drawPoint);
|
|
|
});
|
|
|
} else if (props.airLineForm?.airLineType == 'mapping2d') {
|
|
|
let coordinates = [];
|
|
|
airPoints.value?.forEach((item, index) => {
|
|
|
coordinates.push([item.lng, item.lat]);
|
|
|
});
|
|
|
let line = turf.lineString(coordinates);
|
|
|
preViewPolygonWayLine(line);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const emits = defineEmits([
|
|
|
'exitDraw',
|
|
|
'flyToThere',
|
|
|
'mapOnLoad',
|
|
|
'clickAirPort',
|
|
|
'changeAirportLive',
|
|
|
'changeUAVLive',
|
|
|
'areaData',
|
|
|
]);
|
|
|
|
|
|
const airPoints = ref([]);
|
|
|
const currentAirPoint = ref({});
|
|
|
const airPointConfigShow = ref(false);
|
|
|
|
|
|
// 全局平移工具
|
|
|
let moveTool: mars3d.thing.MatrixMove2;
|
|
|
|
|
|
// 监听航点变化
|
|
|
// watch(
|
|
|
// currentAirPoint,
|
|
|
// (newVal, oldVal) => {
|
|
|
// // console.log("newVal123",newVal);
|
|
|
// // 更新航点
|
|
|
// // updateAirPoint(newVal);
|
|
|
// // 更新镜头
|
|
|
// // handlerDrawCamera(newVal);
|
|
|
// },
|
|
|
// { deep: true },
|
|
|
// );
|
|
|
|
|
|
const clickPoint = (id) => {
|
|
|
airPoints.value?.forEach((item, index) => {
|
|
|
if (item.id == id) {
|
|
|
currentAirPoint.value = item;
|
|
|
// 更新镜头
|
|
|
handlerDrawCamera(currentAirPoint.value);
|
|
|
airPointConfigShow.value = true;
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
|
|
|
const checkPoint = (e) => {
|
|
|
currentAirPoint.value = e;
|
|
|
airPointConfigShow.value = true;
|
|
|
handlerDrawCamera(currentAirPoint.value);
|
|
|
};
|
|
|
|
|
|
|
|
|
///////////////////////////////图层中心////////////////////////////////////////////
|
|
|
|
|
|
let map: mars3d.Map; // 地图对象
|
|
|
|
|
|
let graphicLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
let uavGraphicLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
// 设置参考起飞点图层
|
|
|
let takeOffPointGraphicLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
// 测区面图层
|
|
|
let polygonGraphicLayer: mars3d.layer.GraphicLayer;
|
|
|
// 监测区域面图层
|
|
|
let patrolPolygonGraphicLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
// 面航线图层
|
|
|
let polygonLineGraphicLayer: mars3d.layer.GeoJsonLayer;
|
|
|
|
|
|
// 文本标注图层
|
|
|
let textLabelGraphicLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
// 航点地面投影点图层
|
|
|
let stickGroundPointLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
// 航点连接线
|
|
|
let lineGroundPointLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
|
|
|
// 飞行结果图片贴地点
|
|
|
let imageStickGroundPointLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
// 飞行结果图片连接线
|
|
|
let imageLineGroundPointLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
// 飞行结果图片
|
|
|
let imageResultPointLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
// 飞行结果选中图层照片
|
|
|
|
|
|
|
|
|
// 项目首页机场位置
|
|
|
let homeStartGraphic;
|
|
|
|
|
|
let homeStartGraphicLive;
|
|
|
|
|
|
let graphic = null;
|
|
|
|
|
|
// // 清空所有数据
|
|
|
const exitDraw = () => {
|
|
|
graphicLayer ? graphicLayer.clear() : null;
|
|
|
|
|
|
takeOffPointGraphicLayer ? takeOffPointGraphicLayer.clear() : null;
|
|
|
|
|
|
stickGroundPointLayer ? stickGroundPointLayer.clear() : null;
|
|
|
|
|
|
lineGroundPointLayer ? lineGroundPointLayer.clear() : null;
|
|
|
|
|
|
textLabelGraphicLayer ? textLabelGraphicLayer.clear() : null;
|
|
|
|
|
|
polygonGraphicLayer ? polygonGraphicLayer.clear() : null;
|
|
|
|
|
|
patrolPolygonGraphicLayer ? patrolPolygonGraphicLayer.clear() : null;
|
|
|
|
|
|
polygonLineGraphicLayer ? polygonLineGraphicLayer.clear() : null;
|
|
|
|
|
|
airPoints.value = [];
|
|
|
|
|
|
props.airLineForm.airLineType = null;
|
|
|
|
|
|
airPointConfigShow.value = false;
|
|
|
|
|
|
emits('exitDraw');
|
|
|
};
|
|
|
|
|
|
// 航点航线信息
|
|
|
const lineInfo = ref({
|
|
|
count: 0,
|
|
|
length: 0,
|
|
|
time: 0,
|
|
|
picture: '- -',
|
|
|
});
|
|
|
// 面航线信息
|
|
|
const airInfo = ref({
|
|
|
area: 0,
|
|
|
length: 0,
|
|
|
time: 0,
|
|
|
picture: '- -',
|
|
|
});
|
|
|
|
|
|
const polygonAirForm = ref({
|
|
|
startingPoint: null,
|
|
|
lensMode: 1,
|
|
|
gatherMode: 1,
|
|
|
heightMode: 1,
|
|
|
height: 120,
|
|
|
speed: 15,
|
|
|
angle: 0,
|
|
|
complete: 1,
|
|
|
});
|
|
|
|
|
|
const vChartRef = ref<HTMLElement>();
|
|
|
|
|
|
onMounted(() => {
|
|
|
if (props.drawArea) {
|
|
|
centerObj.lat = 835.9;
|
|
|
centerObj.heading = 2;
|
|
|
centerObj.pitch = -86;
|
|
|
}
|
|
|
|
|
|
initMap();
|
|
|
|
|
|
EventBus.on('closeTranslation', (val: any) => {
|
|
|
if (moveTool) {
|
|
|
moveTool.destroy();
|
|
|
moveTool = null;
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
// center: { lat: 35.132103, lng: 118.296315, alt: 260.9, heading: 357.9, pitch: -32 },
|
|
|
|
|
|
// 初始化地图
|
|
|
const initMap = () => {
|
|
|
map = new mars3d.Map('mars3d-container_' + mapId.value, {
|
|
|
scene: {
|
|
|
center: {
|
|
|
lat: 35.132103,
|
|
|
lng: 118.296315,
|
|
|
alt: centerObj.lat,
|
|
|
heading: centerObj.heading,
|
|
|
pitch: centerObj.pitch,
|
|
|
},
|
|
|
scene3DOnly: false,
|
|
|
shadows: false,
|
|
|
removeDblClick: true,
|
|
|
sceneMode: 3,
|
|
|
showSun: true,
|
|
|
showMoon: true,
|
|
|
showSkyBox: true,
|
|
|
showSkyAtmosphere: true,
|
|
|
fog: true,
|
|
|
fxaa: true,
|
|
|
requestRenderMode: true,
|
|
|
contextOptions: {
|
|
|
requestWebgl1: false,
|
|
|
webgl: {
|
|
|
preserveDrawingBuffer: true,
|
|
|
alpha: false,
|
|
|
stencil: true,
|
|
|
powerPreference: 'high-performance',
|
|
|
},
|
|
|
},
|
|
|
|
|
|
globe: {
|
|
|
depthTestAgainstTerrain: true,
|
|
|
baseColor: '#546a53',
|
|
|
showGroundAtmosphere: true,
|
|
|
enableLighting: false,
|
|
|
},
|
|
|
cameraController: {
|
|
|
zoomFactor: 3,
|
|
|
minimumZoomDistance: 1,
|
|
|
maximumZoomDistance: 50000000,
|
|
|
enableRotate: true,
|
|
|
enableTranslate: true,
|
|
|
enableTilt: true,
|
|
|
enableZoom: true,
|
|
|
enableCollisionDetection: true,
|
|
|
minimumCollisionTerrainHeight: 15000,
|
|
|
},
|
|
|
},
|
|
|
control: {
|
|
|
homeButton: true,
|
|
|
baseLayerPicker: false,
|
|
|
sceneModePicker: true,
|
|
|
vrButton: false,
|
|
|
fullscreenButton: true,
|
|
|
navigationHelpButton: true,
|
|
|
animation: false,
|
|
|
timeline: false,
|
|
|
infoBox: false,
|
|
|
geocoder: false,
|
|
|
selectionIndicator: false,
|
|
|
showRenderLoopErrors: true,
|
|
|
contextmenu: {
|
|
|
hasDefault: true,
|
|
|
},
|
|
|
mouseDownView: true,
|
|
|
zoom: {
|
|
|
insertIndex: 1,
|
|
|
},
|
|
|
compass: {
|
|
|
bottom: 'toolbar',
|
|
|
left: '5px',
|
|
|
rotation: true,
|
|
|
},
|
|
|
distanceLegend: {
|
|
|
left: '10px',
|
|
|
bottom: '2px',
|
|
|
},
|
|
|
locationBar: {
|
|
|
crs: 'CGCS2000_GK_Zone_3',
|
|
|
crsDecimal: 0,
|
|
|
template:
|
|
|
"<div>经度:{lng}</div> <div>纬度:{lat}</div> <div class='hide1000'>横{crsx} 纵{crsy}</div> <div>海拔:{alt}米</div> <div class='hide700'>层级:{level}</div><div>方向:{heading}°</div> <div>俯仰角:{pitch}°</div><div class='hide700'>视高:{cameraHeight}米</div>",
|
|
|
cacheTime: 50,
|
|
|
},
|
|
|
},
|
|
|
method: {
|
|
|
templateValues: {
|
|
|
dataServer: '//data.mars3d.cn',
|
|
|
gltfServerUrl: '//data.mars3d.cn/gltf',
|
|
|
},
|
|
|
},
|
|
|
terrain: {
|
|
|
url: '//data.mars3d.cn/terrain',
|
|
|
show: true,
|
|
|
clip: true,
|
|
|
},
|
|
|
basemaps: [
|
|
|
{
|
|
|
id: 10,
|
|
|
name: '地图底图',
|
|
|
type: 'group',
|
|
|
},
|
|
|
{
|
|
|
id: 2021,
|
|
|
pid: 10,
|
|
|
name: '天地图影像',
|
|
|
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
|
|
|
type: 'group',
|
|
|
layers: [
|
|
|
{
|
|
|
name: '底图',
|
|
|
type: 'tdt',
|
|
|
layer: 'img_d',
|
|
|
},
|
|
|
{
|
|
|
name: '注记',
|
|
|
type: 'tdt',
|
|
|
layer: 'img_z',
|
|
|
zIndex: 20,
|
|
|
},
|
|
|
],
|
|
|
zIndex: 20,
|
|
|
show: true,
|
|
|
},
|
|
|
],
|
|
|
layers: [],
|
|
|
});
|
|
|
|
|
|
map.on(mars3d.EventType.load, function (event) {
|
|
|
// 地图右键菜单
|
|
|
handlerBindMapMenus();
|
|
|
|
|
|
graphicLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing: false, // 是否自动激活编辑
|
|
|
});
|
|
|
|
|
|
graphicLayer.bindContextMenu([
|
|
|
{
|
|
|
text: '按轴平移',
|
|
|
icon: 'fa fa-pencil',
|
|
|
callback: (event) => {
|
|
|
const graphic = event.graphic;
|
|
|
let id = event.graphic.options.id;
|
|
|
|
|
|
if (moveTool) {
|
|
|
return null;
|
|
|
}
|
|
|
// 按轴移动
|
|
|
moveTool = new mars3d.thing.MatrixMove2({
|
|
|
position: graphic.position,
|
|
|
});
|
|
|
map.addThing(moveTool);
|
|
|
moveTool.on(mars3d.EventType.change, (event) => {
|
|
|
graphic.position = event.position;
|
|
|
pointMove(event, id);
|
|
|
});
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: '停止平移',
|
|
|
icon: 'fa fa-pencil',
|
|
|
callback: (event) => {
|
|
|
const graphic = event.graphic;
|
|
|
if (moveTool) {
|
|
|
map.removeThing(moveTool);
|
|
|
moveTool.destroy();
|
|
|
moveTool = null;
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: '删除',
|
|
|
icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
callback: (e) => {
|
|
|
deleteAirPoint(e);
|
|
|
},
|
|
|
},
|
|
|
]);
|
|
|
|
|
|
map.addLayer(graphicLayer);
|
|
|
|
|
|
// 参考起飞点图层
|
|
|
takeOffPointGraphicLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing: true,
|
|
|
});
|
|
|
|
|
|
takeOffPointGraphicLayer.on(mars3d.EventType.editMovePoint, function (event) {
|
|
|
takeOffPointMove(event);
|
|
|
});
|
|
|
|
|
|
map.addLayer(takeOffPointGraphicLayer);
|
|
|
|
|
|
// 航点地面投影点
|
|
|
stickGroundPointLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing: false, // 是否自动激活编辑
|
|
|
});
|
|
|
map.addLayer(stickGroundPointLayer);
|
|
|
|
|
|
// 航点连接线
|
|
|
lineGroundPointLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing: false, // 是否自动激活编辑
|
|
|
});
|
|
|
map.addLayer(lineGroundPointLayer);
|
|
|
|
|
|
// 绘制航线
|
|
|
graphicLayer.on(mars3d.EventType.click, (e) => {
|
|
|
// 设置当前选中点
|
|
|
clickPoint(e.graphic.options.id);
|
|
|
});
|
|
|
|
|
|
// 面测区图层
|
|
|
polygonGraphicLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing: true, // 是否自动激活编辑
|
|
|
});
|
|
|
// 监测面区域
|
|
|
patrolPolygonGraphicLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing: true, // 是否自动激活编辑
|
|
|
});
|
|
|
|
|
|
polygonGraphicLayer.bindContextMenu([
|
|
|
{
|
|
|
text: '删除测区',
|
|
|
icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
callback: (e) => {
|
|
|
handlerClearPolygonGraphicLayer(e);
|
|
|
},
|
|
|
},
|
|
|
]);
|
|
|
patrolPolygonGraphicLayer.bindContextMenu([
|
|
|
{
|
|
|
text: '删除测区',
|
|
|
icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
callback: (e) => {
|
|
|
handlerClearPolygonGraphicLayer(e);
|
|
|
},
|
|
|
},
|
|
|
]);
|
|
|
|
|
|
polygonGraphicLayer.on(mars3d.EventType.editMovePoint, (event) => {
|
|
|
onPolygonGraphicLayerEdit(event);
|
|
|
});
|
|
|
patrolPolygonGraphicLayer.on(mars3d.EventType.editMovePoint, (event) => {
|
|
|
console.log(event);
|
|
|
onPatrolPolygonGraphicLayerEdit(event);
|
|
|
});
|
|
|
|
|
|
map.addLayer(polygonGraphicLayer);
|
|
|
map.addLayer(patrolPolygonGraphicLayer);
|
|
|
|
|
|
// 绘制起点
|
|
|
// handlerDrawStartPoint();
|
|
|
|
|
|
if (props.airPort) {
|
|
|
setAirportPosition();
|
|
|
}
|
|
|
if (props.uavTrack) {
|
|
|
// setUAVPosition();
|
|
|
}
|
|
|
// 加载长光高清影像
|
|
|
// loadChangGuangLayer();
|
|
|
|
|
|
// 图层回显
|
|
|
if (props.editMode == 'edit' || props.editMode == 'detail') {
|
|
|
// 判断航线类型进行加载编辑
|
|
|
if (props.airLineForm.airLineType == 'waypoint') {
|
|
|
handlerEditWaypointAirLine();
|
|
|
} else if (props.airLineForm.airLineType == 'mapping2d') {
|
|
|
handlerEditPolygonAirLine();
|
|
|
}
|
|
|
}else if(props.editMode == 'autoAdd'){ // 自动航线规划
|
|
|
// handlerEditPolygonAirLine();
|
|
|
let geojson = {
|
|
|
"type": "FeatureCollection",
|
|
|
"features": [
|
|
|
{
|
|
|
"type": "Feature",
|
|
|
"geometry": {
|
|
|
"type": "Polygon",
|
|
|
"coordinates": [
|
|
|
[
|
|
|
[118.30155473, 35.13429214999999],
|
|
|
[118.30155473, 35.135213541900015],
|
|
|
[118.30068670230001, 35.135213541900015],
|
|
|
[118.30068670230001, 35.13429214999999],
|
|
|
[118.30155473, 35.13429214999999]
|
|
|
]
|
|
|
]
|
|
|
}
|
|
|
}
|
|
|
]
|
|
|
};
|
|
|
|
|
|
handlerDrawPolygon(geojson);
|
|
|
|
|
|
|
|
|
// console.log("templateKmlConfig123",props.templateKmlConfig)
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
// 监测面区域回显
|
|
|
if (props.polygonArea) {
|
|
|
handlerReportPolygonAirLine();
|
|
|
}
|
|
|
|
|
|
emits('mapOnLoad', map);
|
|
|
});
|
|
|
};
|
|
|
|
|
|
// 绑定地图右键菜单
|
|
|
const handlerBindMapMenus = () => {
|
|
|
let mapContextmenuItems = [];
|
|
|
|
|
|
if (props.airLineForm.airLineType == null) {
|
|
|
mapContextmenuItems = [
|
|
|
{
|
|
|
text: '飞行到此处',
|
|
|
icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
callback: (e) => {
|
|
|
flyToThere(e);
|
|
|
},
|
|
|
},
|
|
|
];
|
|
|
} else if (props.airLineForm.airLineType == 'waypoint') {
|
|
|
mapContextmenuItems = [
|
|
|
{
|
|
|
text: '飞行到此处',
|
|
|
icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
callback: (e) => {
|
|
|
flyToThere(e);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: '添加航点',
|
|
|
icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
callback: (e) => {
|
|
|
if (!takeOffPointPosition.value) {
|
|
|
message.warning('请先设置起飞点');
|
|
|
return null;
|
|
|
}
|
|
|
handlerDrawPoint(e);
|
|
|
},
|
|
|
},
|
|
|
];
|
|
|
} else if (props.airLineForm.airLineType == 'mapping2d') {
|
|
|
mapContextmenuItems = [
|
|
|
{
|
|
|
text: '飞行到此处',
|
|
|
icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
callback: (e) => {
|
|
|
flyToThere(e);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: '添加面区域',
|
|
|
icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
callback: (e) => {
|
|
|
if (!polygonAirForm.value.startingPoint) {
|
|
|
message.warning('请先设置起飞点');
|
|
|
return null;
|
|
|
}
|
|
|
handlerDrawPolygon();
|
|
|
},
|
|
|
},
|
|
|
];
|
|
|
}
|
|
|
// if (props.drawArea) {
|
|
|
// mapContextmenuItems = [
|
|
|
// {
|
|
|
// text: '添加面区域',
|
|
|
// icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
// callback: (e) => {
|
|
|
// handlerDrawPolygonPatrol();
|
|
|
// },
|
|
|
// },
|
|
|
// ];
|
|
|
// }
|
|
|
|
|
|
map.bindContextMenu(mapContextmenuItems);
|
|
|
};
|
|
|
|
|
|
///////////////////////////////图层和影像加载////////////////////////////////////////////
|
|
|
|
|
|
// 加载长光卫星高分影像
|
|
|
const loadChangGuangLayer = () => {
|
|
|
var layer = new mars3d.layer.XyzLayer({
|
|
|
url: 'https://api.jl1mall.com/getMap/{z}/{x}/{reverseY}',
|
|
|
queryParameters: {
|
|
|
mk: '73ad26c4aa6957eef051ecc5a15308b4',
|
|
|
tk: '5538f710dfc641048a8bdf1a7f705cd1',
|
|
|
pro: '9297426cbe4c4ac2a01ca228a4ad30f7',
|
|
|
vf: 0,
|
|
|
},
|
|
|
minimumLevel: 1,
|
|
|
maximumLevel: 18,
|
|
|
zIndex: 2,
|
|
|
});
|
|
|
map.addLayer(layer);
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////飞行结果加载//////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////参考起飞点////////////////////////////////////////////
|
|
|
|
|
|
// 全局参考起飞点 数据格式:[lng,lat,alt]
|
|
|
const takeOffPointPosition = ref(null);
|
|
|
|
|
|
// 设置起飞点
|
|
|
const setTakeOffPoint = async () => {
|
|
|
takeOffPointGraphicLayer ? takeOffPointGraphicLayer.clear() : null;
|
|
|
|
|
|
const graphic = await takeOffPointGraphicLayer.startDraw({
|
|
|
type: 'billboardP',
|
|
|
style: {
|
|
|
image: '/map/start.png',
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '参考起飞点',
|
|
|
font_size: 16,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -50,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
|
|
|
takeOffPointPosition.value = graphic.toJSON().position;
|
|
|
|
|
|
props.templateKmlConfig.missionConfig.takeOffRefPoint =
|
|
|
takeOffPointPosition.value[1] +
|
|
|
',' +
|
|
|
takeOffPointPosition.value[0] +
|
|
|
',' +
|
|
|
takeOffPointPosition.value[2];
|
|
|
|
|
|
polygonAirForm.value.startingPoint = graphic.toJSON().position;
|
|
|
|
|
|
// 设置表单数据
|
|
|
props.airLineForm.taskOffLng = takeOffPointPosition.value[0];
|
|
|
props.airLineForm.taskOffLat = takeOffPointPosition.value[1];
|
|
|
|
|
|
// 更新航线
|
|
|
updatePolygonLineByParams();
|
|
|
};
|
|
|
|
|
|
// 参考起飞点移动
|
|
|
const takeOffPointMove = (e) => {
|
|
|
let res = handlerGetLngLatHeight(e);
|
|
|
|
|
|
takeOffPointPosition.value = [res.lng, res.lat, res.alt];
|
|
|
polygonAirForm.value.startingPoint = [res.lng, res.lat, res.alt];
|
|
|
|
|
|
// 设置表单数据
|
|
|
props.airLineForm.taskOffLng = takeOffPointPosition.value[0];
|
|
|
props.airLineForm.taskOffLat = takeOffPointPosition.value[1];
|
|
|
|
|
|
props.templateKmlConfig.missionConfig.takeOffRefPoint =
|
|
|
takeOffPointPosition.value[1].toFixed(8) +
|
|
|
',' +
|
|
|
takeOffPointPosition.value[0].toFixed(8) +
|
|
|
',' +
|
|
|
takeOffPointPosition.value[2].toFixed(2);
|
|
|
|
|
|
// 根据航线类型更新航线
|
|
|
if (props.airLineForm.airLineType == 'mapping2d') {
|
|
|
updatePolygonLineByParams();
|
|
|
} else if (props.airLineForm.airLineType == 'waypoint') {
|
|
|
handlerDrawLine();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 处理Graphic鼠标事件返回信息
|
|
|
const handlerGetLngLatHeight = (e) => {
|
|
|
let cartographic = mars3d.Cesium.Cartographic.fromCartesian(e.cartesian);
|
|
|
let longitude = mars3d.Cesium.Math.toDegrees(cartographic.longitude);
|
|
|
let latitude = mars3d.Cesium.Math.toDegrees(cartographic.latitude);
|
|
|
let height = cartographic.height;
|
|
|
|
|
|
let res = {
|
|
|
lng: longitude,
|
|
|
lat: latitude,
|
|
|
alt: height,
|
|
|
};
|
|
|
return res;
|
|
|
};
|
|
|
|
|
|
///////////////////////////////面状航线计算////////////////////////////////////////////
|
|
|
|
|
|
// 全局面状测区
|
|
|
const polygonGeoJson = ref();
|
|
|
|
|
|
// 计算参数
|
|
|
const polygonCalculateParams = ref({
|
|
|
gsd: 0,
|
|
|
overlapY: 70,
|
|
|
overlapX: 80,
|
|
|
overlapAngle: 0,
|
|
|
height: 0,
|
|
|
spacing: 0,
|
|
|
safeyFlyHeight: 20,
|
|
|
});
|
|
|
|
|
|
// 绘制面状测区
|
|
|
const handlerDrawPolygon = async (geojson:any = null) => {
|
|
|
if(geojson!=null){
|
|
|
|
|
|
// 解析和设置参考起飞点
|
|
|
|
|
|
let takeoffArray = props.templateKmlConfig.missionConfig.takeOffRefPoint.split(',');
|
|
|
|
|
|
takeOffPointPosition.value = [
|
|
|
parseFloat(takeoffArray[1]),
|
|
|
parseFloat(takeoffArray[0]),
|
|
|
parseFloat(takeoffArray[2]),
|
|
|
];
|
|
|
|
|
|
polygonAirForm.value.startingPoint = [
|
|
|
parseFloat(takeoffArray[1]),
|
|
|
parseFloat(takeoffArray[0]),
|
|
|
parseFloat(takeoffArray[2]),
|
|
|
];
|
|
|
|
|
|
takeOffPointGraphicLayer ? takeOffPointGraphicLayer.clear() : null;
|
|
|
|
|
|
let startFlyGraphic = new mars3d.graphic.BillboardEntity({
|
|
|
position: takeOffPointPosition.value,
|
|
|
style: {
|
|
|
image: '/map/start.png',
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '参考起飞点',
|
|
|
font_size: 16,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -50,
|
|
|
},
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
|
|
|
takeOffPointGraphicLayer.addGraphic(startFlyGraphic);
|
|
|
|
|
|
polygonGraphicLayer.loadGeoJSON(geojson, {
|
|
|
type: 'polygon',
|
|
|
flyTo: true,
|
|
|
style: {
|
|
|
color: '#408eff',
|
|
|
opacity: 0.3,
|
|
|
outline: true,
|
|
|
outlineColor: '#408eff',
|
|
|
outlineWidth: 3.0,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
|
|
|
|
|
|
let coordinates = geojson.features[0].geometry[0];
|
|
|
polygonGeoJson.value = coordinates;
|
|
|
let polygon = turf.polygon([coordinates]);
|
|
|
let polygonWkt = GeojsonToWkt(polygon['geometry']);
|
|
|
// props.airLineForm.flyToFirstPointMode = polygonWkt;
|
|
|
// // 航线间距
|
|
|
// let spceing = parseFloat(polygonCalculateParams.value?.spacing) / 10000;
|
|
|
// // 初始化角度
|
|
|
// let direction = props.templateKmlConfig.Folder.Placemark.direction ? props.templateKmlConfig.Folder.Placemark.direction : 0;
|
|
|
// // 计算航线
|
|
|
// let lines = generateScanLines(polygon, spceing, direction);
|
|
|
// // 计算测区面积、航线长度
|
|
|
// CalculateAreaInfo(polygon, lines);
|
|
|
// // 绘制面航线
|
|
|
// handlerDrawPolygonLine(lines);
|
|
|
// // 计算边长等信息
|
|
|
// handlerGetPolygonBorderInfo(polygonGeoJson.value);
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
const graphic = await polygonGraphicLayer.startDraw({
|
|
|
type: 'polygon',
|
|
|
style: {
|
|
|
color: '#408eff',
|
|
|
opacity: 0.3,
|
|
|
outline: true,
|
|
|
outlineColor: '#408eff',
|
|
|
outlineWidth: 3.0,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
let coordinates = graphic.toJSON().positions;
|
|
|
|
|
|
coordinates.push(coordinates[0]);
|
|
|
polygonGeoJson.value = coordinates;
|
|
|
let polygon = turf.polygon([coordinates]);
|
|
|
let polygonWkt = GeojsonToWkt(polygon['geometry']);
|
|
|
props.airLineForm.flyToFirstPointMode = polygonWkt;
|
|
|
// 航线间距
|
|
|
let spceing = parseFloat(polygonCalculateParams.value?.spacing) / 10000;
|
|
|
// 初始化角度
|
|
|
let direction = props.templateKmlConfig.Folder.Placemark.direction ? props.templateKmlConfig.Folder.Placemark.direction : 0;
|
|
|
// 计算航线
|
|
|
let lines = generateScanLines(polygon, spceing, direction);
|
|
|
// 计算测区面积、航线长度
|
|
|
CalculateAreaInfo(polygon, lines);
|
|
|
// 绘制面航线
|
|
|
handlerDrawPolygonLine(lines);
|
|
|
// 计算边长等信息
|
|
|
handlerGetPolygonBorderInfo(polygonGeoJson.value);
|
|
|
}
|
|
|
};
|
|
|
// 绘制监测区域
|
|
|
const handlerDrawPolygonPatrol = async () => {
|
|
|
const graphic = await patrolPolygonGraphicLayer.startDraw({
|
|
|
type: 'polygon',
|
|
|
style: {
|
|
|
color: '#408eff',
|
|
|
opacity: 0.3,
|
|
|
outline: true,
|
|
|
outlineColor: '#408eff',
|
|
|
outlineWidth: 3.0,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
let coordinates = graphic.toJSON().positions;
|
|
|
coordinates.push(coordinates[0]);
|
|
|
polygonGeoJson.value = coordinates;
|
|
|
emits('areaData', polygonGeoJson.value);
|
|
|
};
|
|
|
// 测区编辑后重新计算航线
|
|
|
const onPolygonGraphicLayerEdit = (e) => {
|
|
|
let coordinates = e.graphic.toJSON().positions;
|
|
|
|
|
|
if (props.editMode == 'add') {
|
|
|
coordinates.push(coordinates[0]);
|
|
|
}
|
|
|
|
|
|
polygonGeoJson.value = coordinates;
|
|
|
|
|
|
let polygon = turf.polygon([coordinates]);
|
|
|
|
|
|
let polygonWkt = GeojsonToWkt(polygon['geometry']);
|
|
|
props.airLineForm.flyToFirstPointMode = polygonWkt;
|
|
|
|
|
|
let spceing = parseFloat(polygonCalculateParams.value?.spacing) / 10000;
|
|
|
let direction = props.templateKmlConfig.Folder.Placemark.direction;
|
|
|
let lines = generateScanLines(polygon, spceing, direction);
|
|
|
|
|
|
// 计算面积
|
|
|
CalculateAreaInfo(polygon, lines);
|
|
|
// 绘制面航线
|
|
|
handlerDrawPolygonLine(lines);
|
|
|
// 计算边长等信息
|
|
|
handlerGetPolygonBorderInfo(polygonGeoJson.value);
|
|
|
};
|
|
|
|
|
|
// 监测区域编辑后重新赋值
|
|
|
const onPatrolPolygonGraphicLayerEdit = (e) => {
|
|
|
let coordinates = e.graphic.toJSON().positions;
|
|
|
if (props.editMode == 'add') {
|
|
|
coordinates.push(coordinates[0]);
|
|
|
}
|
|
|
polygonGeoJson.value = coordinates;
|
|
|
emits('areaData', polygonGeoJson.value);
|
|
|
};
|
|
|
// 绘制面航线
|
|
|
const handlerDrawPolygonLine = (lines) => {
|
|
|
// 设置首航点
|
|
|
let firstAirLinePoint = polygonGraphicLayer.getGraphicById('polygon-node-1');
|
|
|
if (firstAirLinePoint) {
|
|
|
firstAirLinePoint.setOptions({
|
|
|
position: lines.geometry.coordinates[0],
|
|
|
});
|
|
|
} else {
|
|
|
const graphic = new mars3d.graphic.BillboardEntity({
|
|
|
id: 'polygon-node-1',
|
|
|
name: '航点',
|
|
|
position: lines.geometry.coordinates[0],
|
|
|
style: {
|
|
|
image: '/map/node.png',
|
|
|
scale: 1,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '',
|
|
|
font_size: 14,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -35,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
polygonGraphicLayer.addGraphic(graphic);
|
|
|
}
|
|
|
|
|
|
// 判断飞行模式 设置航点高度
|
|
|
lines.geometry.coordinates.unshift([
|
|
|
polygonAirForm.value.startingPoint[0],
|
|
|
polygonAirForm.value.startingPoint[1],
|
|
|
polygonAirForm.value.startingPoint[2] +
|
|
|
parseFloat(polygonCalculateParams.value.safeyFlyHeight),
|
|
|
]);
|
|
|
|
|
|
// 链接起点
|
|
|
lines.geometry.coordinates.unshift(polygonAirForm.value.startingPoint);
|
|
|
|
|
|
if (polygonLineGraphicLayer) {
|
|
|
polygonLineGraphicLayer.clear();
|
|
|
polygonLineGraphicLayer.loadGeoJSON(lines);
|
|
|
} else {
|
|
|
polygonLineGraphicLayer = new mars3d.layer.GeoJsonLayer({
|
|
|
name: '面航线',
|
|
|
data: lines,
|
|
|
symbol: {
|
|
|
type: 'polyline',
|
|
|
styleOptions: {
|
|
|
arcType: Cesium.ArcType.GEODESIC, // 使用大地线
|
|
|
width: 2.0,
|
|
|
color: '#0aed8b',
|
|
|
},
|
|
|
},
|
|
|
flyTo: true,
|
|
|
});
|
|
|
map.addLayer(polygonLineGraphicLayer);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 计算面航线
|
|
|
function generateScanLines(polygon, spacing, angle = 0) {
|
|
|
if (!turf.booleanValid(polygon)) throw new Error('无效的多边形');
|
|
|
|
|
|
spacing = Math.abs(spacing);
|
|
|
|
|
|
// 获取多边形的旋转边界框
|
|
|
const bbox = turf.bbox(polygon);
|
|
|
const center = turf.center(polygon).geometry.coordinates;
|
|
|
|
|
|
// 计算需要生成的线数量(加缓冲确保完全覆盖)
|
|
|
const diagLength = turf.distance(
|
|
|
turf.point([bbox[0], bbox[1]]),
|
|
|
turf.point([bbox[2], bbox[3]]),
|
|
|
);
|
|
|
const lineCount = Math.ceil(diagLength / spacing) + 2;
|
|
|
|
|
|
// 生成基础水平线
|
|
|
const lines = [];
|
|
|
|
|
|
for (let i = -1; i <= lineCount; i++) {
|
|
|
const y = bbox[1] + i * spacing * 0.11 - spacing * 0.11;
|
|
|
lines.push(
|
|
|
turf.lineString([
|
|
|
[bbox[0] - spacing, y],
|
|
|
[bbox[2] + spacing, y],
|
|
|
]),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
// 旋转线条到指定角度
|
|
|
const rotatedLines = lines.map((line) =>
|
|
|
turf.transformRotate(line, angle - 90, { pivot: center }),
|
|
|
);
|
|
|
|
|
|
// 裁剪线条到多边形内并处理结果
|
|
|
const coverageLines = [];
|
|
|
|
|
|
rotatedLines.forEach((line) => {
|
|
|
try {
|
|
|
const intersection = turf.lineIntersect(line, polygon);
|
|
|
|
|
|
if (intersection.features.length >= 2) {
|
|
|
// 按与线起点距离排序交点
|
|
|
const sortedPoints = intersection.features
|
|
|
.map((f) => f.geometry.coordinates)
|
|
|
.sort(
|
|
|
(a, b) =>
|
|
|
turf.distance(line.geometry.coordinates[0], turf.point(a)) -
|
|
|
turf.distance(line.geometry.coordinates[0], turf.point(b)),
|
|
|
);
|
|
|
|
|
|
// 创建连接最远两个交点的线段
|
|
|
coverageLines.push(
|
|
|
turf.lineString([sortedPoints[0], sortedPoints[sortedPoints.length - 1]]),
|
|
|
);
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.warn('处理线段时出错:', e);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
let connectedLine = connectLinesManual(turf.featureCollection(coverageLines));
|
|
|
|
|
|
// 将航点提取并添加到airPoints
|
|
|
airPoints.value = [];
|
|
|
|
|
|
connectedLine.geometry.coordinates?.forEach((item, index) => {
|
|
|
let point = {
|
|
|
id: index,
|
|
|
lng: item[0],
|
|
|
lat: item[1],
|
|
|
alt: item[2],
|
|
|
aircraftHorizontalAngle: 0,
|
|
|
cameraHorizontalAngle: 0,
|
|
|
cameraVerticalAngle: 0,
|
|
|
focalLength: 1,
|
|
|
};
|
|
|
|
|
|
airPoints.value?.push(point);
|
|
|
});
|
|
|
|
|
|
// 倒数第2个点
|
|
|
let penultimatePoint = JSON.parse(JSON.stringify(airPoints.value[airPoints.value.length - 1]));
|
|
|
penultimatePoint.id = penultimatePoint.id + 1;
|
|
|
airPoints.value?.push(penultimatePoint);
|
|
|
|
|
|
// 添加测区中心点 (最后1个点)
|
|
|
let turfPolygon = turf.polygon([polygonGeoJson.value]);
|
|
|
|
|
|
let polygonCenter = turf.centroid(turfPolygon);
|
|
|
|
|
|
let lastPoint = {
|
|
|
id: airPoints.value[airPoints.value.length - 1].id + 1,
|
|
|
lng: polygonCenter.geometry.coordinates[0],
|
|
|
lat: polygonCenter.geometry.coordinates[1],
|
|
|
alt: airPoints.value[airPoints.value.length - 1].alt,
|
|
|
aircraftHorizontalAngle: 0,
|
|
|
cameraHorizontalAngle: 0,
|
|
|
cameraVerticalAngle: 0,
|
|
|
focalLength: 1,
|
|
|
};
|
|
|
airPoints.value?.push(lastPoint);
|
|
|
|
|
|
// 添加最后一个点到线数据中
|
|
|
connectedLine.geometry.coordinates.push([lastPoint.lng, lastPoint.lat, lastPoint.alt]);
|
|
|
|
|
|
return connectedLine;
|
|
|
}
|
|
|
|
|
|
// 处理面航线
|
|
|
const connectLinesManual = (lines) => {
|
|
|
// 确保输入是FeatureCollection
|
|
|
if (lines.type !== 'FeatureCollection') {
|
|
|
lines = turf.featureCollection([lines]);
|
|
|
}
|
|
|
|
|
|
// 收集所有坐标点
|
|
|
let allCoords = [];
|
|
|
lines.features.forEach((line, index) => {
|
|
|
// 相对起飞点高度
|
|
|
let relativeHeight =
|
|
|
takeOffPointPosition.value[2] + parseFloat(polygonCalculateParams.value.height);
|
|
|
|
|
|
line.geometry.coordinates?.forEach((item, idx) => {
|
|
|
line.geometry.coordinates[idx].push(relativeHeight);
|
|
|
});
|
|
|
|
|
|
if (line.geometry.type === 'LineString' && index % 2 == 0) {
|
|
|
allCoords = allCoords.concat(line.geometry.coordinates.reverse());
|
|
|
} else {
|
|
|
allCoords = allCoords.concat(line.geometry.coordinates);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 移除连续重复的点
|
|
|
const cleanedCoords = [];
|
|
|
if (allCoords.length > 0) {
|
|
|
cleanedCoords.push(allCoords[0]);
|
|
|
for (let i = 1; i < allCoords.length; i++) {
|
|
|
const prev = cleanedCoords[cleanedCoords.length - 1];
|
|
|
if (prev[0] !== allCoords[i][0] || prev[1] !== allCoords[i][1]) {
|
|
|
cleanedCoords.push(allCoords[i]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return turf.lineString(cleanedCoords);
|
|
|
};
|
|
|
|
|
|
// 标绘面状航线起点
|
|
|
const handlerDrawStartPoint = async () => {
|
|
|
graphic = await graphicLayer.startDraw({
|
|
|
type: 'billboard',
|
|
|
style: {
|
|
|
image: '/map/start.png',
|
|
|
scale: 0.7,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '无人机起始位置',
|
|
|
font_size: 16,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -60,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
// 设置贴地点 和 连接线
|
|
|
};
|
|
|
|
|
|
// 计算面状测区面积、长度、完成用时、拍摄数量
|
|
|
const CalculateAreaInfo = (polygon, lines) => {
|
|
|
// 测区面积
|
|
|
airInfo.value.area = turf.area(polygon).toFixed(2);
|
|
|
|
|
|
// 航线长度
|
|
|
airInfo.value.length = turf.length(lines).toFixed(2);
|
|
|
|
|
|
// 预计用时
|
|
|
airInfo.value.time = ((airInfo.value.length * 1000) / polygonAirForm.value.speed / 60).toFixed(
|
|
|
2,
|
|
|
);
|
|
|
|
|
|
// 照片数量
|
|
|
};
|
|
|
|
|
|
// 删除面状测区 和 面状航线
|
|
|
const handlerClearPolygonGraphicLayer = () => {
|
|
|
polygonGraphicLayer ? polygonGraphicLayer.clear() : null;
|
|
|
|
|
|
polygonLineGraphicLayer ? polygonLineGraphicLayer.clear() : null;
|
|
|
|
|
|
patrolPolygonGraphicLayer ? patrolPolygonGraphicLayer.clear() : null;
|
|
|
|
|
|
textLabelGraphicLayer ? textLabelGraphicLayer.clear() : null;
|
|
|
|
|
|
polygonGeoJson.value = null;
|
|
|
|
|
|
airInfo.value = {
|
|
|
area: 0,
|
|
|
length: 0,
|
|
|
time: 0,
|
|
|
picture: '- -',
|
|
|
};
|
|
|
};
|
|
|
|
|
|
// 面状航线测区、参数改变
|
|
|
const calculatParamChange = (params) => {
|
|
|
polygonCalculateParams.value = params;
|
|
|
|
|
|
if (polygonGeoJson.value) {
|
|
|
let polygon = turf.polygon([polygonGeoJson.value]);
|
|
|
let spceing = parseFloat(params.spacing) / 10000;
|
|
|
let angle = parseFloat(params.overlapAngle);
|
|
|
// 生成航线
|
|
|
let lines = generateScanLines(polygon, spceing, angle);
|
|
|
// 计算面积 长度
|
|
|
CalculateAreaInfo(polygon, lines);
|
|
|
// 绘制面航线
|
|
|
handlerDrawPolygonLine(lines);
|
|
|
// 计算边长等信息
|
|
|
handlerGetPolygonBorderInfo(polygonGeoJson.value);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 根据参数更新面状航线
|
|
|
const updatePolygonLineByParams = () => {
|
|
|
if (polygonGeoJson.value && polygonCalculateParams.value) {
|
|
|
let polygon = turf.polygon([polygonGeoJson.value]);
|
|
|
let spceing = parseFloat(polygonCalculateParams.value.spacing) / 10000;
|
|
|
let angle = parseFloat(polygonCalculateParams.value.overlapAngle);
|
|
|
// 生成航线
|
|
|
let lines = generateScanLines(polygon, spceing, angle);
|
|
|
// 计算面积 长度
|
|
|
CalculateAreaInfo(polygon, lines);
|
|
|
// 绘制面航线
|
|
|
handlerDrawPolygonLine(lines);
|
|
|
// 计算边长等信息
|
|
|
handlerGetPolygonBorderInfo(polygonGeoJson.value);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 计算绘制的多边形每条线的长度和中心点
|
|
|
const polygonBorderInfo = ref([]);
|
|
|
|
|
|
// 计算测区各边长
|
|
|
const handlerGetPolygonBorderInfo = (polygonCoords) => {
|
|
|
// 创建Turf多边形对象
|
|
|
let polygon = turf.polygon([polygonCoords]);
|
|
|
|
|
|
// 1. 计算边长
|
|
|
let coordinates = polygon.geometry.coordinates[0];
|
|
|
let edgeLengths = [];
|
|
|
|
|
|
for (let i = 0; i < coordinates.length - 1; i++) {
|
|
|
let start = coordinates[i];
|
|
|
let end = coordinates[i + 1];
|
|
|
let distance = turf.distance(turf.point(start), turf.point(end), { units: 'meters' });
|
|
|
|
|
|
let midpoint = turf.midpoint(start, end);
|
|
|
|
|
|
edgeLengths.push({
|
|
|
length: distance.toFixed(2),
|
|
|
center: midpoint?.geometry?.coordinates,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
handlerLoadtextLabelGraphicLayer(edgeLengths);
|
|
|
return edgeLengths;
|
|
|
};
|
|
|
|
|
|
// 绘制文本标注
|
|
|
const handlerLoadtextLabelGraphicLayer = (info) => {
|
|
|
if (textLabelGraphicLayer == null) {
|
|
|
textLabelGraphicLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing: false,
|
|
|
});
|
|
|
map.addLayer(textLabelGraphicLayer);
|
|
|
} else {
|
|
|
textLabelGraphicLayer.clear();
|
|
|
}
|
|
|
|
|
|
|
|
|
// 绘制文本标注
|
|
|
const handlerLoadtextLabelGraphicLayer = (info) => {
|
|
|
|
|
|
if(textLabelGraphicLayer == null){
|
|
|
textLabelGraphicLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing:false
|
|
|
})
|
|
|
map.addLayer(textLabelGraphicLayer);
|
|
|
}else{
|
|
|
textLabelGraphicLayer.clear();
|
|
|
}
|
|
|
|
|
|
info?.forEach((item,index)=>{
|
|
|
const graphic = new mars3d.graphic.LabelEntity({
|
|
|
position: [item.center[0], item.center[1], 0],
|
|
|
style: {
|
|
|
text: item.length+"m",
|
|
|
font_size: 15,
|
|
|
scale: 1,
|
|
|
font_family: "微软雅黑",
|
|
|
color: "#ffffff",
|
|
|
outline: true,
|
|
|
outlineColor: "#000000",
|
|
|
outlineWidth: 2,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
visibleDepth: false,
|
|
|
clampToGround:true,
|
|
|
},
|
|
|
attr: { remark: "示例1" }
|
|
|
})
|
|
|
textLabelGraphicLayer.addGraphic(graphic)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 编辑回显面状航线
|
|
|
// 编辑回显航线
|
|
|
const handlerEditPolygonAirLine = async () => {
|
|
|
|
|
|
// 解析和设置参考起飞点
|
|
|
|
|
|
let takeoffArray = props.templateKmlConfig.missionConfig.takeOffRefPoint.split(',');
|
|
|
takeOffPointPosition.value = [
|
|
|
parseFloat(takeoffArray[1]),
|
|
|
parseFloat(takeoffArray[0]),
|
|
|
parseFloat(takeoffArray[2]),
|
|
|
];
|
|
|
|
|
|
polygonAirForm.value.startingPoint = [
|
|
|
parseFloat(takeoffArray[1]),
|
|
|
parseFloat(takeoffArray[0]),
|
|
|
parseFloat(takeoffArray[2]),
|
|
|
];
|
|
|
|
|
|
takeOffPointGraphicLayer ? takeOffPointGraphicLayer.clear() : null;
|
|
|
|
|
|
let startFlyGraphic = new mars3d.graphic.BillboardEntity({
|
|
|
position: takeOffPointPosition.value,
|
|
|
style: {
|
|
|
image: '/map/start.png',
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '参考起飞点',
|
|
|
font_size: 16,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -50,
|
|
|
},
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
|
|
|
takeOffPointGraphicLayer.addGraphic(startFlyGraphic);
|
|
|
|
|
|
// 处理 和 加载测区数据
|
|
|
|
|
|
let coordinateArray =
|
|
|
props.templateKmlConfig.Folder.Placemark.Polygon.outerBoundaryIs.LinearRing.coordinates.split(
|
|
|
'\n',
|
|
|
);
|
|
|
|
|
|
let geomtryCoorinate = [];
|
|
|
|
|
|
coordinateArray.forEach((item, index) => {
|
|
|
let trimStr = item.trim();
|
|
|
let arr = trimStr.split(',');
|
|
|
for (let i = 0; i < arr.length; i++) {
|
|
|
arr[i] = parseFloat(arr[i]);
|
|
|
}
|
|
|
geomtryCoorinate.push(arr);
|
|
|
});
|
|
|
|
|
|
geomtryCoorinate.push(geomtryCoorinate[0]);
|
|
|
|
|
|
let geometry = {
|
|
|
type: 'Polygon',
|
|
|
coordinates: [geomtryCoorinate],
|
|
|
};
|
|
|
|
|
|
// let areaJson = WktToGeojson(props.airLineForm.flyToFirstPointMode)
|
|
|
polygonGeoJson.value = geometry.coordinates[0];
|
|
|
|
|
|
let geojsonData = {
|
|
|
type: 'FeatureCollection',
|
|
|
features: [
|
|
|
{
|
|
|
type: 'Feature',
|
|
|
geometry: geometry,
|
|
|
},
|
|
|
],
|
|
|
};
|
|
|
|
|
|
polygonGraphicLayer ? polygonGraphicLayer.clear() : null;
|
|
|
|
|
|
polygonGraphicLayer.loadGeoJSON(geojsonData, {
|
|
|
type: 'polygon',
|
|
|
flyTo: true,
|
|
|
style: {
|
|
|
color: '#408eff',
|
|
|
opacity: 0.3,
|
|
|
outline: true,
|
|
|
outlineColor: '#408eff',
|
|
|
outlineWidth: 3.0,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
|
|
|
// 加载文本标注
|
|
|
handlerGetPolygonBorderInfo(geometry.coordinates[0]);
|
|
|
|
|
|
// 加载航线
|
|
|
// let placemark = props.waylineInfo?.Folder?.Placemark
|
|
|
|
|
|
// placemark?.forEach((item, index) => {
|
|
|
// let coordinate = item.Point.coordinates.split(',');
|
|
|
// let airPointInfo = {
|
|
|
// id: item.index,
|
|
|
// name: '航点',
|
|
|
// lng: coordinate[0],
|
|
|
// lat: coordinate[1],
|
|
|
// alt: item.executeHeight,
|
|
|
// aircraftHorizontalAngle: 0,
|
|
|
// cameraHorizontalAngle: 0,
|
|
|
// cameraVerticalAngle: 0,
|
|
|
// focalLength: 2,
|
|
|
// };
|
|
|
// airPoints.value?.push(airPointInfo);
|
|
|
// });
|
|
|
|
|
|
// let coordinates = [];
|
|
|
|
|
|
// airPoints.value?.forEach((item, index) => {
|
|
|
// coordinates.push([item.lng, item.lat]);
|
|
|
// });
|
|
|
|
|
|
// let line = turf.lineString(coordinates);
|
|
|
|
|
|
// handlerDrawPolygonLine(line);
|
|
|
};
|
|
|
|
|
|
// 监测区域面图层回显
|
|
|
const handlerReportPolygonAirLine = () => {
|
|
|
let geometry = {
|
|
|
type: 'Polygon',
|
|
|
coordinates: [props.polygonArea],
|
|
|
};
|
|
|
let geojsonData = {
|
|
|
type: 'FeatureCollection',
|
|
|
features: [
|
|
|
{
|
|
|
type: 'Feature',
|
|
|
geometry: geometry,
|
|
|
},
|
|
|
],
|
|
|
};
|
|
|
|
|
|
patrolPolygonGraphicLayer ? patrolPolygonGraphicLayer.clear() : null;
|
|
|
|
|
|
patrolPolygonGraphicLayer.loadGeoJSON(geojsonData, {
|
|
|
type: 'polygon',
|
|
|
flyTo: true,
|
|
|
style: {
|
|
|
color: '#408eff',
|
|
|
opacity: 0.3,
|
|
|
outline: true,
|
|
|
outlineColor: '#408eff',
|
|
|
outlineWidth: 3.0,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
};
|
|
|
|
|
|
///////////////////////////////航点航线计算////////////////////////////////////////////
|
|
|
|
|
|
// 航点移动
|
|
|
const pointMove = (e, id) => {
|
|
|
const cartographic = mars3d.Cesium.Cartographic.fromCartesian(e.position);
|
|
|
const longitude = mars3d.Cesium.Math.toDegrees(cartographic.longitude);
|
|
|
const latitude = mars3d.Cesium.Math.toDegrees(cartographic.latitude);
|
|
|
const height = cartographic.height; // 高度(米)
|
|
|
let stickGraphic = stickGroundPointLayer.getGraphicById('stick' + id);
|
|
|
if (stickGraphic) {
|
|
|
stickGraphic.setOptions({
|
|
|
position: [longitude, latitude],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
pixelSize: 8,
|
|
|
outline: true,
|
|
|
outlineColor: '#f5f5f5',
|
|
|
outlineWidth: 1,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
let lineGraphic = lineGroundPointLayer.getGraphicById('line' + id);
|
|
|
if (lineGraphic) {
|
|
|
lineGraphic.setOptions({
|
|
|
positions: [
|
|
|
[longitude, latitude, height],
|
|
|
[longitude, latitude, 0],
|
|
|
],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
width: 1,
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 更新坐标数据
|
|
|
airPoints.value?.forEach((item, index) => {
|
|
|
if (item.id == id) {
|
|
|
airPoints.value[index].lng = longitude;
|
|
|
airPoints.value[index].lat = latitude;
|
|
|
airPoints.value[index].alt = height;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 更新航线
|
|
|
handlerDrawLine();
|
|
|
};
|
|
|
|
|
|
// 绘制航线
|
|
|
const handlerDrawLine = () => {
|
|
|
let positions = [];
|
|
|
|
|
|
airPoints.value?.forEach((item, index) => {
|
|
|
positions.push([item.lng, item.lat, item.alt]);
|
|
|
});
|
|
|
|
|
|
positions.unshift([
|
|
|
takeOffPointPosition.value[0],
|
|
|
takeOffPointPosition.value[1],
|
|
|
airPoints.value[0].alt,
|
|
|
]);
|
|
|
|
|
|
positions.unshift([
|
|
|
takeOffPointPosition.value[0],
|
|
|
takeOffPointPosition.value[1],
|
|
|
takeOffPointPosition.value[2],
|
|
|
]);
|
|
|
|
|
|
// 判断是否已经绘制
|
|
|
if (positions.length > 1) {
|
|
|
let lineGraphic = graphicLayer.getGraphicById('pointsLine');
|
|
|
|
|
|
if (lineGraphic) {
|
|
|
lineGraphic.setOptions({
|
|
|
id: 'pointsLine',
|
|
|
positions: positions,
|
|
|
style: {
|
|
|
width: 2,
|
|
|
color: '#3388ff',
|
|
|
},
|
|
|
});
|
|
|
} else {
|
|
|
const graphic = new mars3d.graphic.PolylineEntity({
|
|
|
id: 'pointsLine',
|
|
|
positions: positions,
|
|
|
style: {
|
|
|
width: 2,
|
|
|
color: '#3388ff',
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(graphic);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 计算航线长度
|
|
|
// let lineString = turf.lineString(positions);
|
|
|
// lineInfo.value.length = turf.length(lineString).toFixed(2);
|
|
|
};
|
|
|
|
|
|
// 全局航点数组
|
|
|
const uavPoints = ref([]);
|
|
|
|
|
|
// 绘制航点
|
|
|
const handlerDrawPoint = (e) => {
|
|
|
if (moveTool) {
|
|
|
moveTool.destroy();
|
|
|
moveTool = null;
|
|
|
}
|
|
|
// 设置航线默认高度
|
|
|
let position = mars3d.LngLatPoint.fromCartesian(e.position);
|
|
|
let uuid = airPoints.value.length + 1;
|
|
|
|
|
|
// 获取默认航线高度
|
|
|
let globalHeight = props.templateKmlConfig.Folder.globalHeight;
|
|
|
|
|
|
// 航点三维模型
|
|
|
let uavAngleGraphic = new mars3d.graphic.ModelEntity({
|
|
|
id: uuid,
|
|
|
name: '航向',
|
|
|
position: [position._lng, position._lat, globalHeight],
|
|
|
style: {
|
|
|
url: '/map/uav-angle.gltf',
|
|
|
scale: 0.1,
|
|
|
heading: 90,
|
|
|
distanceDisplayCondition: true,
|
|
|
distanceDisplayCondition_near: 0,
|
|
|
distanceDisplayPoint: {
|
|
|
color: '#00ff00',
|
|
|
pixelSize: 8,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(uavAngleGraphic);
|
|
|
|
|
|
// 地面投影点
|
|
|
let stickGraphic = new mars3d.graphic.PointEntity({
|
|
|
id: 'stick' + uuid,
|
|
|
position: [position._lng, position._lat],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
pixelSize: 8,
|
|
|
outline: true,
|
|
|
outlineColor: '#f5f5f5',
|
|
|
outlineWidth: 1,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
stickGroundPointLayer.addGraphic(stickGraphic);
|
|
|
|
|
|
// 航点 投影点连接线
|
|
|
let lineGraphic = new mars3d.graphic.PolylineEntity({
|
|
|
id: 'line' + uuid,
|
|
|
positions: [
|
|
|
[position._lng, position._lat, globalHeight],
|
|
|
[position._lng, position._lat, 0],
|
|
|
],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
width: 1,
|
|
|
},
|
|
|
});
|
|
|
lineGroundPointLayer.addGraphic(lineGraphic);
|
|
|
|
|
|
// 航点列表
|
|
|
let airPointInfo = {
|
|
|
id: uuid,
|
|
|
name: '航点',
|
|
|
lng: position._lng,
|
|
|
lat: position._lat,
|
|
|
alt: globalHeight,
|
|
|
aircraftHorizontalAngle: 0,
|
|
|
cameraHorizontalAngle: 0,
|
|
|
cameraVerticalAngle: 0,
|
|
|
focalLength: 2,
|
|
|
actions: [
|
|
|
{
|
|
|
// 设置无人机偏航角
|
|
|
name: '飞行器偏航角',
|
|
|
value: 'rotateYaw',
|
|
|
type: 'action',
|
|
|
config: {
|
|
|
actionId: null,
|
|
|
actionActuatorFunc: 'rotateYaw',
|
|
|
actionActuatorFuncParam: {
|
|
|
aircraftHeading: 0,
|
|
|
aircraftPathMode: 'counterClockwise',
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
// 设置旋转云台俯仰角
|
|
|
name: '云台俯仰角',
|
|
|
value: 'gimbalRotate',
|
|
|
type: 'action',
|
|
|
config: {
|
|
|
actionId: 3,
|
|
|
actionActuatorFunc: 'gimbalRotate',
|
|
|
actionActuatorFuncParam: {
|
|
|
gimbalHeadingYawBase: 'north',
|
|
|
gimbalRotateMode: 'absoluteAngle',
|
|
|
gimbalPitchRotateEnable: 1,
|
|
|
gimbalPitchRotateAngle: 0,
|
|
|
gimbalRollRotateEnable: 0,
|
|
|
gimbalRollRotateAngle: 0,
|
|
|
gimbalYawRotateEnable: 0,
|
|
|
gimbalYawRotateAngle: 0,
|
|
|
gimbalRotateTimeEnable: 0,
|
|
|
gimbalRotateTime: 0,
|
|
|
payloadPositionIndex: 0,
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
// 调整相机焦距
|
|
|
name: '相机焦距',
|
|
|
value: 'zoom',
|
|
|
type: 'action',
|
|
|
config: {
|
|
|
actionId: null,
|
|
|
actionActuatorFunc: 'zoom',
|
|
|
actionActuatorFuncParam: {
|
|
|
focalLength: 24,
|
|
|
isUseFocalFactor: 0,
|
|
|
payloadPositionIndex: 0,
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
],
|
|
|
};
|
|
|
airPoints.value?.push(airPointInfo);
|
|
|
uavPoints.value.push(graphic);
|
|
|
|
|
|
// 当前航点
|
|
|
currentAirPoint.value = airPoints.value[airPoints.value?.length - 1];
|
|
|
|
|
|
// 更新镜头
|
|
|
handlerDrawCamera(airPointInfo);
|
|
|
|
|
|
// 更新航线
|
|
|
handlerDrawLine();
|
|
|
};
|
|
|
|
|
|
// 绘制镜头
|
|
|
const handlerDrawCamera = (e) => {
|
|
|
// 判断是否已经添加
|
|
|
const graphic = graphicLayer.getGraphicById('cameraGraphic');
|
|
|
if (graphic) {
|
|
|
// 如果存在更新数据
|
|
|
graphic.setOptions({
|
|
|
id: 'cameraGraphic',
|
|
|
position: [e.lng, e.lat, e.alt],
|
|
|
show: true,
|
|
|
style: {
|
|
|
angle1: 30, // 椎体夹角1
|
|
|
angle2: 30, // 椎体夹角2
|
|
|
length: 100, // 椎体长度
|
|
|
rayEllipsoid: false,
|
|
|
color: 'rgba(0,255,255,0.3)',
|
|
|
outline: true,
|
|
|
topShow: true,
|
|
|
topSteps: 2,
|
|
|
flat: true,
|
|
|
cameraHpr: true,
|
|
|
heading: e.aircraftHorizontalAngle - 90, // 偏航角
|
|
|
pitch: e.cameraVerticalAngle - 90, // 俯仰角 0 - 360度
|
|
|
roll: 0,
|
|
|
},
|
|
|
});
|
|
|
} else {
|
|
|
let satelliteSensor = new mars3d.graphic.RectSensor({
|
|
|
id: 'cameraGraphic',
|
|
|
position: [e.lng, e.lat, e.alt],
|
|
|
style: {
|
|
|
flat: true,
|
|
|
angle1: 30, // 椎体夹角1
|
|
|
angle2: 30, // 椎体夹角2
|
|
|
length: 100, // 椎体长度
|
|
|
rayEllipsoid: false,
|
|
|
color: 'rgba(0,255,255,0.3)',
|
|
|
outline: true,
|
|
|
topShow: true,
|
|
|
topSteps: 2,
|
|
|
cameraHpr: true,
|
|
|
heading: e.aircraftHorizontalAngle - 90,
|
|
|
pitch: e.cameraVerticalAngle - 90, // 俯仰角 0 - 360度
|
|
|
roll: 0,
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(satelliteSensor);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 更新航点
|
|
|
const updateAirPoint = (e) => {
|
|
|
// 更新航点
|
|
|
let graphic = graphicLayer.getGraphicById(e.id);
|
|
|
if (graphic) {
|
|
|
graphic.setOptions({
|
|
|
name: '航向',
|
|
|
position: [e.lng, e.lat, e.alt],
|
|
|
style: {
|
|
|
url: '/map/uav-angle.gltf',
|
|
|
scale: 0.1,
|
|
|
heading: e.aircraftHorizontalAngle + 90,
|
|
|
distanceDisplayCondition: true,
|
|
|
distanceDisplayCondition_near: 0,
|
|
|
distanceDisplayPoint: {
|
|
|
color: '#00ff00',
|
|
|
pixelSize: 8,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 更新贴地点
|
|
|
let stickGraphic = stickGroundPointLayer.getGraphicById('stick' + e.id);
|
|
|
if (stickGraphic) {
|
|
|
stickGraphic.setOptions({
|
|
|
position: [e.lng, e.lat],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
pixelSize: 8,
|
|
|
outline: true,
|
|
|
outlineColor: '#f5f5f5',
|
|
|
outlineWidth: 1,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 更新投影点连线
|
|
|
let lineGraphic = lineGroundPointLayer.getGraphicById('line' + e.id);
|
|
|
if (lineGraphic) {
|
|
|
lineGraphic.setOptions({
|
|
|
positions: [
|
|
|
[e.lng, e.lat, e.alt],
|
|
|
[e.lng, e.lat, 0],
|
|
|
],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
width: 1,
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
|
|
|
let cameraGraphic = graphicLayer.getGraphicById('camera' + e.id);
|
|
|
if (cameraGraphic) {
|
|
|
cameraGraphic.setOptions({
|
|
|
position: [e.lng, e.lat, e.alt],
|
|
|
// style: {
|
|
|
// angle1: 30, // 椎体夹角1
|
|
|
// angle2: 30, // 椎体夹角2
|
|
|
// length: 50, // 椎体长度
|
|
|
// rayEllipsoid: true,
|
|
|
// color: "rgba(0,255,255,0.3)",
|
|
|
// outline: true,
|
|
|
// topShow: true,
|
|
|
// topSteps: 2,
|
|
|
// flat: true,
|
|
|
// cameraHpr: true,
|
|
|
// heading: 0,
|
|
|
// pitch: 180,
|
|
|
// roll: 0, //
|
|
|
// clippingPlanes: [{
|
|
|
// distance: 0, // 设置裁剪平面在地表(0高度)
|
|
|
// normal: new Cesium.Cartesian3(0, 0, -1) // 法向量向下(隐藏地表以下部分)
|
|
|
// }]
|
|
|
// }
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 更新航线
|
|
|
handlerDrawLine();
|
|
|
};
|
|
|
|
|
|
// 航点动作参数改变
|
|
|
const paramChagne = (info) => {
|
|
|
console.log('info1232', info);
|
|
|
|
|
|
// 判断事件类型
|
|
|
|
|
|
if (info.value == 'rotateYaw') {
|
|
|
// 飞行器偏航角
|
|
|
// 设置参数
|
|
|
currentAirPoint.value.aircraftHorizontalAngle =
|
|
|
info.config.actionActuatorFuncParam.aircraftHeading;
|
|
|
// 更新镜头
|
|
|
handlerDrawCamera(currentAirPoint.value);
|
|
|
// 更新航点
|
|
|
updateAirPoint(currentAirPoint.value);
|
|
|
}
|
|
|
|
|
|
if (info.value == 'gimbalRotate') {
|
|
|
// 云台俯仰角
|
|
|
// 设置参数
|
|
|
currentAirPoint.value.cameraVerticalAngle =
|
|
|
info.config.actionActuatorFuncParam.gimbalPitchRotateAngle;
|
|
|
// 更新镜头
|
|
|
handlerDrawCamera(currentAirPoint.value);
|
|
|
}
|
|
|
|
|
|
if (info.value == 'position') {
|
|
|
// 坐标高度改变
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 航点位置参数改变
|
|
|
const positionChange = () => {
|
|
|
// 更新航点
|
|
|
updateAirPoint(currentAirPoint.value);
|
|
|
|
|
|
// 更新镜头
|
|
|
handlerDrawCamera(currentAirPoint.value);
|
|
|
};
|
|
|
|
|
|
// 切换航点
|
|
|
const pointChange = (id, type) => {
|
|
|
if (type == 'next') {
|
|
|
if (id == airPoints.value.length) {
|
|
|
currentAirPoint.value = airPoints.value[0];
|
|
|
} else {
|
|
|
currentAirPoint.value = airPoints.value[id];
|
|
|
}
|
|
|
} else if (type == 'last') {
|
|
|
if (id == 1) {
|
|
|
currentAirPoint.value = airPoints.value[airPoints.value.length - 1];
|
|
|
} else {
|
|
|
currentAirPoint.value = airPoints.value[id - 2];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 更新镜头
|
|
|
handlerDrawCamera(currentAirPoint.value);
|
|
|
};
|
|
|
|
|
|
// 删除航点
|
|
|
const deleteAirPoint = (e) => {
|
|
|
let id = e.graphic.id;
|
|
|
|
|
|
// 删除航点
|
|
|
let uavModel = graphicLayer.getGraphicById(id);
|
|
|
if (uavModel) {
|
|
|
graphicLayer.removeGraphic(uavModel);
|
|
|
}
|
|
|
|
|
|
// 删除相机
|
|
|
let camera = graphicLayer.getGraphicById('cameraGraphic');
|
|
|
if (camera) {
|
|
|
graphicLayer.removeGraphic(camera);
|
|
|
}
|
|
|
|
|
|
// 删除贴地点
|
|
|
let point = lineGroundPointLayer.getGraphicById('line' + id);
|
|
|
if (point) {
|
|
|
lineGroundPointLayer.removeGraphic(point);
|
|
|
}
|
|
|
|
|
|
// 删除连接线
|
|
|
let line = stickGroundPointLayer.getGraphicById('stick' + id);
|
|
|
if (line) {
|
|
|
stickGroundPointLayer.removeGraphic(line);
|
|
|
}
|
|
|
|
|
|
// 删除数据
|
|
|
airPoints.value?.forEach((item, index) => {
|
|
|
if (item.id == id) {
|
|
|
airPoints.value?.splice(index, 1);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 更新航线
|
|
|
handlerDrawLine();
|
|
|
};
|
|
|
|
|
|
// 编辑回显航点航线
|
|
|
const handlerEditWaypointAirLine = async () => {
|
|
|
// 解析和设置参考起飞点
|
|
|
let takeoffArray = props.templateKmlConfig.missionConfig.takeOffRefPoint.split(',');
|
|
|
takeOffPointPosition.value = [
|
|
|
parseFloat(takeoffArray[1]),
|
|
|
parseFloat(takeoffArray[0]),
|
|
|
parseFloat(takeoffArray[2]),
|
|
|
];
|
|
|
polygonAirForm.value.startingPoint = [
|
|
|
parseFloat(takeoffArray[1]),
|
|
|
parseFloat(takeoffArray[0]),
|
|
|
parseFloat(takeoffArray[2]),
|
|
|
];
|
|
|
takeOffPointGraphicLayer ? takeOffPointGraphicLayer.clear() : null;
|
|
|
let startFlyGraphic = new mars3d.graphic.BillboardEntity({
|
|
|
position: takeOffPointPosition.value,
|
|
|
style: {
|
|
|
image: '/map/start.png',
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '参考起飞点',
|
|
|
font_size: 16,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -50,
|
|
|
},
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
takeOffPointGraphicLayer.addGraphic(startFlyGraphic);
|
|
|
|
|
|
// 处理和加载航点
|
|
|
if (props.waylineWpmlConfig.Folder.Placemark.length > 0) {
|
|
|
props.waylineWpmlConfig.Folder.Placemark?.forEach((item, index) => {
|
|
|
let coordinate = item.Point.coordinates.split(',');
|
|
|
// 处理航点
|
|
|
let airPointInfo = {
|
|
|
id: item.index + 1,
|
|
|
lng: coordinate[0],
|
|
|
lat: coordinate[1],
|
|
|
alt: item.executeHeight,
|
|
|
aircraftHorizontalAngle: 0,
|
|
|
cameraHorizontalAngle: 0,
|
|
|
cameraVerticalAngle: 0,
|
|
|
focalLength: 24,
|
|
|
actions: [],
|
|
|
};
|
|
|
// 处理动作
|
|
|
item.actionGroup.action?.forEach((action, idx) => {
|
|
|
let actionConfig = JSON.parse(JSON.stringify(airPointActions[action.actionActuatorFunc]));
|
|
|
actionConfig.config = JSON.parse(JSON.stringify(action));
|
|
|
|
|
|
console.log('123', action);
|
|
|
|
|
|
// 处理航偏角和俯仰角
|
|
|
if (action.actionActuatorFunc == 'rotateYaw') {
|
|
|
airPointInfo.aircraftHorizontalAngle = action.actionActuatorFuncParam.aircraftHeading;
|
|
|
}
|
|
|
|
|
|
if (action.actionActuatorFunc == 'gimbalRotate') {
|
|
|
airPointInfo.cameraVerticalAngle =
|
|
|
action.actionActuatorFuncParam.gimbalPitchRotateAngle;
|
|
|
}
|
|
|
|
|
|
airPointInfo.actions.push(actionConfig);
|
|
|
});
|
|
|
airPoints.value?.push(airPointInfo);
|
|
|
// 回显航点
|
|
|
displayWaypointAirLine(airPointInfo);
|
|
|
});
|
|
|
// 更新航线
|
|
|
handlerDrawLine();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 回显航点航线信息
|
|
|
const displayWaypointAirLine = (position) => {
|
|
|
console.log('position123', position);
|
|
|
|
|
|
// 设置航线默认高度
|
|
|
let uuid = buildUUID();
|
|
|
|
|
|
// 获取默认航线高度
|
|
|
|
|
|
// 航点三维模型
|
|
|
let uavAngleGraphic = new mars3d.graphic.ModelEntity({
|
|
|
id: position.id,
|
|
|
name: '航向',
|
|
|
position: [position.lng, position.lat, position.alt],
|
|
|
style: {
|
|
|
url: '/map/uav-angle.gltf',
|
|
|
scale: 0.1,
|
|
|
heading: position.aircraftHorizontalAngle + 90,
|
|
|
distanceDisplayCondition: true,
|
|
|
distanceDisplayCondition_near: 0,
|
|
|
distanceDisplayPoint: {
|
|
|
color: '#00ff00',
|
|
|
pixelSize: 8,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(uavAngleGraphic);
|
|
|
|
|
|
// 地面投影点
|
|
|
let stickGraphic = new mars3d.graphic.PointEntity({
|
|
|
id: 'stick' + position.id,
|
|
|
position: [position.lng, position.lat],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
pixelSize: 8,
|
|
|
outline: true,
|
|
|
outlineColor: '#f5f5f5',
|
|
|
outlineWidth: 1,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
stickGroundPointLayer.addGraphic(stickGraphic);
|
|
|
|
|
|
// 航点 投影点连接线
|
|
|
let lineGraphic = new mars3d.graphic.PolylineEntity({
|
|
|
id: 'line' + position.id,
|
|
|
positions: [
|
|
|
[position.lng, position.lat, position.alt],
|
|
|
[position.lng, position.lat, 0],
|
|
|
],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
width: 1,
|
|
|
},
|
|
|
});
|
|
|
lineGroundPointLayer.addGraphic(lineGraphic);
|
|
|
};
|
|
|
|
|
|
let stickGraphicLayer: mars3d.layer.GraphicLayer;
|
|
|
|
|
|
// 飞行到此处
|
|
|
const flyToThere = (e) => {
|
|
|
if (!uavGraphicLayer) {
|
|
|
uavGraphicLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing: false, // 是否自动激活编辑
|
|
|
});
|
|
|
|
|
|
uavGraphicLayer.bindContextMenu([
|
|
|
{
|
|
|
text: '按轴平移',
|
|
|
icon: 'fa fa-pencil',
|
|
|
callback: (event) => {
|
|
|
const graphic = event.graphic;
|
|
|
if (moveTool) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
// 按轴移动
|
|
|
moveTool = new mars3d.thing.MatrixMove2({
|
|
|
position: graphic.position,
|
|
|
});
|
|
|
map.addThing(moveTool);
|
|
|
moveTool.on(mars3d.EventType.change, (event) => {
|
|
|
graphic.position = event.position;
|
|
|
uavGraphicMove(event);
|
|
|
});
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: '停止平移',
|
|
|
icon: 'fa fa-pencil',
|
|
|
callback: (event) => {
|
|
|
const graphic = event.graphic;
|
|
|
if (moveTool) {
|
|
|
moveTool.destroy();
|
|
|
moveTool = null;
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: '删除',
|
|
|
icon: 'fa fa-camera-retro', // 支持 font-class 的字体方式图标
|
|
|
callback: (e) => {
|
|
|
deleteFlyToThere(e);
|
|
|
},
|
|
|
},
|
|
|
]);
|
|
|
|
|
|
map.addLayer(uavGraphicLayer);
|
|
|
|
|
|
uavGraphicLayer.on(mars3d.EventType.editMouseMove, (e) => {});
|
|
|
}
|
|
|
|
|
|
if (moveTool) {
|
|
|
moveTool.destroy();
|
|
|
moveTool = null;
|
|
|
}
|
|
|
|
|
|
if (!stickGraphicLayer) {
|
|
|
stickGraphicLayer = new mars3d.layer.GraphicLayer({
|
|
|
isAutoEditing: false, // 是否自动激活编辑
|
|
|
});
|
|
|
map.addLayer(stickGraphicLayer);
|
|
|
}
|
|
|
|
|
|
uavGraphicLayer.clear();
|
|
|
stickGraphicLayer.clear();
|
|
|
|
|
|
let position = mars3d.LngLatPoint.fromCartesian(e.position);
|
|
|
|
|
|
let mark = graphicLayer.getGraphicById('flytothere');
|
|
|
|
|
|
if (mark) {
|
|
|
graphicLayer.removeGraphic(mark);
|
|
|
}
|
|
|
|
|
|
// 无人机点
|
|
|
const graphic = new mars3d.graphic.BillboardEntity({
|
|
|
id: 'flytothere-uav',
|
|
|
name: '标点',
|
|
|
position: [position._lng, position._lat, position._alt + 80],
|
|
|
style: {
|
|
|
image: '/map/uav-mark.png',
|
|
|
scale: 0.3,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '',
|
|
|
font_size: 14,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -40,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
|
|
|
// 贴地点
|
|
|
const stickGraphic = new mars3d.graphic.PointEntity({
|
|
|
id: 'flytothere-stick',
|
|
|
position: [position._lng, position._lat],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
pixelSize: 8,
|
|
|
outline: true,
|
|
|
outlineColor: '#f5f5f5',
|
|
|
outlineWidth: 1,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
|
|
|
stickGraphic.on(mars3d.EventType.editMouseMove, (e) => {
|
|
|
const cartographic = mars3d.Cesium.Cartographic.fromCartesian(e.cartesian);
|
|
|
// 弧度转度数
|
|
|
const longitude = mars3d.Cesium.Math.toDegrees(cartographic.longitude);
|
|
|
const latitude = mars3d.Cesium.Math.toDegrees(cartographic.latitude);
|
|
|
const height = cartographic.height; // 高度(米)
|
|
|
stickGraphicMove([longitude, latitude, height]);
|
|
|
});
|
|
|
|
|
|
// 连接线
|
|
|
let connectLine = new mars3d.graphic.PolylineEntity({
|
|
|
id: 'flytothere-line',
|
|
|
positions: [
|
|
|
[position._lng, position._lat, position._alt + 80],
|
|
|
[position._lng, position._lat, 0],
|
|
|
],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
width: 1,
|
|
|
},
|
|
|
});
|
|
|
|
|
|
uavGraphicLayer.addGraphic(graphic);
|
|
|
stickGraphicLayer.addGraphic(stickGraphic);
|
|
|
uavGraphicLayer.addGraphic(connectLine);
|
|
|
|
|
|
// 获取无人机的坐标并返回
|
|
|
let flyToPosition = mars3d.LngLatPoint.fromCartesian(graphic.position);
|
|
|
emits('flyToThere', flyToPosition);
|
|
|
};
|
|
|
|
|
|
// 移动贴地点
|
|
|
const stickGraphicMove = (e) => {
|
|
|
let uav = uavGraphicLayer.getGraphicById('flytothere-uav');
|
|
|
|
|
|
if (uav) {
|
|
|
uav.setOptions({
|
|
|
id: 'flytothere-uav',
|
|
|
name: '标点',
|
|
|
position: [e[0], e[1], 200],
|
|
|
style: {
|
|
|
image: '/map/uav-mark.png',
|
|
|
scale: 0.3,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '',
|
|
|
font_size: 14,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -40,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
|
|
|
let line = uavGraphicLayer.getGraphicById('flytothere-line');
|
|
|
if (line) {
|
|
|
line.setOptions({
|
|
|
id: 'flytothere-line',
|
|
|
positions: [
|
|
|
[e[0], e[1], 200],
|
|
|
[e[0], e[1], 0],
|
|
|
],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
width: 1,
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 删除飞行到此处
|
|
|
const deleteFlyToThere = (e) => {
|
|
|
let id = e.graphic.id;
|
|
|
|
|
|
let uavGraphic = uavGraphicLayer.getGraphicById(id);
|
|
|
if (uavGraphic) {
|
|
|
uavGraphicLayer.removeGraphic(uavGraphic);
|
|
|
}
|
|
|
|
|
|
let lineGraphic = uavGraphicLayer.getGraphicById('flytothere-line');
|
|
|
if (lineGraphic) {
|
|
|
uavGraphicLayer.removeGraphic(lineGraphic);
|
|
|
}
|
|
|
|
|
|
let stickGraphic = stickGraphicLayer.getGraphicById('flytothere-stick');
|
|
|
if (stickGraphic) {
|
|
|
stickGraphicLayer.removeGraphic(stickGraphic);
|
|
|
}
|
|
|
|
|
|
if (moveTool) {
|
|
|
moveTool.destroy();
|
|
|
moveTool = null;
|
|
|
}
|
|
|
emits('flyToThere', { _lng: null, _lat: null, _alt: null });
|
|
|
};
|
|
|
|
|
|
// 无人机点按轴移动
|
|
|
const uavGraphicMove = (e) => {
|
|
|
const cartographic = mars3d.Cesium.Cartographic.fromCartesian(e.position);
|
|
|
|
|
|
// 弧度转度数
|
|
|
const longitude = mars3d.Cesium.Math.toDegrees(cartographic.longitude);
|
|
|
const latitude = mars3d.Cesium.Math.toDegrees(cartographic.latitude);
|
|
|
const height = cartographic.height; // 高度(米)
|
|
|
|
|
|
emits('flyToThere', { _lng: longitude, _lat: latitude, _alt: height });
|
|
|
|
|
|
let line = uavGraphicLayer.getGraphicById('flytothere-line');
|
|
|
|
|
|
if (line) {
|
|
|
line.setOptions({
|
|
|
id: 'flytothere-line',
|
|
|
positions: [
|
|
|
[longitude, latitude, height],
|
|
|
[longitude, latitude, 0],
|
|
|
],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
width: 1,
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
|
|
|
let stick = stickGraphicLayer.getGraphicById('flytothere-stick');
|
|
|
if (stick) {
|
|
|
stick.setOptions({
|
|
|
id: 'flytothere-stick',
|
|
|
position: [longitude, latitude],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
pixelSize: 8,
|
|
|
outline: true,
|
|
|
outlineColor: '#f5f5f5',
|
|
|
outlineWidth: 1,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 预览航点航线
|
|
|
const preViewPointWayLine = (position) => {
|
|
|
if (moveTool) {
|
|
|
moveTool.destroy();
|
|
|
moveTool = null;
|
|
|
}
|
|
|
|
|
|
let uuid = buildUUID();
|
|
|
// 参考起飞点
|
|
|
|
|
|
let startGraphic = new mars3d.graphic.BillboardEntity({
|
|
|
id: 'start-graphic',
|
|
|
position: takeOffPointPosition.value,
|
|
|
style: {
|
|
|
image: '/map/start.png',
|
|
|
scale: 1,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '参考起飞点',
|
|
|
font_size: 14,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -35,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(startGraphic);
|
|
|
|
|
|
// 航点
|
|
|
let graphic = new mars3d.graphic.BillboardEntity({
|
|
|
id: uuid,
|
|
|
name: '航点',
|
|
|
position: [position._lng, position._lat, position._alt],
|
|
|
style: {
|
|
|
image: '/map/node.png',
|
|
|
scale: 1,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '航点',
|
|
|
font_size: 14,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -35,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(graphic);
|
|
|
|
|
|
// 地面投影点
|
|
|
let stickGraphic = new mars3d.graphic.PointEntity({
|
|
|
id: 'stick' + uuid,
|
|
|
position: [position._lng, position._lat],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
pixelSize: 8,
|
|
|
outline: true,
|
|
|
outlineColor: '#f5f5f5',
|
|
|
outlineWidth: 1,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
stickGroundPointLayer.addGraphic(stickGraphic);
|
|
|
|
|
|
// 航点 投影点连接线
|
|
|
let lineGraphic = new mars3d.graphic.PolylineEntity({
|
|
|
id: 'line' + uuid,
|
|
|
positions: [
|
|
|
[position._lng, position._lat, position._alt],
|
|
|
[position._lng, position._lat, 0],
|
|
|
],
|
|
|
style: {
|
|
|
color: '#f5f5f5',
|
|
|
width: 1,
|
|
|
},
|
|
|
});
|
|
|
lineGroundPointLayer.addGraphic(lineGraphic);
|
|
|
|
|
|
graphicLayer.flyTo();
|
|
|
|
|
|
// 绘制航线
|
|
|
handlerDrawLine();
|
|
|
};
|
|
|
|
|
|
// 预览面状航线
|
|
|
const preViewPolygonWayLine = (lines) => {
|
|
|
handlerDrawLine();
|
|
|
};
|
|
|
|
|
|
// 清空所有图层
|
|
|
const clearAllLayer = () => {
|
|
|
graphicLayer ? graphicLayer.clear() : null;
|
|
|
|
|
|
stickGroundPointLayer ? stickGroundPointLayer.clear() : null;
|
|
|
|
|
|
lineGroundPointLayer ? lineGroundPointLayer.clear() : null;
|
|
|
|
|
|
polygonGraphicLayer ? polygonGraphicLayer.clear() : null;
|
|
|
|
|
|
// 面状航线
|
|
|
polygonLineGraphicLayer ? polygonLineGraphicLayer.clear() : null;
|
|
|
|
|
|
// 文字标注
|
|
|
textLabelGraphicLayer ? textLabelGraphicLayer.clear() : null;
|
|
|
|
|
|
airPoints.value = [];
|
|
|
polygonGeoJson.value = null;
|
|
|
};
|
|
|
|
|
|
//////////////////////////////项目、机场、无人机////////////////////////////////////////////
|
|
|
|
|
|
// 设置机场位置
|
|
|
const setAirportPosition = async () => {
|
|
|
if (!graphicLayer) {
|
|
|
return;
|
|
|
}
|
|
|
if (props.airPort.longitude == null) {
|
|
|
return;
|
|
|
}
|
|
|
let point = graphicLayer.getGraphicById('set-airport');
|
|
|
// // 创建点的经纬度信息
|
|
|
let position = [props.airPort.longitude, props.airPort.latitude, 70];
|
|
|
// 更新航点
|
|
|
if (point) {
|
|
|
// point.setOptions({
|
|
|
// id: 'set-airport',
|
|
|
// name: '机场位置',
|
|
|
// position: position,
|
|
|
// style: {
|
|
|
// image: '/projecthome/airport.png',
|
|
|
// width: 35,
|
|
|
// height: 59,
|
|
|
// scale: 1,
|
|
|
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
// label: {
|
|
|
// text: '机场',
|
|
|
// font_size: 14,
|
|
|
// color: '#ffffff',
|
|
|
// outline: true,
|
|
|
// outlineColor: '#000000',
|
|
|
// pixelOffsetY: -70,
|
|
|
// },
|
|
|
// },
|
|
|
// });
|
|
|
} else {
|
|
|
let startGraphic = new mars3d.graphic.BillboardEntity({
|
|
|
id: 'set-airport',
|
|
|
position: position,
|
|
|
style: {
|
|
|
image: '/projecthome/airport.png',
|
|
|
width: 35,
|
|
|
height: 59,
|
|
|
scale: 1,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '机场',
|
|
|
font_size: 14,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -70,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(startGraphic);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 项目首页设置机场位置
|
|
|
const homeSetAirportPosition = () => {
|
|
|
if (!graphicLayer) {
|
|
|
return;
|
|
|
}
|
|
|
// // 创建点的经纬度信息
|
|
|
let position = [props.homeAirport.longitude, props.homeAirport.latitude, 70];
|
|
|
let airportImg =
|
|
|
props.homeAirport.mode_code == 4
|
|
|
? '/projecthome/work_airport.png'
|
|
|
: '/projecthome/standby_airport.png';
|
|
|
let airportLiveImg =
|
|
|
props.homeAirport.mode_code == 4
|
|
|
? '/projecthome/work_airport_live.png'
|
|
|
: '/projecthome/standby_airport_live.png';
|
|
|
// 更新航点
|
|
|
if (homeStartGraphic && homeStartGraphicLive) {
|
|
|
homeStartGraphic.position = position;
|
|
|
homeStartGraphic.image = airportImg;
|
|
|
homeStartGraphicLive.position = position;
|
|
|
homeStartGraphicLive.image = airportLiveImg;
|
|
|
} else {
|
|
|
homeStartGraphic = new mars3d.graphic.BillboardEntity({
|
|
|
id: 'set-home-airport',
|
|
|
position: position,
|
|
|
style: {
|
|
|
image: airportImg,
|
|
|
width: 118,
|
|
|
height: 133,
|
|
|
scale: 1,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
label: {
|
|
|
text: '机场',
|
|
|
font_size: 14,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -70,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
homeStartGraphicLive = new mars3d.graphic.BillboardEntity({
|
|
|
id: 'set-home-airport-live',
|
|
|
position: position,
|
|
|
style: {
|
|
|
image: airportLiveImg,
|
|
|
width: 21,
|
|
|
height: 21,
|
|
|
scale: 1,
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
pixelOffset: new Cesium.Cartesian2(45, -107),
|
|
|
label: {
|
|
|
text: '机场',
|
|
|
font_size: 14,
|
|
|
color: '#ffffff',
|
|
|
outline: true,
|
|
|
outlineColor: '#000000',
|
|
|
pixelOffsetY: -70,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
homeStartGraphic.on(mars3d.EventType.click, function (event) {
|
|
|
emits('clickAirPort');
|
|
|
});
|
|
|
homeStartGraphicLive.on(mars3d.EventType.click, function (event) {
|
|
|
emits('changeAirportLive', true);
|
|
|
if (props.homeAirport.mode_code == 4) {
|
|
|
emits('changeUAVLive', true);
|
|
|
}
|
|
|
});
|
|
|
graphicLayer.addGraphic(homeStartGraphic);
|
|
|
graphicLayer.addGraphic(homeStartGraphicLive);
|
|
|
}
|
|
|
};
|
|
|
// 设置无人机轨迹
|
|
|
const setUAVPosition = () => {
|
|
|
let point = graphicLayer.getGraphicById('set-uav');
|
|
|
const position = [props.uavTrack.longitude, props.uavTrack.latitude, props.uavTrack.height];
|
|
|
// 更新航点
|
|
|
if (point) {
|
|
|
point.setOptions({
|
|
|
id: 'set-uav',
|
|
|
name: '飞行器位置',
|
|
|
position: position,
|
|
|
style: {
|
|
|
url: '/projecthome/dajiang.gltf',
|
|
|
scale: 0.1,
|
|
|
minimumPixelSize: 100,
|
|
|
},
|
|
|
frameRate: 1,
|
|
|
});
|
|
|
} else {
|
|
|
const graphicModel = new mars3d.graphic.ModelPrimitive({
|
|
|
id: 'set-uav',
|
|
|
name: '飞行器位置',
|
|
|
position: position,
|
|
|
style: {
|
|
|
url: '/projecthome/dajiang.gltf',
|
|
|
scale: 0.1,
|
|
|
minimumPixelSize: 100,
|
|
|
},
|
|
|
frameRate: 1,
|
|
|
});
|
|
|
graphicLayer.addGraphic(graphicModel);
|
|
|
}
|
|
|
|
|
|
let route = graphicLayer.getGraphicById('uav-route');
|
|
|
if (!route) {
|
|
|
route = new mars3d.graphic.Route({
|
|
|
id: 'uav-route',
|
|
|
polyline: {
|
|
|
color: '#3388ff',
|
|
|
width: 2,
|
|
|
},
|
|
|
flyTo: true,
|
|
|
});
|
|
|
graphicLayer.addGraphic(route);
|
|
|
// 是与route绑定的矢量对象,放在route构造时一起构造
|
|
|
addGroundLine(route, 'uav-route');
|
|
|
addRectSensor(route, 'uav-route');
|
|
|
}
|
|
|
if (props.uavTrack.longitude) {
|
|
|
const positionVal = Cesium.Cartesian3.fromDegrees(
|
|
|
props.uavTrack.longitude,
|
|
|
props.uavTrack.latitude,
|
|
|
props.uavTrack.height,
|
|
|
);
|
|
|
route.addTimePosition(positionVal, Cesium.JulianDate.fromDate(new Date()));
|
|
|
const airPortStoreVal = airPortStore();
|
|
|
const uav = airPortStoreVal.getUAV;
|
|
|
const type_subtype_gimbalindex = props.uavTrack[uav.camera_index];
|
|
|
if (type_subtype_gimbalindex) {
|
|
|
const rectSensor = graphicLayer.getGraphicById('uav-route-rectSensor');
|
|
|
rectSensor.heading = type_subtype_gimbalindex.gimbal_yaw; //四周方向角,0至360度角度值
|
|
|
rectSensor.pitch = type_subtype_gimbalindex.gimbal_pitch; //俯仰角,上下摇摆的角度,0至360度角度值
|
|
|
rectSensor.roll = type_subtype_gimbalindex.gimbal_roll + 90; //滚转角,左右摆动的角度,0至360度角度值
|
|
|
rectSensor.angle1 = 10; //夹角1,半场角度,取值范围 0.1-89.9
|
|
|
rectSensor.angle2 = 10; //夹角2,半场角度,取值范围 0.1-89.9
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
// 绘制连接地面线
|
|
|
function addGroundLine(route) {
|
|
|
const groundPoint = new mars3d.graphic.PointPrimitive({
|
|
|
id: route.id + '-groundPoint',
|
|
|
position: route.position,
|
|
|
style: {
|
|
|
color: '#ff0000',
|
|
|
pixelSize: 6,
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(groundPoint);
|
|
|
|
|
|
const linePositions = [];
|
|
|
const groundLine = new mars3d.graphic.PolylineEntity({
|
|
|
id: route.id + '-groundLine',
|
|
|
positions: new Cesium.CallbackProperty(function (time) {
|
|
|
return linePositions;
|
|
|
}, false),
|
|
|
style: {
|
|
|
width: 1,
|
|
|
materialType: mars3d.MaterialType.PolylineDash,
|
|
|
materialOptions: {
|
|
|
color: Cesium.Color.WHITE,
|
|
|
dashLength: 20,
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(groundLine);
|
|
|
|
|
|
route.on(mars3d.EventType.change, function (event) {
|
|
|
const wrjPt = route.position;
|
|
|
const wrjCarto = Cesium.Cartographic.fromCartesian(wrjPt);
|
|
|
const dmHeight = mars3d.PointUtil.getHeight(map?.scene, wrjCarto, { max: wrjCarto.height });
|
|
|
const pt2 = Cesium.Cartesian3.fromRadians(wrjCarto.longitude, wrjCarto.latitude, dmHeight);
|
|
|
|
|
|
// 更新竖直线坐标
|
|
|
linePositions[0] = wrjPt;
|
|
|
linePositions[1] = pt2;
|
|
|
|
|
|
// 更新其他矢量对象
|
|
|
groundPoint.position = pt2;
|
|
|
|
|
|
if (route.label) {
|
|
|
// const wrjHeight = wrjCarto.height - dmHeight // 相对地面高度(AGL): 飞行海拔-地面海拔
|
|
|
// fixedRoute.label.text = `火星无人机\nAGL:${mars3d.Util.formatNum(wrjHeight, 2)}m`
|
|
|
|
|
|
// 绝对高度(ASL): 飞行海拔
|
|
|
route.label.text = `火星无人机\nASL:${mars3d.Util.formatNum(wrjCarto.height, 2)}m`;
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
// 绘制 相机视锥体
|
|
|
function addRectSensor(route) {
|
|
|
const rectSensor = new mars3d.graphic.RectSensor({
|
|
|
id: route.id + '-rectSensor',
|
|
|
position: route.property,
|
|
|
style: {
|
|
|
angle1: 10,
|
|
|
angle2: 10,
|
|
|
length: 10,
|
|
|
rayEllipsoid: true,
|
|
|
color: 'rgba(0,255,255,0.3)',
|
|
|
outline: true,
|
|
|
topShow: true,
|
|
|
topSteps: 2,
|
|
|
flat: true,
|
|
|
cameraHpr: true,
|
|
|
heading: 0,
|
|
|
pitch: 0,
|
|
|
roll: 90,
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(rectSensor);
|
|
|
|
|
|
// 连接线
|
|
|
const rectLine = new mars3d.graphic.PolylineEntity({
|
|
|
id: route.id + '-rectLine',
|
|
|
positions: new Cesium.CallbackProperty(function (time) {
|
|
|
const localEnd = rectSensor?.rayPosition;
|
|
|
if (!localEnd) {
|
|
|
return [];
|
|
|
}
|
|
|
return [rectSensor.position, localEnd];
|
|
|
}, false),
|
|
|
style: {
|
|
|
arcType: Cesium.ArcType.NONE,
|
|
|
materialType: mars3d.MaterialType.PolylineDash,
|
|
|
materialOptions: {
|
|
|
color: '#ff0000',
|
|
|
},
|
|
|
width: 1,
|
|
|
},
|
|
|
});
|
|
|
graphicLayer.addGraphic(rectLine);
|
|
|
}
|
|
|
|
|
|
/////////////////////////////////动作处理//////////////////////////////////////
|
|
|
const addAction = (action) => {
|
|
|
// 需要特殊处理拍照动作
|
|
|
if (action.value == 'takePhoto') {
|
|
|
currentAirPoint.value.actions.push(JSON.parse(JSON.stringify(airPointActions['focus'])));
|
|
|
}
|
|
|
|
|
|
// 当前航点添加动作
|
|
|
currentAirPoint.value.actions.push(JSON.parse(JSON.stringify(action)));
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
.mars3d-container {
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
position: relative;
|
|
|
}
|
|
|
|
|
|
.air-container {
|
|
|
width: 400px;
|
|
|
background: #0d0e15c1;
|
|
|
position: absolute;
|
|
|
height: calc(100vh - 80px);
|
|
|
top: 40px;
|
|
|
left: 40px;
|
|
|
z-index: 999;
|
|
|
}
|
|
|
|
|
|
.airpolygon-container {
|
|
|
width: 400px;
|
|
|
background: #0d0e15c1;
|
|
|
overflow-y: hidden;
|
|
|
position: absolute;
|
|
|
height: calc(100vh - 80px);
|
|
|
top: 40px;
|
|
|
left: 40px;
|
|
|
z-index: 999;
|
|
|
}
|
|
|
|
|
|
.airpoint-config-container {
|
|
|
width: 400px;
|
|
|
background: #0d0e15c1;
|
|
|
overflow-y: hidden;
|
|
|
position: absolute;
|
|
|
height: calc(100vh - 80px);
|
|
|
top: 40px;
|
|
|
right: 40px;
|
|
|
z-index: 999;
|
|
|
}
|
|
|
|
|
|
.draw-polygon-patrol {
|
|
|
cursor: pointer;
|
|
|
position: absolute;
|
|
|
top: 20px;
|
|
|
right: 20px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
width: 40px;
|
|
|
height: 40px;
|
|
|
color: #fff;
|
|
|
background: linear-gradient(180deg, rgba(13, 25, 45, 0.87) 0%, #25436c 100%);
|
|
|
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
|
|
border-radius: 10px;
|
|
|
border-image: linear-gradient(180deg, #3661a4, rgba(61, 109, 171, 0.68)) 1 1;
|
|
|
z-index: 2;
|
|
|
}
|
|
|
|
|
|
.airline-preview-container{
|
|
|
width:500px;
|
|
|
background:rgba(0,0,0,0.6);
|
|
|
position: absolute;
|
|
|
bottom:100px;
|
|
|
left:50%;
|
|
|
transform: translate(0%,0);
|
|
|
z-index:999;
|
|
|
border-radius: 10px;
|
|
|
display: flex;
|
|
|
padding:20px;
|
|
|
font-size:18px;
|
|
|
color:#fff;
|
|
|
}
|
|
|
.airline-preview-container .info-item{
|
|
|
flex:1;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.airline-preview-container .info-item .info-label{
|
|
|
font-size:14px;
|
|
|
margin-top:12px;
|
|
|
}
|
|
|
</style>
|