diff --git a/public/images/plane.png b/public/images/plane.png new file mode 100644 index 0000000..7ba4910 Binary files /dev/null and b/public/images/plane.png differ diff --git a/src/views/simulationScene/instructor/system/display/BaseDraw.js b/src/views/simulationScene/instructor/system/display/BaseDraw.js new file mode 100644 index 0000000..8e112be --- /dev/null +++ b/src/views/simulationScene/instructor/system/display/BaseDraw.js @@ -0,0 +1,91 @@ +import * as Cesium from 'cesium' + +// 作战区域 1 保障区域 2 模型 3 图片 4 +export const ENTITY_TYPES = { + WARZONE: 1, + SAFEZONE: 2, + + MODEL: 3, + IMAGE: 4, + ROUTE: 5, + + LINE: 6, // 两个模型之间的连线 + POINT_PLANNING: 7, // 规划点 + + GRAPHICS: 8, // 折线 + + AIR_ROUTE: 9, // 航路 + ROAMING_PLANE: 10, +} + +export default class BaseDraw { + /** + * @type {Cesium.Viewer} + * @description Cesium Viewer 实例 + */ + viewer = null + isComplete = false + + /** + * @type {Cesium.ScreenSpaceEventHandler} + */ + handler = null + constructor(viewer) { + if (!viewer) throw new Error('viewer is null') + this.viewer = viewer + this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas) + } + + start() { + throw new Error('start() is not implemented') + } + + /** + * 将 Cartesian3 坐标转换为海拔高度(WGS84 高度) + * @param {Cesium.Cartesian3} cartesian - Cartesian3 坐标 + * @returns {Number} 海拔高度(米) + */ + getAltitudeFromCartesian(cartesian) { + const ellipsoid = Cesium.Ellipsoid.WGS84 + const cartographic = ellipsoid.cartesianToCartographic(cartesian) + // 如果需要考虑地形高度,可以使用 sampleTerrain 提取真实地形高度 + return cartographic.height || 0 + } + + /** + * 获取高度的文本 + * @param {Cesium.Cartesian3} position + * @returns + */ + getHeightText(position) { + return `${this.getAltitudeFromCartesian(position).toFixed(1)}m` + } + + calculateDistance(position0, position1) { + const distance = Cesium.Cartesian3.distance(position0, position1) + return distance + } + + formatDistance(distance, precision = 1) { + if (distance > 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 @@ + + + + +