|
|
@@ -269,7 +269,7 @@ import TyphoonVisualization from "../../components/typhoon-visualization/typhoon
|
|
|
import CesiumThreeFusion from "@/components/ThreeCesiumIntegration/CesiumThreeFusion.vue"; //Three.js与Cesium融合组件
|
|
|
import ThreeModelViewer from "@/components/ThreeModelViewer/ModelViewer.vue"; //模型查看器组件
|
|
|
import { CircleClose, Plus, CirclePlus, Setting } from '@element-plus/icons-vue'; //删除图标
|
|
|
-import { listModel } from '@/api/watershed/model'; //模型API
|
|
|
+import { listModel, getModel } from '@/api/watershed/model'; //模型API
|
|
|
import { getDefaultMapConfig, saveMapConfig } from '@/api/cesium/mapConfig'; //地图配置API
|
|
|
import serviceApi from '@/api/watershed/service'; //自定义服务API
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
@@ -487,7 +487,7 @@ export default {
|
|
|
format: model.format,
|
|
|
uploadUnit: model.uploadUnit || '未知单位',
|
|
|
filePath: model.filePath || model.file_path || model.url || '',
|
|
|
- coordinates: model.coordinates,
|
|
|
+ coordinates: model.coordinates || model.modelCoordinates || '',
|
|
|
rotationX: model.rotationX != null ? model.rotationX : (model.rotation_x != null ? model.rotation_x : 0),
|
|
|
rotationY: model.rotationY != null ? model.rotationY : (model.rotation_y != null ? model.rotation_y : 0),
|
|
|
rotationZ: model.rotationZ != null ? model.rotationZ : (model.rotation_z != null ? model.rotation_z : 0),
|
|
|
@@ -534,6 +534,31 @@ export default {
|
|
|
console.log('已加载的模型实体:', this.loadedModelEntities)
|
|
|
console.log('isModelLoaded结果:', this.isModelLoaded(model.id))
|
|
|
|
|
|
+ try {
|
|
|
+ const latestData = await getModel(model.id)
|
|
|
+ if (latestData && latestData.data) {
|
|
|
+ const latest = latestData.data
|
|
|
+ model.coordinates = latest.coordinates || latest.modelCoordinates || model.coordinates
|
|
|
+ model.rotationX = latest.rotationX != null ? latest.rotationX : (model.rotationX || 0)
|
|
|
+ model.rotationY = latest.rotationY != null ? latest.rotationY : (model.rotationY || 0)
|
|
|
+ model.rotationZ = latest.rotationZ != null ? latest.rotationZ : (model.rotationZ || 0)
|
|
|
+ model.scaleX = latest.scaleX != null ? latest.scaleX : (model.scaleX || 1)
|
|
|
+ model.scaleY = latest.scaleY != null ? latest.scaleY : (model.scaleY || 1)
|
|
|
+ model.scaleZ = latest.scaleZ != null ? latest.scaleZ : (model.scaleZ || 1)
|
|
|
+ console.log('已更新模型最新数据:', {
|
|
|
+ coordinates: model.coordinates,
|
|
|
+ rotationX: model.rotationX,
|
|
|
+ rotationY: model.rotationY,
|
|
|
+ rotationZ: model.rotationZ,
|
|
|
+ scaleX: model.scaleX,
|
|
|
+ scaleY: model.scaleY,
|
|
|
+ scaleZ: model.scaleZ
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (fetchError) {
|
|
|
+ console.warn('获取最新模型数据失败,使用缓存数据:', fetchError.message)
|
|
|
+ }
|
|
|
+
|
|
|
// 清除之前的模型编辑器和高亮模型
|
|
|
if (this.currentModelEditor) {
|
|
|
if (this.currentModelEditor.destroy) {
|
|
|
@@ -634,16 +659,28 @@ export default {
|
|
|
if (coords.length >= 2 && !isNaN(coords[0]) && !isNaN(coords[1])) {
|
|
|
const lon = coords[0]
|
|
|
const lat = coords[1]
|
|
|
- const height = coords[2] || 0
|
|
|
+ const modelHeight = coords[2] !== undefined && !isNaN(coords[2]) ? coords[2] : 0
|
|
|
+
|
|
|
+ console.log('解析到的模型高度:', modelHeight)
|
|
|
|
|
|
- // 获取地面高度
|
|
|
const cartographic = Cesium.Cartographic.fromDegrees(lon, lat)
|
|
|
- const terrainHeight = viewer.scene.globe.getHeight(cartographic)
|
|
|
- const groundHeight = terrainHeight || 0
|
|
|
|
|
|
- // 模型高度 = 地面高度 + 用户指定的高度
|
|
|
- position = Cesium.Cartesian3.fromDegrees(lon, lat, groundHeight + height)
|
|
|
- console.log('使用经纬度定位 - 经度:', lon, '纬度:', lat, '地面高度:', groundHeight, '模型高度:', height, '总高度:', groundHeight + height)
|
|
|
+ if (viewer.scene.globe && viewer.terrainProvider) {
|
|
|
+ try {
|
|
|
+ const updatedPositions = await Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [cartographic])
|
|
|
+ const terrainHeight = updatedPositions[0].height || 0
|
|
|
+ const finalHeight = terrainHeight + modelHeight
|
|
|
+ position = Cesium.Cartesian3.fromDegrees(lon, lat, finalHeight)
|
|
|
+ console.log('使用地形高度定位 - 经度:', lon, '纬度:', lat, '地形高度:', terrainHeight, '模型高度:', modelHeight, '总高度:', finalHeight)
|
|
|
+ } catch (terrainError) {
|
|
|
+ console.warn('获取地形高度失败,使用默认高度:', terrainError.message)
|
|
|
+ position = Cesium.Cartesian3.fromDegrees(lon, lat, modelHeight)
|
|
|
+ console.log('使用模型指定高度 - 经度:', lon, '纬度:', lat, '模型高度:', modelHeight)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ position = Cesium.Cartesian3.fromDegrees(lon, lat, modelHeight)
|
|
|
+ console.log('无地形服务,使用绝对高度 - 经度:', lon, '纬度:', lat, '高度:', modelHeight)
|
|
|
+ }
|
|
|
} else {
|
|
|
console.warn('经纬度格式不正确或为NaN,使用默认位置')
|
|
|
position = Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0)
|
|
|
@@ -693,6 +730,7 @@ export default {
|
|
|
const scaleY = model.scaleY || 1;
|
|
|
const scaleZ = model.scaleZ || 1;
|
|
|
entity.model.scale = (scaleX + scaleY + scaleZ) / 3;
|
|
|
+ entity._modelScale = { x: scaleX, y: scaleY, z: scaleZ };
|
|
|
}
|
|
|
|
|
|
console.log('实体已添加:', entity)
|
|
|
@@ -703,17 +741,64 @@ export default {
|
|
|
|
|
|
if (shouldFlyTo) {
|
|
|
setTimeout(() => {
|
|
|
- try {
|
|
|
- viewer.flyTo(entity, {
|
|
|
- duration: 2,
|
|
|
- offset: new Cesium.HeadingPitchRange(Cesium.Math.toRadians(0), Cesium.Math.toRadians(-30), 5)
|
|
|
- })
|
|
|
- console.log('开始飞行到模型位置')
|
|
|
- } catch (flyError) {
|
|
|
- console.error('飞行失败:', flyError)
|
|
|
- ElMessage.warning('模型已加载,但跳转失败')
|
|
|
- }
|
|
|
- }, 100)
|
|
|
+ const calculateFlyDistance = () => {
|
|
|
+ const tryGetModelSize = (attempts = 0) => {
|
|
|
+ if (attempts > 15) {
|
|
|
+ console.log('多次尝试获取模型尺寸失败,使用默认距离');
|
|
|
+ viewer.flyTo(entity, {
|
|
|
+ duration: 2,
|
|
|
+ offset: new Cesium.HeadingPitchRange(Cesium.Math.toRadians(0), Cesium.Math.toRadians(-30), 100)
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const entityPosition = entity.position.getValue(viewer.clock.currentTime);
|
|
|
+ if (!entityPosition) {
|
|
|
+ console.log('无法获取实体位置');
|
|
|
+ setTimeout(() => tryGetModelSize(attempts + 1), 300);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let bestModel = null;
|
|
|
+ let bestDistance = Infinity;
|
|
|
+
|
|
|
+ for (let i = 0; i < viewer.scene.primitives.length; i++) {
|
|
|
+ const primitive = viewer.scene.primitives.get(i);
|
|
|
+ if (primitive instanceof Cesium.Model) {
|
|
|
+ const modelPosition = primitive.modelMatrix ? primitive.modelMatrix.clone() : null;
|
|
|
+ if (modelPosition) {
|
|
|
+ const modelCartesian = Cesium.Matrix4.getTranslation(modelPosition, new Cesium.Cartesian3());
|
|
|
+ const distance = Cesium.Cartesian3.distance(entityPosition, modelCartesian);
|
|
|
+ if (distance < bestDistance) {
|
|
|
+ bestDistance = distance;
|
|
|
+ bestModel = primitive;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bestModel && bestModel.boundingSphere && bestModel.boundingSphere.radius > 0) {
|
|
|
+ const modelRadius = bestModel.boundingSphere.radius;
|
|
|
+ const flyDistance = modelRadius * 3;
|
|
|
+ console.log('通过位置匹配找到模型,半径:', modelRadius, '飞行距离:', flyDistance);
|
|
|
+
|
|
|
+ viewer.flyTo(entity, {
|
|
|
+ duration: 2,
|
|
|
+ offset: new Cesium.HeadingPitchRange(Cesium.Math.toRadians(0), Cesium.Math.toRadians(-30), flyDistance)
|
|
|
+ });
|
|
|
+ console.log('开始飞行到模型位置,模型半径:', modelRadius, '飞行距离:', flyDistance);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('等待模型加载完成,尝试次数:', attempts + 1);
|
|
|
+ setTimeout(() => tryGetModelSize(attempts + 1), 300);
|
|
|
+ };
|
|
|
+
|
|
|
+ tryGetModelSize();
|
|
|
+ };
|
|
|
+
|
|
|
+ calculateFlyDistance();
|
|
|
+ }, 1500)
|
|
|
}
|
|
|
|
|
|
this.saveLoadedServices()
|
|
|
@@ -1023,10 +1108,19 @@ export default {
|
|
|
});
|
|
|
break;
|
|
|
case "tianDiTuTerrain":
|
|
|
- var t_Provider = new Cesium.TiandituTerrainProvider({
|
|
|
- token: "3fb1e9fda20ee995dc815c8243553ce8"
|
|
|
- });
|
|
|
- viewer.terrainProvider = t_Provider;
|
|
|
+ console.log('加载 Cesium 官方地形...');
|
|
|
+ const cesiumIonToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiZGYwNWZmMi0wYTJjLTQ3MDgtODk3Mi1mNTg4YjljZTMzYWUiLCJpZCI6MjA0NTU5LCJpYXQiOjE3MTE0NDc4NDh9.xU-eWEQxv-FeADvsH_uM35EKRN6brqmXl1AQm6phnEM";
|
|
|
+ Cesium.Ion.defaultAccessToken = cesiumIonToken;
|
|
|
+ try {
|
|
|
+ viewer.terrainProvider = Cesium.createWorldTerrain({
|
|
|
+ requestWaterMask: true,
|
|
|
+ requestVertexNormals: true
|
|
|
+ });
|
|
|
+ console.log('Cesium 地形加载成功');
|
|
|
+ } catch (e) {
|
|
|
+ console.error('Cesium 地形加载失败:', e);
|
|
|
+ viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();
|
|
|
+ }
|
|
|
break;
|
|
|
case "supermapOnlineTerrain":
|
|
|
viewer.terrainProvider = new Cesium.SCTTerrainProvider({
|