| | |
| | | import { cartesianToXY } from "@/utils/map" |
| | | let water = null |
| | | import { useSimStore } from "@/store/simulation"; |
| | | import { storeToRefs } from "pinia"; |
| | | const simStore = useSimStore(); |
| | | const { waterLegendData } = storeToRefs(simStore); |
| | | let water = null; |
| | | |
| | | /** |
| | | * 销毁水体模拟层 |
| | | */ |
| | | export function destoryWaterPrimitive() { |
| | | if (water) { |
| | | water.destroy() |
| | | water = null |
| | | } |
| | | if (water) { |
| | | enableWaterArrowFlow(false); |
| | | water.destroy(); |
| | | water = null; |
| | | // console.log("Water simulation destroyed."); |
| | | } |
| | | } |
| | | |
| | | export function createWaterPrimitive(rainfall) { |
| | | if (water) { |
| | | water.rainfall = rainfall |
| | | return |
| | | } |
| | | let positionArray = [ |
| | | { |
| | | x: -2172418.4199554003, |
| | | y: 4339741.174232391, |
| | | z: 4124707.9687457774, |
| | | }, |
| | | { |
| | | x: -2173054.1197314346, |
| | | y: 4339420.091643301, |
| | | z: 4124710.896091218, |
| | | }, |
| | | { |
| | | x: -2172832.10576698, |
| | | y: 4338665.615224519, |
| | | z: 4125615.341361447, |
| | | }, |
| | | { |
| | | x: -2171464.714295606, |
| | | y: 4337884.628113293, |
| | | z: 4127145.919793182, |
| | | }, |
| | | { |
| | | x: -2170738.824348358, |
| | | y: 4338621.865525843, |
| | | z: 4126755.442367371, |
| | | }, |
| | | { |
| | | x: -2171270.181257778, |
| | | y: 4338967.11477535, |
| | | z: 4126117.1692552743, |
| | | }, |
| | | { |
| | | x: -2171120.444962885, |
| | | y: 4339310.237335228, |
| | | z: 4125837.0031219805, |
| | | }, |
| | | { |
| | | x: -2171911.8873938583, |
| | | y: 4339707.853907823, |
| | | z: 4125007.7462886167, |
| | | }, |
| | | { |
| | | x: -2171934.494218292, |
| | | y: 4339685.285760623, |
| | | z: 4125019.506657141, |
| | | }, |
| | | ] |
| | | const coordinates = [] |
| | | positionArray.forEach(item => { |
| | | const result = cartesianToXY(item) |
| | | coordinates.push(result.longitude, result.latitude, result.height) |
| | | }) |
| | | water = earthCtrl.analysis.createWaterSimulateGPU({ |
| | | //isDraw: true, // 是否绘制水面 |
| | | height: -5, |
| | | maxHeight: 2000, |
| | | coordinates: coordinates, |
| | | // coordinates: [ |
| | | // 116.57628914253382, 40.5654461866556, 0, 116.57628914253382, 40.552898897029046, 0, |
| | | // 116.60855621443835, 40.552898897029046, 0, 116.60855621443835, 40.5654461866556, 0, |
| | | // ], |
| | | // coordinates: [ |
| | | // 116.568865, 40.590729, 0, 116.568865, 40.533505, 0, |
| | | // 116.608505, 40.533505, 0, 116.608505, 40.590729, 0, |
| | | // ], |
| | | }) |
| | | console.log("water", water) |
| | | /** |
| | | * 创建水体模拟层 |
| | | * @param {Object} options - 可选参数 |
| | | * @param {number} options.interval - 水体模拟的时间间隔(单位:毫秒) |
| | | * @param {string} options.baseUrl - 仿真服务地址 |
| | | * @param {boolean} options.colorRender - 是否启用颜色渲染 |
| | | */ |
| | | export async function createWaterPrimitive(options = {}) { |
| | | const { |
| | | baseUrl = "/simu/c2h1dc", |
| | | interval = 1000, |
| | | colorRender = true, |
| | | minFlowRate = 0.1, // 新增参数 |
| | | maxFlowRate = 12, // 新增参数 |
| | | } = options; |
| | | |
| | | // water.rainfall = 0.0001; // 调节雨量 |
| | | // water.rainPointMax = 2.0; // 渗水阈值 |
| | | // water.attenuation = 0.995; // 衰减 |
| | | // water.strenght = 0.25 // 水流强度 |
| | | // 定义水深颜色映射的色标 |
| | | const colorStops = [ |
| | | "#09a2dc", |
| | | "#58c196", |
| | | "#bedf74", |
| | | "#d7f06e", |
| | | "#ffe930", |
| | | "#fdd10a", |
| | | "#feb652", |
| | | "#fd7f06", |
| | | "#fe2b07", |
| | | "#4d0a08", |
| | | ]; |
| | | |
| | | const levelCount = colorStops.length; |
| | | const minAllowed = 0.05; // 最小允许值 |
| | | const threshold = 1; // 小值与大值分界点 |
| | | |
| | | let effectiveMin = Math.max(minFlowRate, minAllowed); // 最小不能小于 0.01 |
| | | |
| | | const waterHeightLevels = []; |
| | | |
| | | // 分两段构造高度数组 |
| | | for (let i = 0; i < levelCount; i++) { |
| | | let ratio = i / (levelCount - 1); // 0 ~ 1 |
| | | |
| | | let height; |
| | | if (ratio <= 0.5) { |
| | | // 前半段:低值区域,使用强指数增长,从 effectiveMin 到 threshold |
| | | const localRatio = ratio * 2; // 映射到 0~1 |
| | | const expRatio = Math.pow(localRatio, 2); // 更强调低值区域密度 |
| | | height = effectiveMin + (threshold - effectiveMin) * expRatio; |
| | | } else { |
| | | // 后半段:高值区域,从 threshold 到 maxFlowRate,使用指数增长 |
| | | const localRatio = (ratio - 0.5) * 2; // 映射到 0~1 |
| | | const expBase = Math.exp(Math.log(maxFlowRate / threshold) / 1); |
| | | height = threshold * Math.pow(expBase, localRatio); |
| | | } |
| | | |
| | | waterHeightLevels.push({ |
| | | height: parseFloat(height.toFixed(2)), // 保留两位小数 |
| | | color: colorStops[i], |
| | | }); |
| | | } |
| | | |
| | | waterLegendData.value = waterHeightLevels; |
| | | // console.log(waterLegendData.value, "图例数据"); |
| | | water = await earthCtrl.simulate.createWaterSimulateLayer({ |
| | | baseUrl, |
| | | interval, |
| | | color: SmartEarth.Cesium.Color.fromCssColorString("#D4F2E7"), |
| | | loop: false, |
| | | callback: timeCallback, |
| | | alphaByDepth: -0.3, |
| | | waterHeightLevels, |
| | | colorRender, |
| | | sizeIndex: 0, |
| | | }); |
| | | //防止缩放导致地形变动压盖水面,水面增加设置 |
| | | water.clampMinHeight = 0; //相机相对于水面最小高度 |
| | | water.clampMaxHeight = 1000; //相机相对于水面最大高度 |
| | | water.offsetMinHeight = 0; //水偏移最小高度 |
| | | water.offsetMaxHeight = 100; //水偏移最大高度 |
| | | // 是否开启箭头 |
| | | enableWaterArrowFlow(false); |
| | | // 是否开启水面阴影 |
| | | toggleWaterShadow(false); |
| | | |
| | | // console.log( |
| | | // `仿真模拟参数:请求路径 ${baseUrl}, 帧间间隔 ${interval}ms, 是否开启专题渲染 ${colorRender}` |
| | | // ); |
| | | } |
| | | |
| | | /** |
| | | * 初始化水体模拟视图 |
| | | */ |
| | | export function initeWaterPrimitiveView() { |
| | | let view = { |
| | | destination: { |
| | | x: -2173603.2294639186, |
| | | y: 4338938.333124211, |
| | | z: 4128027.401463165, |
| | | }, |
| | | orientation: { |
| | | pitch: -0.6208443477400212, |
| | | roll: 0.000049799989940702005, |
| | | heading: 3.6294612473618644, |
| | | }, |
| | | } |
| | | viewer.scene.camera.flyTo(view) |
| | | let view = { |
| | | destination: { |
| | | x: -2173603.2294639186, |
| | | y: 4338938.333124211, |
| | | z: 4128027.401463165, |
| | | }, |
| | | orientation: { |
| | | pitch: -0.6208443477400212, |
| | | roll: 0.000049799989940702005, |
| | | heading: 3.6294612473618644, |
| | | }, |
| | | }; |
| | | viewer.scene.camera.flyTo(view); |
| | | // console.log("Camera view initialized for water simulation."); |
| | | } |
| | | /** |
| | | * 更换水透明度 |
| | | */ |
| | | export function updateWaterColor(color, alpha) { |
| | | if (water) { |
| | | water.color = Cesium.Color.fromCssColorString(color); |
| | | water.alphaByDepth = alpha; |
| | | } else { |
| | | console.warn("No water simulation to pause."); |
| | | } |
| | | } |
| | | /** |
| | | * 暂停水体模拟 |
| | | */ |
| | | export function pauseWaterSimulation() { |
| | | if (water) { |
| | | water.pause(); |
| | | // console.log("暂停仿真"); |
| | | } else { |
| | | console.warn("No water simulation to pause."); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 恢复水体模拟 |
| | | */ |
| | | export function resumeWaterSimulation() { |
| | | if (water) { |
| | | water.resume(); |
| | | // console.log("继续仿真"); |
| | | } else { |
| | | console.warn("No water simulation to resume."); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 跳转到某个时间点的水面状态 |
| | | * @param {number} closestIndex - 目标时间戳索引 |
| | | */ |
| | | export function setTimeForWaterSimulation(closestIndex) { |
| | | if (water) { |
| | | const imageList = water.getTimeList(); |
| | | |
| | | if (!imageList.length) { |
| | | console.warn("No timestamps available for water simulation."); |
| | | return; |
| | | } |
| | | // const idx = Math.floor(Math.random() * imageList.length); //随机索引跳转,实际中用不到,只用作演示 |
| | | // console.log( |
| | | // `Jumping to timestamp: count:[${imageList.length}], index:[${closestIndex}]` |
| | | // ); |
| | | water.setTime(imageList[closestIndex]); |
| | | } else { |
| | | console.warn("No water simulation to set time for."); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置或关闭颜色渲染 |
| | | * @param {boolean} enabled |
| | | */ |
| | | export function toggleWaterColorRender(enabled) { |
| | | if (water) { |
| | | water.colorRender = enabled; |
| | | // console.log(`是否开启专题渲染 ${enabled}`); |
| | | } else { |
| | | console.warn("No water simulation to toggle color rendering."); |
| | | } |
| | | } |
| | | // ==================【SDK 新增功能 - 箭头流向 & 阴影控制】================== |
| | | |
| | | /** |
| | | * 开启/关闭箭头流向动画 |
| | | * @param {boolean} enabled - 是否启用箭头动画 |
| | | */ |
| | | export function enableWaterArrowFlow(enabled) { |
| | | if (water) { |
| | | // 默认关闭状态 |
| | | water.flowEnabled = enabled; // 假设 SDK 支持此属性 |
| | | // console.log(`箭头流向动画已${enabled ? "开启" : "关闭"}`); |
| | | } else { |
| | | console.warn("未找到水体模拟图层,请先启动洪水模拟"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 开启/关闭全局阴影效果 |
| | | * @param {boolean} enabled - 是否启用阴影 |
| | | */ |
| | | export function toggleWaterShadow(enabled) { |
| | | if (!viewer) { |
| | | console.warn("Cesium Viewer 未初始化,无法设置阴影"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | earthCtrl.shadows = enabled; |
| | | if (enabled) { |
| | | earthCtrl.shadowMap.maximumDistance = 10000.0; //最大距离 |
| | | earthCtrl.shadowMap.pointLightRadius = 50.0; //点光源半径 |
| | | } |
| | | // console.log(`阴影效果已${enabled ? "开启" : "关闭"}`); |
| | | } catch (error) { |
| | | console.error("设置阴影失败:", error); |
| | | } |
| | | } |
| | | |
| | | // ================================================== |
| | | /** |
| | | * 时间戳回调函数 |
| | | * @param {number} timeStamp - 当前时间戳 |
| | | */ |
| | | function timeCallback(timeStamp) { |
| | | // console.log(`Current timestamp: ${timeStamp}`); |
| | | } |