From ef40b81a5084c116e445339bec521cd9b7da4373 Mon Sep 17 00:00:00 2001 From: kaifa <2496371772@qq.com> Date: Mon, 15 Sep 2025 09:13:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=8E=AF=E5=A2=83=E6=95=88?= =?UTF-8?q?=E6=9E=9C=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/images/plane.png | Bin 0 -> 2960 bytes .../instructor/system/display/BaseDraw.js | 91 ++++ .../instructor/system/display/CesiumHelper.js | 107 +++++ .../instructor/system/utils/Effect/rain.js | 84 ++++ .../instructor/system/utils/Effect/snow.js | 84 ++++ .../trainer/system/simulationModel/BzTask.vue | 233 +++++++++ .../trainer/system/simulationModel/Jcsx.vue | 446 ++++++++++++++++++ .../system/simulationModel/LonLatInput.vue | 143 ++++++ .../trainer/system/simulationModel/Zzxd.vue | 166 +++++++ .../trainer/system/simulationModel/index1.vue | 246 ++++++++++ 10 files changed, 1600 insertions(+) create mode 100644 public/images/plane.png create mode 100644 src/views/simulationScene/instructor/system/display/BaseDraw.js create mode 100644 src/views/simulationScene/instructor/system/display/CesiumHelper.js create mode 100644 src/views/simulationScene/instructor/system/utils/Effect/rain.js create mode 100644 src/views/simulationScene/instructor/system/utils/Effect/snow.js create mode 100644 src/views/simulationScene/trainer/system/simulationModel/BzTask.vue create mode 100644 src/views/simulationScene/trainer/system/simulationModel/Jcsx.vue create mode 100644 src/views/simulationScene/trainer/system/simulationModel/LonLatInput.vue create mode 100644 src/views/simulationScene/trainer/system/simulationModel/Zzxd.vue create mode 100644 src/views/simulationScene/trainer/system/simulationModel/index1.vue diff --git a/public/images/plane.png b/public/images/plane.png new file mode 100644 index 0000000000000000000000000000000000000000..7ba491090cff146903664b2723a3b11e676742e5 GIT binary patch literal 2960 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 1000) { + return `${(distance / 1000).toFixed(precision)}km` + } + return `${distance.toFixed(precision)}m` + } + + /** + * 未完成时的清理 + */ + clear() { + console.warn('clear() is not implemented') + } + + /** + * 销毁事件处理器 + */ + destroyHandler() { + if (!this.handler) return + this.handler.destroy() + this.handler = null + } +} diff --git a/src/views/simulationScene/instructor/system/display/CesiumHelper.js b/src/views/simulationScene/instructor/system/display/CesiumHelper.js new file mode 100644 index 0000000..9f072e1 --- /dev/null +++ b/src/views/simulationScene/instructor/system/display/CesiumHelper.js @@ -0,0 +1,107 @@ +import * as Cesium from 'cesium' + +/** + * 兼容模型和地形上坐标拾取 + * @param {Cesium.Viewer} viewer + * @param {*} px + * @returns + */ +export const getCatesian3FromPX = (viewer, px) => { + const picks = viewer.scene.drillPick(px) + viewer.scene.render() + let cartesian + let isOn3dtiles = false + for (var i = 0; i < picks.length; i++) { + if ( + picks[i] && + picks[i].primitive && + picks[i].primitive instanceof Cesium.Cesium3DTileset + ) { + //模型上拾取 + isOn3dtiles = true + break + } + } + if (isOn3dtiles) { + cartesian = viewer.scene.pickPosition(px) + } else { + var ray = viewer.camera.getPickRay(px) + if (!ray) return null + cartesian = viewer.scene.globe.pick(ray, viewer.scene) + } + return cartesian +} + +// catesian3坐标转经纬度坐标 +export function getLngLatFromCartisian3(cartesian3) { + const { longitude, latitude, height } = + Cesium.Cartographic.fromCartesian(cartesian3) + return { + longitude: radiansToDegrees(longitude), + latitude: radiansToDegrees(latitude), + height, + } +} + +/** + * 将弧度值转换为角度值 + * @param {number} radians - 弧度值 + * @return {number} 角度值 + */ +export const radiansToDegrees = (radians) => { + return Cesium.Math.toDegrees(radians) +} + +export const degreesToRadians = (degrees) => { + return Cesium.Math.toRadians(degrees) +} + +export const mixDegree = (west, south, east, north) => { + return [ + [west, north], + [east, north], + [east, south], + [west, south], + ] +} + +/** + * + * @param {Cesium.Viewer} viewer + * @param {Cesium.Cartesian2} position + * @returns + */ +export const getCartesian3ByPosition = (viewer, position) => { + const _position = viewer.scene.globe.pick( + viewer.camera.getPickRay(position), + viewer.scene + ) + + if (Cesium.defined(position)) { + return _position + } + return null +} +/** + * 获取模型自身参数 + * @param {Cesium.Viewer} viewer + * @param {Cesium.Entity} entity + * @returns {Promise<{ center: Cesium.Cartesian3; radius: number }>} + */ +export const getSphere = (viewer, entity) => { + return new Promise((resolve) => { + // entity没有加载完成时 state 不会等于0 所以设置定时器直到获取到为止 + const interval = setInterval(() => { + const sphere = new Cesium.BoundingSphere() + const state = viewer._dataSourceDisplay.getBoundingSphere( + entity, + false, + sphere + ) + if (state === Cesium.BoundingSphereState.DONE) { + clearInterval(interval) + resolve(sphere) + } + }, 100) + }) +} diff --git a/src/views/simulationScene/instructor/system/utils/Effect/rain.js b/src/views/simulationScene/instructor/system/utils/Effect/rain.js new file mode 100644 index 0000000..1766c15 --- /dev/null +++ b/src/views/simulationScene/instructor/system/utils/Effect/rain.js @@ -0,0 +1,84 @@ +/* + * @Descripttion: 雨粒子效果 + * @Author: 笙痞 + * @Date: 2023-01-04 15:01:03 + * @LastEditors: 笙痞77 + * @LastEditTime: 2023-05-19 09:54:15 + */ +import * as Cesium from 'cesium' + +class RainEffect { + constructor(viewer, options) { + if (!viewer) throw new Error('no viewer object!') + options = options || {} + //倾斜角度,负数向右,正数向左 + this.tiltAngle = Cesium.defaultValue(options.tiltAngle, -0.6) + this.rainSize = Cesium.defaultValue(options.rainSize, 0.3) + this.rainSpeed = Cesium.defaultValue(options.rainSpeed, 120.0) + this.viewer = viewer + this.init() + } + + init() { + this.rainStage = new Cesium.PostProcessStage({ + name: 'czm_rain', + fragmentShader: this.rain(), + uniforms: { + tiltAngle: () => { + return this.tiltAngle + }, + rainSize: () => { + return this.rainSize + }, + rainSpeed: () => { + return this.rainSpeed + }, + }, + }) + this.viewer.scene.postProcessStages.add(this.rainStage) + } + + destroy() { + if (!this.viewer || !this.rainStage) return + this.viewer.scene.postProcessStages.remove(this.rainStage) + const isDestroyed = this.rainStage.isDestroyed() + // 先检查是否被销毁过,如果已经被销毁过再调用destroy会报错 + if (!isDestroyed) { + this.rainStage.destroy() + } + delete this.tiltAngle + delete this.rainSize + delete this.rainSpeed + } + + show(visible) { + this.rainStage.enabled = visible + } + + rain() { + return 'uniform sampler2D colorTexture;\n\ + varying vec2 v_textureCoordinates;\n\ + uniform float tiltAngle;\n\ + uniform float rainSize;\n\ + uniform float rainSpeed;\n\ + float hash(float x) {\n\ + return fract(sin(x * 133.3) * 13.13);\n\ + }\n\ + void main(void) {\n\ + float time = czm_frameNumber / rainSpeed;\n\ + vec2 uv = (gl_FragCoord.xy - czm_viewport.xy) / czm_viewport.zw;\n\ + vec3 c = vec3(.6, .7, .8);\n\ + float a = tiltAngle;\n\ + float si = sin(a), co = cos(a);\n\ + uv *= mat2(co, -si, si, co);\n\ + uv *= length(uv + vec2(0, 4.9)) * rainSize + 1.;\n\ + float v = 1. - sin(hash(floor(uv.x * 100.)) * 2.);\n\ + float b = clamp(abs(sin(20. * time * v + uv.y * (5. / (2. + v)))) - .95, 0., 1.) * 20.;\n\ + c *= v * b;\n\ + gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c, 1), .5);\n\ + }\n\ + ' + } +} + +export default RainEffect diff --git a/src/views/simulationScene/instructor/system/utils/Effect/snow.js b/src/views/simulationScene/instructor/system/utils/Effect/snow.js new file mode 100644 index 0000000..807e282 --- /dev/null +++ b/src/views/simulationScene/instructor/system/utils/Effect/snow.js @@ -0,0 +1,84 @@ +/* + * @Descripttion: 雪花粒子类 + * @Author: 笙痞 + * @Date: 2023-01-04 14:01:07 + * @LastEditors: 笙痞77 + * @LastEditTime: 2023-05-19 09:52:52 + */ + +import * as Cesium from 'cesium' +class SnowEffect { + constructor(viewer, options) { + if (!viewer) throw new Error('no viewer object!') + options = options || {} + this.snowSize = Cesium.defaultValue(options.snowSize, 0.02)// ❄️大小,最好小于0.02 + this.snowSpeed = Cesium.defaultValue(options.snowSpeed, 60.0) // 速度 + this.viewer = viewer + this.init() + } + + init() { + this.snowStage = new Cesium.PostProcessStage({ + name: 'czm_snow', + fragmentShader: this.snow(), + uniforms: { + snowSize: () => { + return this.snowSize + }, + snowSpeed: () => { + return this.snowSpeed + }, + }, + }) + this.viewer.scene.postProcessStages.add(this.snowStage) + } + + destroy() { + if (!this.viewer || !this.snowStage) return + this.viewer.scene.postProcessStages.remove(this.snowStage) + const isDestroyed = this.snowStage.isDestroyed() + // 先检查是否被销毁过,如果已经被销毁过再调用destroy会报错 + if (!isDestroyed) { + this.snowStage.destroy() + } + delete this.snowSize + delete this.snowSpeed + } + show(visible) { + this.snowStage.enabled = visible + } + + snow() { + return 'uniform sampler2D colorTexture;\n\ + varying vec2 v_textureCoordinates;\n\ + uniform float snowSpeed;\n\ + uniform float snowSize;\n\ + float snow(vec2 uv,float scale)\n\ + {\n\ + float time=czm_frameNumber/snowSpeed;\n\ + float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;\n\ + uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;\n\ + uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;\n\ + p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);\n\ + k=smoothstep(0.,k,sin(f.x+f.y)*snowSize);\n\ + return k*w;\n\ + }\n\ + void main(void){\n\ + vec2 resolution=czm_viewport.zw;\n\ + vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n\ + vec3 finalColor=vec3(0);\n\ + float c=0.;\n\ + c+=snow(uv,30.)*.0;\n\ + c+=snow(uv,20.)*.0;\n\ + c+=snow(uv,15.)*.0;\n\ + c+=snow(uv,10.);\n\ + c+=snow(uv,8.);\n\ + c+=snow(uv,6.);\n\ + c+=snow(uv,5.);\n\ + finalColor=(vec3(c));\n\ + gl_FragColor=mix(texture2D(colorTexture,v_textureCoordinates),vec4(finalColor,1),.5);\n\ + }\n\ + ' + } +} +export default SnowEffect diff --git a/src/views/simulationScene/trainer/system/simulationModel/BzTask.vue b/src/views/simulationScene/trainer/system/simulationModel/BzTask.vue new file mode 100644 index 0000000..181ff48 --- /dev/null +++ b/src/views/simulationScene/trainer/system/simulationModel/BzTask.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/src/views/simulationScene/trainer/system/simulationModel/Jcsx.vue b/src/views/simulationScene/trainer/system/simulationModel/Jcsx.vue new file mode 100644 index 0000000..a6c8fca --- /dev/null +++ b/src/views/simulationScene/trainer/system/simulationModel/Jcsx.vue @@ -0,0 +1,446 @@ + + + + + + diff --git a/src/views/simulationScene/trainer/system/simulationModel/LonLatInput.vue b/src/views/simulationScene/trainer/system/simulationModel/LonLatInput.vue new file mode 100644 index 0000000..43fe543 --- /dev/null +++ b/src/views/simulationScene/trainer/system/simulationModel/LonLatInput.vue @@ -0,0 +1,143 @@ + + + + + diff --git a/src/views/simulationScene/trainer/system/simulationModel/Zzxd.vue b/src/views/simulationScene/trainer/system/simulationModel/Zzxd.vue new file mode 100644 index 0000000..f5337f0 --- /dev/null +++ b/src/views/simulationScene/trainer/system/simulationModel/Zzxd.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/src/views/simulationScene/trainer/system/simulationModel/index1.vue b/src/views/simulationScene/trainer/system/simulationModel/index1.vue new file mode 100644 index 0000000..f17eaaf --- /dev/null +++ b/src/views/simulationScene/trainer/system/simulationModel/index1.vue @@ -0,0 +1,246 @@ + + + + +