| | |
| | | <template> |
| | | <div id="deviceJobDetailsMap" class="ztzf-cesium"> |
| | | <PlanarRouteLineList :curRouteLineData="curRouteLineData" @routeLineListClick="routeLineListClick" /> |
| | | </div> |
| | | </template> |
| | | <script setup> |
| | | import PlanarRouteLineList from '@/components/PlanarRouteLineList/PlanarRouteLineList.vue' |
| | | |
| | | import * as Cesium from 'cesium' |
| | | import { PublicCesium } from '@/utils/cesium/publicCesium' |
| | | |
| | | const props = defineProps(['detailsData','yuanImages']) |
| | | console.log('props.yua',props.yuanImages); |
| | | import { useRouteLine } from '@/hooks/useRouteLine/useRouteLine.js' |
| | | |
| | | // 加载航线hook |
| | | const { curRouteLineData, routeLineListClick, initViewer, renderPreviewLine } = useRouteLine() |
| | | |
| | | |
| | | import { flyVisual } from '@/utils/cesium/mapUtil' |
| | | import _ from 'lodash' |
| | | import photoDirection from '@/assets/images/historyMapPopup/photoDirection-new.png' |
| | | import panoramaPoint from '@/assets/images/panorama/panorama-point.png' //全景图标 |
| | | import { getShowImg } from '@/utils/util' |
| | | import { getEventImage } from '@/utils/stateToImageMap/event' |
| | | import { getPanoramaList } from '@/api/panorama' |
| | | import CreateRouteLine from '@/utils/cesium/createRouteLine' |
| | | import { useStore } from 'vuex' |
| | | import { getOdmToken } from '@/api/model' |
| | | const createRouteLineExample = new CreateRouteLine() |
| | | const store = useStore() |
| | | const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode) |
| | | let viewer = null |
| | | let publicCesiumInstance = null |
| | | const viewInstance = shallowRef(null) |
| | | import { cloneDeep } from 'lodash' |
| | | let handler = null |
| | | let curMoveEntity = null |
| | | const tokenStr = ref('') |
| | | const emit = defineEmits(['showImageeclick']) |
| | | const props = defineProps(['detailsData', 'yuanImages', 'jobId']) |
| | | |
| | | const initMap = () => { |
| | | viewer = new PublicCesium({ dom: 'deviceJobDetailsMap' }).getViewer() |
| | | publicCesiumInstance = new PublicCesium({ |
| | | dom: 'deviceJobDetailsMap', |
| | | terrain: true, |
| | | flatMode: false, |
| | | layerMode: 4, |
| | | }) |
| | | |
| | | initViewer(viewer) |
| | | viewer = publicCesiumInstance.getViewer() |
| | | viewInstance.value = publicCesiumInstance |
| | | viewer.scene.globe.depthTestAgainstTerrain = true |
| | | createRouteLineExample.initCreateRoute(viewer) |
| | | handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) |
| | | handler.setInputAction(click => { |
| | | const pickedObjects = viewer.scene.drillPick(click.position) |
| | | LeftClickEvent(click, pickedObjects, viewer) |
| | | }, Cesium.ScreenSpaceEventType.LEFT_CLICK) |
| | | |
| | | handler.setInputAction(e => { |
| | | let pick = viewer.scene.drillPick(e.endPosition) |
| | | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) |
| | | } |
| | | |
| | | // 绘制线和飞行 |
| | | const drawLine = async () => { |
| | | Promise.all( |
| | | props.detailsData.way_lines.map( |
| | | async item => await renderPreviewLine(`${item.url}?_t=${new Date().getTime()}`, item.wayline_type) |
| | | async item => |
| | | await createRouteLineExample.parsingFiles( |
| | | { |
| | | ...item, |
| | | url: `${item.url}?_t=${new Date().getTime()}`, |
| | | }, |
| | | { |
| | | longitude: item.longitude, |
| | | latitude: item.latitude, |
| | | height: item.height, |
| | | }, |
| | | true, |
| | | false |
| | | ) |
| | | ) |
| | | ) |
| | | ).then(res => { |
| | | createRouteLineExample.showDetailMapPopup(props.detailsData.way_lines) |
| | | let arr = res.map(i => i.filePositions) |
| | | let newArr = _.flatten(arr) |
| | | flyVisual({ |
| | | positionsData: newArr.map(i => [i.lng, i.lat, i.alt]), |
| | | viewer, |
| | | pitch: -60, |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | const lastSelectedId = ref(null) |
| | | // 鼠标左键点击事件 |
| | | const LeftClickEvent = (click, pick, viewer) => { |
| | | // pick是一个数组 |
| | | if (pick && pick.length > 0) { |
| | | let startEntity = pick.find( |
| | | i => i.id.name === 'work-drone-route-planar-polyline' || i.id.name === 'work-drone-route-point-polyline' |
| | | )?.id |
| | | if (startEntity) { |
| | | createRouteLineExample.showSingleDetailMapPopup(startEntity?.customData?.data) |
| | | return |
| | | } |
| | | let imagePath = [] |
| | | let categories = '' |
| | | let panoramic = '' |
| | | pick.forEach(item => { |
| | | const index = item.id.index |
| | | if (item.id.customType == 'spotImages') { |
| | | imagePath.push(item.id.customInfo.link) |
| | | } else if (item.id.customType == 'aggregationSplashed') { |
| | | imagePath.push(item.id.customInfo.link) |
| | | } else if (item.id.customType == 'panorama') { |
| | | //全景 |
| | | imagePath.push(item.id.customInfo.link) |
| | | categories = item.id.customInfo.resultType |
| | | } |
| | | }) |
| | | if (imagePath.length === 0) return |
| | | const finalImagePaths = categories === 5 ? imagePath : imagePath.map(i => getShowImg(i)) |
| | | emit('showImageeclick', finalImagePaths, 0, categories) |
| | | } |
| | | } |
| | | const removeMap = () => { |
| | | viewer.entities.removeAll() |
| | | viewer.destroy() |
| | | publicCesiumInstance?.viewerDestroy() |
| | | publicCesiumInstance = null |
| | | viewer = null |
| | | } |
| | | |
| | | watch( |
| | |
| | | } |
| | | } |
| | | ) |
| | | const zsList = ref([]) |
| | | // 获取odmtoken |
| | | function getOdmTokenStr() { |
| | | getOdmToken().then(res => { |
| | | if (res.data.code !== 200) return |
| | | tokenStr.value = res.data.data |
| | | }) |
| | | } |
| | | // 获取正射列表 |
| | | function getZSList(newVal) { |
| | | let list = [] |
| | | newVal.map((item, index) => { |
| | | item.childrens.map(zschilditem => { |
| | | if (zschilditem?.data) { |
| | | zschilditem?.data.map(dataitem => { |
| | | list.push(dataitem) |
| | | }) |
| | | } |
| | | }) |
| | | }) |
| | | return list |
| | | } |
| | | // 获取正射请求地图聚合数据 |
| | | const zsMapList = ref([]) |
| | | function getZSMapList(valSn) { |
| | | const params = { |
| | | areaCode: userAreaCode.value, |
| | | deviceSn: valSn, |
| | | resultType: 4, |
| | | wayLineJobId: props.jobId, |
| | | } |
| | | getPanoramaList(params).then(res => { |
| | | const resData = res?.data?.data |
| | | zsMapList.value = resData?.childrens || [] |
| | | zsList.value = getZSList(zsMapList.value) |
| | | |
| | | renderOrthophoto() |
| | | }) |
| | | } |
| | | // 解析经纬度 |
| | | function getLonLat(str) { |
| | | if (!str) return [] |
| | | return str |
| | | .replace('POLYGON((', '') |
| | | .replace('))', '') |
| | | .split(',') |
| | | .map(pair => { |
| | | const [lon, lat] = pair.trim().split(' ').map(Number) |
| | | return [lon, lat] |
| | | }) |
| | | } |
| | | // 渲染正射 |
| | | function renderOrthophoto() { |
| | | zsList.value.forEach((item, index) => { |
| | | const cur = viewInstance.value.addCustomImageryProviderDataSource( |
| | | new Cesium.UrlTemplateImageryProvider({ |
| | | url: `${import.meta.env.VITE_APP_AREA_NAME}/webodm${item.url}?jwt=${tokenStr.value.split(' ')[1]}`, |
| | | }) |
| | | ) |
| | | }) |
| | | } |
| | | watch( |
| | | () => props.yuanImages, |
| | | (newValue, oldValue) => { |
| | | |
| | | // 增加箭头 |
| | | if (!viewer || !newValue?.length) return; |
| | | // 清除旧实体 |
| | | const oldEntities = viewer.entities.values.filter(e => |
| | | e.id?.startsWith('spotImages') || |
| | | e.id?.startsWith('aggregationSplashed') || |
| | | e.id?.startsWith('panorama') |
| | | ); |
| | | oldEntities.forEach(e => viewer.entities.remove(e)); |
| | | // 添加新实体 |
| | | let eventArr = newValue.filter(i => i.resultType === 2) |
| | | let originalArr = newValue.filter(i => i.resultType === 0) |
| | | let panoramicArr = newValue.filter(i => i.resultType === 5) |
| | | let orthographicArr = newValue.filter(i => i.resultType === 4) |
| | | if (orthographicArr.length >0) { |
| | | getZSMapList(orthographicArr[0]?.deviceSn) |
| | | } |
| | | originalArr.forEach((item_in, index) => { |
| | | // 根据偏航角度展示图片拍摄的方向 |
| | | let yawAngleDegrees = |
| | | item_in.metadata.gimbalYawDegree < 0 |
| | | ? 360 + Number(item_in.metadata.gimbalYawDegree) |
| | | : Number(item_in.metadata.gimbalYawDegree) |
| | | |
| | | viewer.entities.add({ |
| | | position: Cesium.Cartesian3.fromDegrees( |
| | | +item_in.metadata.shootPosition.lng, |
| | | +item_in.metadata.shootPosition.lat, |
| | | +item_in.metadata.absoluteAltitude |
| | | ), |
| | | id: 'spotImages' + item_in.id, |
| | | customType: 'spotImages', |
| | | customInfo: { |
| | | ...item_in, |
| | | }, |
| | | index: index, |
| | | billboard: { |
| | | image: photoDirection, |
| | | outlineWidth: 0, |
| | | width: 14, |
| | | height: 21, |
| | | disableDepthTestDistance: Number.POSITIVE_INFINITY, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, |
| | | }, |
| | | }) |
| | | }) |
| | | |
| | | eventArr.forEach((item, index) => { |
| | | viewer.entities.add({ |
| | | id: `aggregationSplashed${item.id}`, |
| | | customType: 'aggregationSplashed', |
| | | customInfo: { |
| | | ...item, |
| | | }, |
| | | position: Cesium.Cartesian3.fromDegrees( |
| | | +item.metadata.shootPosition.lng, |
| | | +item.metadata.shootPosition.lat, |
| | | +item.metadata.absoluteAltitude |
| | | ), |
| | | billboard: { |
| | | image: getEventImage(item.status), |
| | | width: 30, |
| | | height: 30, |
| | | disableDepthTestDistance: Number.POSITIVE_INFINITY, |
| | | }, |
| | | index: index, |
| | | properties: { |
| | | customData: { |
| | | data: item, |
| | | }, |
| | | }, |
| | | }) |
| | | }) |
| | | // 全景 |
| | | panoramicArr.forEach((item, index) => { |
| | | viewer.entities.add({ |
| | | id: `panorama${item.id}`, |
| | | customType: 'panorama', |
| | | customInfo: { |
| | | ...item, |
| | | }, |
| | | position: Cesium.Cartesian3.fromDegrees( |
| | | +item.metadata.shootPosition.lng, |
| | | +item.metadata.shootPosition.lat, |
| | | +item.metadata.absoluteAltitude |
| | | ), |
| | | billboard: { |
| | | image: panoramaPoint, |
| | | width: 30, |
| | | height: 30, |
| | | disableDepthTestDistance: Number.POSITIVE_INFINITY, |
| | | }, |
| | | index: index, |
| | | properties: { |
| | | customData: { |
| | | data: item, |
| | | }, |
| | | }, |
| | | }) |
| | | }) |
| | | }, |
| | | { immediate: true, deep: true } |
| | | ) |
| | | onBeforeUnmount(() => { |
| | | // 移除事件监听 |
| | | handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK) |
| | | handler?.destroy() |
| | | handler = null |
| | | |
| | | createRouteLineExample.destroyedCustomDom() |
| | | |
| | | removeMap() |
| | | }) |
| | | |
| | | onMounted(() => { |
| | | getOdmTokenStr() |
| | | nextTick(() => { |
| | | initMap() |
| | | }) |