| | |
| | | :terrain="true" |
| | | :layer-mode="4" |
| | | :boundary="false" |
| | | :zoom-to-boundary="dialogMode === 'add'" |
| | | /> |
| | | </div> |
| | | <div class="right-container"> |
| | |
| | | import { useRoute } from 'vue-router' |
| | | import { fwAreaDivideDetailApi, fwAreaDivideListApi } from '../partition/partitionApi' |
| | | import { buildEllipsePositions } from '@/utils/cesium/shapeTools' |
| | | import { cartesian3Convert } from '@/utils/cesium/mapUtil' |
| | | import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants' |
| | | |
| | | // 初始化表单数据 |
| | |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = defineModel() // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const dialogMode = ref() // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const readonly = computed(() => dialogMode.value === 'view') |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '新增' }) |
| | |
| | | return normalized.map(point => Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height)) |
| | | } |
| | | |
| | | function resolveLngLatPoint(point) { |
| | | if (!point) return null |
| | | const lng = point?.lng ?? point?.longitude |
| | | const lat = point?.lat ?? point?.latitude |
| | | if (Number.isFinite(Number(lng)) && Number.isFinite(Number(lat))) { |
| | | return { |
| | | lng: Number(lng), |
| | | lat: Number(lat), |
| | | height: Number.isFinite(Number(point?.height)) ? Number(point.height) : 0, |
| | | } |
| | | } |
| | | if (!viewer || !Number.isFinite(point?.x) || !Number.isFinite(point?.y) || !Number.isFinite(point?.z)) { |
| | | return null |
| | | } |
| | | const val = cartesian3Convert(point, viewer) |
| | | return { |
| | | lng: val.longitude, |
| | | lat: val.latitude, |
| | | height: Number.isFinite(val.height) ? val.height : 0, |
| | | } |
| | | } |
| | | |
| | | function getShapeDisplayPoints(shape) { |
| | | if (Array.isArray(shape?.displayPoints) && shape.displayPoints.length) { |
| | | return shape.displayPoints |
| | |
| | | } |
| | | }) |
| | | .filter(Boolean) |
| | | } |
| | | |
| | | function pushRadiusBoundingPoints(positions, center, radius) { |
| | | if (!center || !Number.isFinite(Number(radius)) || radius <= 0) return |
| | | const resolved = resolveLngLatPoint(center) || {} |
| | | const lng = Number(resolved.lng ?? resolved.longitude) |
| | | const lat = Number(resolved.lat ?? resolved.latitude) |
| | | if (!Number.isFinite(lng) || !Number.isFinite(lat)) return |
| | | const baseLat = Cesium.Math.toRadians(lat) |
| | | const earthRadius = Cesium.Ellipsoid.WGS84.maximumRadius |
| | | const deltaLat = radius / earthRadius |
| | | const deltaLng = radius / (earthRadius * Math.max(Math.cos(baseLat), 0.000001)) |
| | | const points = [ |
| | | { lng: Cesium.Math.toDegrees(Cesium.Math.toRadians(lng) + deltaLng), lat }, |
| | | { lng: Cesium.Math.toDegrees(Cesium.Math.toRadians(lng) - deltaLng), lat }, |
| | | { lng, lat: Cesium.Math.toDegrees(baseLat + deltaLat) }, |
| | | { lng, lat: Cesium.Math.toDegrees(baseLat - deltaLat) }, |
| | | ] |
| | | points.forEach(point => { |
| | | positions.push(Cesium.Cartesian3.fromDegrees(point.lng, point.lat, resolved.height || 0)) |
| | | }) |
| | | } |
| | | |
| | | function collectSceneAreaPositions() { |
| | | const positions = [] |
| | | if (!viewer || !areaList.value.length) return positions |
| | | areaList.value.forEach(area => { |
| | | const shapes = resolveAreaShapes(area) |
| | | shapes.forEach(shape => { |
| | | const points = getShapeDisplayPoints(shape) |
| | | if (Array.isArray(points) && points.length) { |
| | | points.forEach(point => { |
| | | const resolved = resolveLngLatPoint(point) |
| | | const normalized = normalizeShapePoint(resolved) |
| | | if (!normalized) return |
| | | positions.push( |
| | | Cesium.Cartesian3.fromDegrees(normalized.lng, normalized.lat, normalized.height) |
| | | ) |
| | | }) |
| | | } |
| | | if (shape?.drawType === 'buffer' && shape?.meta?.center && Array.isArray(shape?.meta?.bufferRadii)) { |
| | | const maxRadius = Math.max(...shape.meta.bufferRadii.filter(item => Number.isFinite(item))) |
| | | pushRadiusBoundingPoints(positions, shape.meta.center, maxRadius) |
| | | } |
| | | if (shape?.drawType === 'ellipse' && shape?.meta?.center) { |
| | | const major = Number(shape?.meta?.semiMajor) |
| | | const minor = Number(shape?.meta?.semiMinor) |
| | | const radius = Number.isFinite(major) && Number.isFinite(minor) ? Math.max(major, minor) : null |
| | | pushRadiusBoundingPoints(positions, shape.meta.center, radius) |
| | | } |
| | | }) |
| | | }) |
| | | return positions |
| | | } |
| | | |
| | | function fitViewToSceneAreas() { |
| | | if (!viewer || !areaList.value.length) return |
| | | const positions = collectSceneAreaPositions() |
| | | if (positions.length < 2) return |
| | | const boundingSphere = Cesium.BoundingSphere.fromPoints(positions) |
| | | const range = Math.max(boundingSphere.radius * 2.4, 200) |
| | | viewer.camera.flyToBoundingSphere(boundingSphere, { |
| | | duration: 0, |
| | | offset: new Cesium.HeadingPitchRange(viewer.camera.heading, Cesium.Math.toRadians(-90), range), |
| | | }) |
| | | } |
| | | |
| | | function renderSceneAreas() { |
| | |
| | | await nextTick() |
| | | initMap() |
| | | await getSceneConfigList() |
| | | if (dialogMode.value !== 'add') { |
| | | if (dialogMode.value === 'add') { |
| | | mapRef.value?.zoomToAdminBoundary?.() |
| | | } else { |
| | | await loadDetail() |
| | | } |
| | | await nextTick() |
| | | setMapPoint(formData.value.longitude, formData.value.latitude) |
| | | await loadAreaList(formData.value.defenseSceneId) |
| | | fitViewToSceneAreas() |
| | | } |
| | | |
| | | onMounted(() => { |