|
|
<template>
|
|
|
<!-- 地图 -->
|
|
|
<div ref="vChartRef" id="mars3d-container" class="mars3d-container">
|
|
|
|
|
|
<!-- 航点航线 -->
|
|
|
<div v-if="props.airLineForm.airLineType == 'waypoint'" 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'" 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"
|
|
|
></airPointConfig>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
</template>
|
|
|
<script lang="ts" setup>
|
|
|
import { ref, onMounted, defineProps, watch, defineEmits } from 'vue';
|
|
|
import { message } from 'ant-design-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 'mars3d-space';
|
|
|
|
|
|
import * as Cesium from 'mars3d-cesium';
|
|
|
// import * as turf from '@turf/turf';
|
|
|
import airPolygon from './airPolygon.vue';
|
|
|
import airPointConfig from './airPointConfig.vue';
|
|
|
|
|
|
// const props = defineProps([
|
|
|
// 'airLineForm',
|
|
|
// 'flyToTherePosition',
|
|
|
// 'wayline',
|
|
|
// 'waylineInfo',
|
|
|
// 'workPlanFormShow',
|
|
|
// 'airPort',
|
|
|
// 'uavTrack',
|
|
|
// 'homeAirport'
|
|
|
// ]);
|
|
|
|
|
|
|
|
|
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
|
|
|
},
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
() => props.editMode,
|
|
|
(newVal,oldVal)=>{
|
|
|
if(newVal == 'edit' ){
|
|
|
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;
|
|
|
};
|
|
|
|
|
|
///////////////////////////////图层中心////////////////////////////////////////////
|
|
|
|
|
|
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 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(() => {
|
|
|
initMap();
|
|
|
EventBus.on('closeTranslation', (val: any) => {
|
|
|
if (moveTool) {
|
|
|
moveTool.destroy();
|
|
|
moveTool = null;
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
|
|
|
// 初始化地图
|
|
|
const initMap = () => {
|
|
|
map = new mars3d.Map(vChartRef.value, {
|
|
|
scene: {
|
|
|
center: { lat: 35.132103, lng: 118.296315, alt: 260.9, heading: 357.9, pitch: -32 },
|
|
|
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' ){
|
|
|
handlerEditPolygonAirLine();
|
|
|
}
|
|
|
// 监测面区域回显
|
|
|
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 () => {
|
|
|
|
|
|
const graphic = await polygonGraphicLayer.startDraw({
|
|
|
type: 'polygon',
|
|
|
style: {
|
|
|
color: '#408eff',
|
|
|
opacity: 0.3,
|
|
|
outline: true,
|
|
|
outlineColor: '#408eff',
|
|
|
outlineWidth: 3.0,
|
|
|
clampToGround: true,
|
|
|
},
|
|
|
});
|
|
|
|
|
|
console.log("graphic1233",graphic.toGeoJSON());
|
|
|
let coordinates = graphic.toJSON().positions;
|
|
|
|
|
|
coordinates.push(coordinates[0]);
|
|
|
|
|
|
polygonGeoJson.value = coordinates;
|
|
|
|
|
|
|
|
|
console.log("polygonGeoJson",polygonGeoJson.value);
|
|
|
|
|
|
let polygon = turf.polygon([coordinates]);
|
|
|
|
|
|
let polygonWkt = GeojsonToWkt(polygon['geometry']);
|
|
|
|
|
|
props.airLineForm.flyToFirstPointMode = polygonWkt;
|
|
|
|
|
|
let spceing = parseFloat(polygonCalculateParams.value?.spacing) / 10000;
|
|
|
let lines = generateScanLines(polygon,spceing, 0);
|
|
|
|
|
|
// 计算面积
|
|
|
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 lines = generateScanLines(polygon,spceing, 0);
|
|
|
|
|
|
// 计算面积
|
|
|
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();
|
|
|
}
|
|
|
|
|
|
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 = buildUUID();
|
|
|
|
|
|
// 获取默认航线高度
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
// 事件处理
|
|
|
const updateCamera = () => {
|
|
|
|
|
|
}
|
|
|
|
|
|
// 删除航点
|
|
|
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();
|
|
|
};
|
|
|
|
|
|
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) => {
|
|
|
return null;
|
|
|
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: 50,
|
|
|
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) => {
|
|
|
|
|
|
// 当前航点添加动作
|
|
|
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;
|
|
|
}
|
|
|
</style>
|