Compare commits
	
		
			2 Commits
		
	
	
		
			e5dc139a6b
			...
			2c0b750b87
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2c0b750b87 | ||
| 
						 | 
					1d8f4af93c | 
							
								
								
									
										
											BIN
										
									
								
								public/images/fire.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/images/fire.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 756 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/models/导弹整体.glb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/models/导弹整体.glb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/models/第一级.glb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/models/第一级.glb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/models/第三级.glb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/models/第三级.glb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/models/第二级.glb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/models/第二级.glb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/models/美三叉戟2动画.glb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/models/美三叉戟2动画.glb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/models/美三叉戟2整体.glb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/models/美三叉戟2整体.glb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/models/美三叉戟2第一级.glb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/models/美三叉戟2第一级.glb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/models/美三叉戟2第三级.glb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/models/美三叉戟2第三级.glb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/models/美三叉戟2第二级.glb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/models/美三叉戟2第二级.glb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@ -2,6 +2,15 @@ export default class ExplosionEffect {
 | 
				
			|||||||
  constructor(viewer, obj) {
 | 
					  constructor(viewer, obj) {
 | 
				
			||||||
    this.viewer = viewer
 | 
					    this.viewer = viewer
 | 
				
			||||||
    this.viewModel = {
 | 
					    this.viewModel = {
 | 
				
			||||||
 | 
					      // emissionRate: 5,
 | 
				
			||||||
 | 
					      // gravity: 0.0, //设置重力参数
 | 
				
			||||||
 | 
					      // minimumParticleLife: 1,
 | 
				
			||||||
 | 
					      // maximumParticleLife: 6,
 | 
				
			||||||
 | 
					      // minimumSpeed: 1.0, //粒子发射的最小速度
 | 
				
			||||||
 | 
					      // maximumSpeed: 4.0, //粒子发射的最大速度
 | 
				
			||||||
 | 
					      // startScale: 0.0,
 | 
				
			||||||
 | 
					      // endScale: 8.0,
 | 
				
			||||||
 | 
					      // particleSize: 25.0,
 | 
				
			||||||
      emissionRate: 5,
 | 
					      emissionRate: 5,
 | 
				
			||||||
      gravity: 0.0, //设置重力参数
 | 
					      gravity: 0.0, //设置重力参数
 | 
				
			||||||
      minimumParticleLife: 1,
 | 
					      minimumParticleLife: 1,
 | 
				
			||||||
@ -10,7 +19,7 @@ export default class ExplosionEffect {
 | 
				
			|||||||
      maximumSpeed: 4.0, //粒子发射的最大速度
 | 
					      maximumSpeed: 4.0, //粒子发射的最大速度
 | 
				
			||||||
      startScale: 0.0,
 | 
					      startScale: 0.0,
 | 
				
			||||||
      endScale: 8.0,
 | 
					      endScale: 8.0,
 | 
				
			||||||
      particleSize: 25.0,
 | 
					      particleSize: 10.0,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.emitterModelMatrix = new Cesium.Matrix4()
 | 
					    this.emitterModelMatrix = new Cesium.Matrix4()
 | 
				
			||||||
    this.translation = new Cesium.Cartesian3()
 | 
					    this.translation = new Cesium.Cartesian3()
 | 
				
			||||||
@ -33,7 +42,8 @@ export default class ExplosionEffect {
 | 
				
			|||||||
    // this.viewer.trackedEntity = this.entity;
 | 
					    // this.viewer.trackedEntity = this.entity;
 | 
				
			||||||
    let particleSystem = this.scene.primitives.add(
 | 
					    let particleSystem = this.scene.primitives.add(
 | 
				
			||||||
      new Cesium.ParticleSystem({
 | 
					      new Cesium.ParticleSystem({
 | 
				
			||||||
        image: './images/explosion.png', //生成所需粒子的图片路径
 | 
					        // image: './images/explosion.png', //生成所需粒子的图片路径
 | 
				
			||||||
 | 
					        image: './images/fire.png', //生成所需粒子的图片路径
 | 
				
			||||||
        //粒子在生命周期开始时的颜色
 | 
					        //粒子在生命周期开始时的颜色
 | 
				
			||||||
        startColor: Cesium.Color.RED.withAlpha(0.7),
 | 
					        startColor: Cesium.Color.RED.withAlpha(0.7),
 | 
				
			||||||
        //粒子在生命周期结束时的颜色
 | 
					        //粒子在生命周期结束时的颜色
 | 
				
			||||||
@ -61,14 +71,33 @@ export default class ExplosionEffect {
 | 
				
			|||||||
        lifetime: 16.0,
 | 
					        lifetime: 16.0,
 | 
				
			||||||
        //设置粒子的大小是否以米或像素为单位
 | 
					        //设置粒子的大小是否以米或像素为单位
 | 
				
			||||||
        sizeInMeters: false,
 | 
					        sizeInMeters: false,
 | 
				
			||||||
 | 
					        // sizeInMeters: true,
 | 
				
			||||||
        //系统的粒子发射器
 | 
					        //系统的粒子发射器
 | 
				
			||||||
        emitter: new Cesium.CircleEmitter(5.0), //BoxEmitter 盒形发射器,ConeEmitter 锥形发射器,SphereEmitter 球形发射器,CircleEmitter圆形发射器
 | 
					        // emitter: new Cesium.CircleEmitter(5.0), //BoxEmitter 盒形发射器,ConeEmitter 锥形发射器,SphereEmitter 球形发射器,CircleEmitter圆形发射器
 | 
				
			||||||
 | 
					        emitter: new Cesium.CircleEmitter(2.0), //BoxEmitter 盒形发射器,ConeEmitter 锥形发射器,SphereEmitter 球形发射器,CircleEmitter圆形发射器
 | 
				
			||||||
 | 
					        //回调函数,实现各种喷泉、烟雾效果
 | 
				
			||||||
 | 
					        updateCallback: (p, dt) => {
 | 
				
			||||||
 | 
					          return this.applyGravity(p, dt)
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    this.particleSystem = particleSystem
 | 
					    this.particleSystem = particleSystem
 | 
				
			||||||
    this.preUpdateEvent()
 | 
					    this.preUpdateEvent()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  applyGravity(p, dt) {
 | 
				
			||||||
 | 
					    let gravityScratch = new Cesium.Cartesian3()
 | 
				
			||||||
 | 
					    let position = p.position
 | 
				
			||||||
 | 
					    Cesium.Cartesian3.normalize(position, gravityScratch)
 | 
				
			||||||
 | 
					    Cesium.Cartesian3.fromElements(
 | 
				
			||||||
 | 
					      20 * dt,
 | 
				
			||||||
 | 
					      30 * dt,
 | 
				
			||||||
 | 
					      gravityScratch.y * dt,
 | 
				
			||||||
 | 
					      gravityScratch
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    p.velocity = Cesium.Cartesian3.add(p.velocity, gravityScratch, p.velocity)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //场景渲染事件
 | 
					  //场景渲染事件
 | 
				
			||||||
  preUpdateEvent() {
 | 
					  preUpdateEvent() {
 | 
				
			||||||
    let _this = this
 | 
					    let _this = this
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										101
									
								
								src/utils/pos.js
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								src/utils/pos.js
									
									
									
									
									
								
							@ -32,6 +32,107 @@ export function getPositionFromTime(
 | 
				
			|||||||
  return points
 | 
					  return points
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getOnePositionFromTime(startTime, i, pos) {
 | 
				
			||||||
 | 
					  const time = Cesium.JulianDate.addSeconds(
 | 
				
			||||||
 | 
					    startTime,
 | 
				
			||||||
 | 
					    i,
 | 
				
			||||||
 | 
					    new Cesium.JulianDate()
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					  const point = pos.getValue(time)
 | 
				
			||||||
 | 
					  return point
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getBezierSpline(points) {
 | 
					export function getBezierSpline(points) {
 | 
				
			||||||
  return bezierSpline(lineString(points))
 | 
					  return bezierSpline(lineString(points))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function test() {
 | 
				
			||||||
 | 
					  const points = createTrajectory(
 | 
				
			||||||
 | 
					    [137, 25, 0, 1183135285000],
 | 
				
			||||||
 | 
					    [140, 27, 100000, 1183135295000]
 | 
				
			||||||
 | 
					  ).map(point => {
 | 
				
			||||||
 | 
					    // const point = getTrajectoryPoint(i)
 | 
				
			||||||
 | 
					    console.log(point)
 | 
				
			||||||
 | 
					    // console.log(
 | 
				
			||||||
 | 
					    //   `t=${point.time}s, lon=${point.longitude.toFixed(
 | 
				
			||||||
 | 
					    //     3
 | 
				
			||||||
 | 
					    //   )}, lat=${point.latitude.toFixed(3)}, alt=${point.altitude.toFixed(2)}m`
 | 
				
			||||||
 | 
					    // )
 | 
				
			||||||
 | 
					    return [point.lon, point.lat, point.alt]
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  // const points = a.map(item => {
 | 
				
			||||||
 | 
					  //   return [item.lon, item.lat, item.alt]
 | 
				
			||||||
 | 
					  // })
 | 
				
			||||||
 | 
					  viewer.entities.add({
 | 
				
			||||||
 | 
					    name: 'line',
 | 
				
			||||||
 | 
					    polyline: {
 | 
				
			||||||
 | 
					      positions: Cesium.Cartesian3.fromDegreesArrayHeights(
 | 
				
			||||||
 | 
					        points.flat(Infinity)
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      width: 10,
 | 
				
			||||||
 | 
					      material: new Cesium.PolylineGlowMaterialProperty({
 | 
				
			||||||
 | 
					        glowPower: 0.1,
 | 
				
			||||||
 | 
					        color: Cesium.Color.RED,
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function createTrajectory(p1, p2, options = {}) {
 | 
				
			||||||
 | 
					  const {
 | 
				
			||||||
 | 
					    steps = 20,
 | 
				
			||||||
 | 
					    useStartAsPeak = false,
 | 
				
			||||||
 | 
					    useEndAsPeak = false,
 | 
				
			||||||
 | 
					    peakBias = 0.3, // 控制曲率偏向:0.5 表示中点;靠近 0 表示更靠近起点
 | 
				
			||||||
 | 
					    midOffset = 1000,
 | 
				
			||||||
 | 
					  } = options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [lon1, lat1, alt1, t1] = p1
 | 
				
			||||||
 | 
					  const [lon2, lat2, alt2, t2] = p2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const dt = (t2 - t1) / 1000 // 秒
 | 
				
			||||||
 | 
					  const tPeak =
 | 
				
			||||||
 | 
					    dt * (useEndAsPeak ? 1 - peakBias : useStartAsPeak ? peakBias : 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 设置高度
 | 
				
			||||||
 | 
					  let h0 = alt1
 | 
				
			||||||
 | 
					  let h2 = alt2
 | 
				
			||||||
 | 
					  let h1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (useStartAsPeak) {
 | 
				
			||||||
 | 
					    h1 = (alt1 + alt2) / 2 - midOffset
 | 
				
			||||||
 | 
					  } else if (useEndAsPeak) {
 | 
				
			||||||
 | 
					    h1 = (alt1 + alt2) / 2 - midOffset
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    h1 = Math.max(alt1, alt2) + midOffset
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 三点拟合抛物线
 | 
				
			||||||
 | 
					  const c = h0
 | 
				
			||||||
 | 
					  const A = [
 | 
				
			||||||
 | 
					    [tPeak ** 2, tPeak],
 | 
				
			||||||
 | 
					    [dt ** 2, dt],
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					  const B = [h1 - c, h2 - c]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const denom = A[0][0] * A[1][1] - A[0][1] * A[1][0]
 | 
				
			||||||
 | 
					  const a = (B[0] * A[1][1] - B[1] * A[0][1]) / denom
 | 
				
			||||||
 | 
					  const b = (A[0][0] * B[1] - A[1][0] * B[0]) / denom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const result = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (let i = 0; i <= steps; i++) {
 | 
				
			||||||
 | 
					    const t = (dt * i) / steps
 | 
				
			||||||
 | 
					    const fraction = t / dt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const lon = lon1 + (lon2 - lon1) * fraction
 | 
				
			||||||
 | 
					    const lat = lat1 + (lat2 - lat1) * fraction
 | 
				
			||||||
 | 
					    const alt = a * t * t + b * t + c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result.push({ t: t1 + t * 1000, lon, lat, alt })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 示例:每秒插值
 | 
				
			||||||
 | 
				
			|||||||
@ -9,8 +9,14 @@ const panels = ['手动配置', 'STK轨迹文件配置']
 | 
				
			|||||||
export default defineComponent({
 | 
					export default defineComponent({
 | 
				
			||||||
  setup() {
 | 
					  setup() {
 | 
				
			||||||
    const { daodanData, showOrHideDdConfig } = useDaodan()
 | 
					    const { daodanData, showOrHideDdConfig } = useDaodan()
 | 
				
			||||||
    const { trajData, interceptData, loadStoreData, addIntercept, initDaodan } =
 | 
					    const {
 | 
				
			||||||
      useTestConfig()
 | 
					      trajData,
 | 
				
			||||||
 | 
					      boosterList,
 | 
				
			||||||
 | 
					      interceptData,
 | 
				
			||||||
 | 
					      loadStoreData,
 | 
				
			||||||
 | 
					      addIntercept,
 | 
				
			||||||
 | 
					      initDaodan,
 | 
				
			||||||
 | 
					    } = useTestConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    watch(daodanData, newval => {
 | 
					    watch(daodanData, newval => {
 | 
				
			||||||
      loadStoreData()
 | 
					      loadStoreData()
 | 
				
			||||||
@ -54,8 +60,19 @@ export default defineComponent({
 | 
				
			|||||||
                  <div class="detail-container">
 | 
					                  <div class="detail-container">
 | 
				
			||||||
                    {panel === '手动配置' ? (
 | 
					                    {panel === '手动配置' ? (
 | 
				
			||||||
                      <>
 | 
					                      <>
 | 
				
			||||||
                        <div class="rounded border border-blue-500 p-4">
 | 
					                        <div class="flex flex-col gap-4 rounded border border-blue-500 p-4">
 | 
				
			||||||
                          <TrajTable title="轨迹点" data={trajData.value} />
 | 
					                          <TrajTable
 | 
				
			||||||
 | 
					                            title="轨迹点"
 | 
				
			||||||
 | 
					                            data={trajData.value}
 | 
				
			||||||
 | 
					                            showPosIcon={false}
 | 
				
			||||||
 | 
					                          />
 | 
				
			||||||
 | 
					                          {boosterList.value.map((booster, index) => (
 | 
				
			||||||
 | 
					                            <TrajTable
 | 
				
			||||||
 | 
					                              title={`${['一', '二', '三'][index]}级助推器`}
 | 
				
			||||||
 | 
					                              data={booster}
 | 
				
			||||||
 | 
					                              showPosIcon={false}
 | 
				
			||||||
 | 
					                            />
 | 
				
			||||||
 | 
					                          ))}
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div class="flex flex-col gap-4 rounded border border-red-500 p-4">
 | 
					                        <div class="flex flex-col gap-4 rounded border border-red-500 p-4">
 | 
				
			||||||
                          {interceptData.value.map(data => (
 | 
					                          {interceptData.value.map(data => (
 | 
				
			||||||
@ -63,6 +80,7 @@ export default defineComponent({
 | 
				
			|||||||
                              title="拦截"
 | 
					                              title="拦截"
 | 
				
			||||||
                              data={data}
 | 
					                              data={data}
 | 
				
			||||||
                              onRemoveIntercept={removeIntercept}
 | 
					                              onRemoveIntercept={removeIntercept}
 | 
				
			||||||
 | 
					                              showPosIcon={false}
 | 
				
			||||||
                            />
 | 
					                            />
 | 
				
			||||||
                          ))}
 | 
					                          ))}
 | 
				
			||||||
                          <div>
 | 
					                          <div>
 | 
				
			||||||
@ -75,6 +93,9 @@ export default defineComponent({
 | 
				
			|||||||
                    ) : (
 | 
					                    ) : (
 | 
				
			||||||
                      <>
 | 
					                      <>
 | 
				
			||||||
                        <TrajUpload title="轨迹点" />
 | 
					                        <TrajUpload title="轨迹点" />
 | 
				
			||||||
 | 
					                        <TrajUpload title="一级助推器" />
 | 
				
			||||||
 | 
					                        <TrajUpload title="二级助推器" />
 | 
				
			||||||
 | 
					                        <TrajUpload title="三级助推器" />
 | 
				
			||||||
                        <TrajUpload title="拦截" />
 | 
					                        <TrajUpload title="拦截" />
 | 
				
			||||||
                      </>
 | 
					                      </>
 | 
				
			||||||
                    )}
 | 
					                    )}
 | 
				
			||||||
 | 
				
			|||||||
@ -38,7 +38,7 @@ export default defineComponent({
 | 
				
			|||||||
        render(row) {
 | 
					        render(row) {
 | 
				
			||||||
          return (
 | 
					          return (
 | 
				
			||||||
            <div class="flex items-center justify-between gap-2">
 | 
					            <div class="flex items-center justify-between gap-2">
 | 
				
			||||||
              <div>{row.name} </div>
 | 
					              <div>{row.name}</div>
 | 
				
			||||||
              {props.showPosIcon && (
 | 
					              {props.showPosIcon && (
 | 
				
			||||||
                <NButton
 | 
					                <NButton
 | 
				
			||||||
                  // quaternary
 | 
					                  // quaternary
 | 
				
			||||||
@ -75,7 +75,7 @@ export default defineComponent({
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        title: '经度',
 | 
					        title: getTitle('lon'),
 | 
				
			||||||
        key: 'lon',
 | 
					        key: 'lon',
 | 
				
			||||||
        render(row) {
 | 
					        render(row) {
 | 
				
			||||||
          return (
 | 
					          return (
 | 
				
			||||||
@ -88,7 +88,7 @@ export default defineComponent({
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        title: '纬度',
 | 
					        title: getTitle('lat'),
 | 
				
			||||||
        key: 'lat',
 | 
					        key: 'lat',
 | 
				
			||||||
        render(row) {
 | 
					        render(row) {
 | 
				
			||||||
          return (
 | 
					          return (
 | 
				
			||||||
@ -109,7 +109,7 @@ export default defineComponent({
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        title: '时间',
 | 
					        title: getTitle('time'),
 | 
				
			||||||
        key: 'time',
 | 
					        key: 'time',
 | 
				
			||||||
        render(row) {
 | 
					        render(row) {
 | 
				
			||||||
          return (
 | 
					          return (
 | 
				
			||||||
@ -117,52 +117,27 @@ export default defineComponent({
 | 
				
			|||||||
          )
 | 
					          )
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        title: '助推器脱落',
 | 
					 | 
				
			||||||
        key: 'detached',
 | 
					 | 
				
			||||||
        render(row, rowIndex) {
 | 
					 | 
				
			||||||
          return rowIndex !== 0 && rowIndex < trajData.value.length - 1 ? (
 | 
					 | 
				
			||||||
            <NSwitch v-model:value={row.detached} type="datetime"></NSwitch>
 | 
					 | 
				
			||||||
          ) : (
 | 
					 | 
				
			||||||
            '-'
 | 
					 | 
				
			||||||
          )
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        title: '操作',
 | 
					 | 
				
			||||||
        render(row, rowIndex) {
 | 
					 | 
				
			||||||
          return rowIndex !== 0 && rowIndex < trajData.value.length - 1 ? (
 | 
					 | 
				
			||||||
            <NButton
 | 
					 | 
				
			||||||
              type="error"
 | 
					 | 
				
			||||||
              text
 | 
					 | 
				
			||||||
              v-slots={{
 | 
					 | 
				
			||||||
                icon: () => (
 | 
					 | 
				
			||||||
                  <NIcon>
 | 
					 | 
				
			||||||
                    <TrashOutline />
 | 
					 | 
				
			||||||
                  </NIcon>
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              }}
 | 
					 | 
				
			||||||
              onClick={() => {
 | 
					 | 
				
			||||||
                trajData.value.splice(rowIndex, 1)
 | 
					 | 
				
			||||||
              }}
 | 
					 | 
				
			||||||
            ></NButton>
 | 
					 | 
				
			||||||
          ) : (
 | 
					 | 
				
			||||||
            '-'
 | 
					 | 
				
			||||||
          )
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const addFeaturePoint = () => {
 | 
					    function getTitle(key) {
 | 
				
			||||||
      trajData.value.splice(trajData.value.length - 1, 0, {
 | 
					      const isIntercept = props.title.indexOf('拦截') > -1
 | 
				
			||||||
        name: '中间特征点',
 | 
					      const isBooster = props.title.indexOf('助推器') > -1
 | 
				
			||||||
        lon: 0,
 | 
					
 | 
				
			||||||
        lat: 0,
 | 
					      const dict = {
 | 
				
			||||||
        alt: 0,
 | 
					        time: isIntercept ? '命中时间' : isBooster ? '脱离时间' : '时间',
 | 
				
			||||||
        time: Date.now(),
 | 
					        lat: isIntercept ? '发射纬度' : isBooster ? '落点纬度' : '纬度',
 | 
				
			||||||
        detached: false,
 | 
					        lon: isIntercept ? '发射经度' : isBooster ? '落点经度' : '经度',
 | 
				
			||||||
      })
 | 
					        alt: '高度',
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return dict[key] || key
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (props.title.indexOf('助推器') > -1) {
 | 
				
			||||||
 | 
					      columns.splice(3, 1)
 | 
				
			||||||
 | 
					    } else if (props.title.indexOf('拦截') > -1) {
 | 
				
			||||||
 | 
					      columns.splice(3, 1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const dialog = useDialog()
 | 
					    const dialog = useDialog()
 | 
				
			||||||
    const remove = () => {
 | 
					    const remove = () => {
 | 
				
			||||||
      dialog.warning({
 | 
					      dialog.warning({
 | 
				
			||||||
@ -180,9 +155,6 @@ export default defineComponent({
 | 
				
			|||||||
        <div class="flex justify-between">
 | 
					        <div class="flex justify-between">
 | 
				
			||||||
          <div class="detail-item-title">{props.title}</div>
 | 
					          <div class="detail-item-title">{props.title}</div>
 | 
				
			||||||
          <div>
 | 
					          <div>
 | 
				
			||||||
            <NButton quaternary type="primary" onClick={addFeaturePoint}>
 | 
					 | 
				
			||||||
              添加特征点
 | 
					 | 
				
			||||||
            </NButton>
 | 
					 | 
				
			||||||
            {props.title.indexOf('拦截') > -1 && (
 | 
					            {props.title.indexOf('拦截') > -1 && (
 | 
				
			||||||
              <NButton quaternary type="error" onClick={remove}>
 | 
					              <NButton quaternary type="error" onClick={remove}>
 | 
				
			||||||
                删除拦截
 | 
					                删除拦截
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,20 @@
 | 
				
			|||||||
import { ref, toRaw } from 'vue'
 | 
					import { ref, toRaw } from 'vue'
 | 
				
			||||||
import { useDaodan } from '../../ddHooks'
 | 
					import { useDaodan } from '../../ddHooks'
 | 
				
			||||||
import { cartesian32LonLat, getPositionFromTime } from '@/utils/pos'
 | 
					import {
 | 
				
			||||||
 | 
					  cartesian32LonLat,
 | 
				
			||||||
 | 
					  getPositionFromTime,
 | 
				
			||||||
 | 
					  getOnePositionFromTime,
 | 
				
			||||||
 | 
					  test,
 | 
				
			||||||
 | 
					  createTrajectory,
 | 
				
			||||||
 | 
					} from '@/utils/pos'
 | 
				
			||||||
import ExplosionEffect from '@/js/Explosion'
 | 
					import ExplosionEffect from '@/js/Explosion'
 | 
				
			||||||
import { generateId } from '@/utils/id'
 | 
					import { generateId } from '@/utils/id'
 | 
				
			||||||
import store from 'store2'
 | 
					import store from 'store2'
 | 
				
			||||||
// import { getPositionFromTime } from '@/utils/pos'
 | 
					import { lineString, bezierSpline } from '@turf/turf'
 | 
				
			||||||
// import { useDaodan } from '../../ddHooks'
 | 
					// import { useDaodan } from '../../ddHooks'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ddScale = 30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const trajData = ref({
 | 
					const trajData = ref({
 | 
				
			||||||
  id: 'dd',
 | 
					  id: 'dd',
 | 
				
			||||||
  data: [
 | 
					  data: [
 | 
				
			||||||
@ -18,63 +26,69 @@ const trajData = ref({
 | 
				
			|||||||
      time: 1183135260000,
 | 
					      time: 1183135260000,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      name: '中间特征点',
 | 
					      name: '最高点',
 | 
				
			||||||
      lon: 122,
 | 
					      lon: 125,
 | 
				
			||||||
      lat: 21,
 | 
					      lat: 25,
 | 
				
			||||||
      alt: 1000000,
 | 
					 | 
				
			||||||
      time: 1183135265000,
 | 
					 | 
				
			||||||
      detached: true,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: '中间特征点',
 | 
					 | 
				
			||||||
      lon: 124,
 | 
					 | 
				
			||||||
      lat: 21,
 | 
					 | 
				
			||||||
      alt: 1500000,
 | 
					 | 
				
			||||||
      time: 1183135270000,
 | 
					 | 
				
			||||||
      detached: true,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: '中间特征点',
 | 
					 | 
				
			||||||
      lon: 128,
 | 
					 | 
				
			||||||
      lat: 21,
 | 
					 | 
				
			||||||
      alt: 2000000,
 | 
					      alt: 2000000,
 | 
				
			||||||
      time: 1183135280000,
 | 
					      time: 1183135280000,
 | 
				
			||||||
      detached: true,
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      name: '落点',
 | 
					      name: '落点',
 | 
				
			||||||
      lon: 135,
 | 
					      lon: 160,
 | 
				
			||||||
      lat: 21,
 | 
					      lat: 40,
 | 
				
			||||||
      alt: 1500000,
 | 
					      alt: 0,
 | 
				
			||||||
      time: 1183135290000,
 | 
					      time: 1183135300000,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
const interceptData = ref([
 | 
					const boosterList = ref([
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    id: 'dd1',
 | 
					    id: 'booster-1',
 | 
				
			||||||
    data: [
 | 
					    data: [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        name: '起始点',
 | 
					        // name: '落点',
 | 
				
			||||||
        lon: 137,
 | 
					        lon: 130,
 | 
				
			||||||
        lat: 25,
 | 
					        lat: 23,
 | 
				
			||||||
 | 
					        alt: 0,
 | 
				
			||||||
 | 
					        time: 1183135265000,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: 'booster-2',
 | 
				
			||||||
 | 
					    data: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        // name: '落点',
 | 
				
			||||||
 | 
					        lon: 135,
 | 
				
			||||||
 | 
					        lat: 28,
 | 
				
			||||||
        alt: 0,
 | 
					        alt: 0,
 | 
				
			||||||
        time: 1183135270000,
 | 
					        time: 1183135270000,
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: 'booster-3',
 | 
				
			||||||
 | 
					    data: [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        name: '中间特征点',
 | 
					        // name: '落点',
 | 
				
			||||||
        lon: 138,
 | 
					        lon: 140,
 | 
				
			||||||
        lat: 24,
 | 
					        lat: 35,
 | 
				
			||||||
        alt: 1000000,
 | 
					        alt: 0,
 | 
				
			||||||
        time: 1183135280000,
 | 
					        time: 1183135275000,
 | 
				
			||||||
        detached: true,
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					const interceptData = ref([
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: 'intercept-1',
 | 
				
			||||||
 | 
					    data: [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        name: '落点',
 | 
					        // name: '起始点',
 | 
				
			||||||
        lon: 135,
 | 
					        lon: 137,
 | 
				
			||||||
        lat: 21,
 | 
					        lat: 25,
 | 
				
			||||||
        alt: 1500000,
 | 
					        alt: 0,
 | 
				
			||||||
        time: 1183135290000,
 | 
					        time: 1183135285000,
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
@ -85,6 +99,7 @@ const { daodanData, showDdConfigCom } = useDaodan()
 | 
				
			|||||||
export function useTestConfig() {
 | 
					export function useTestConfig() {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    trajData,
 | 
					    trajData,
 | 
				
			||||||
 | 
					    boosterList,
 | 
				
			||||||
    interceptData,
 | 
					    interceptData,
 | 
				
			||||||
    loadStoreData,
 | 
					    loadStoreData,
 | 
				
			||||||
    addIntercept,
 | 
					    addIntercept,
 | 
				
			||||||
@ -94,13 +109,16 @@ export function useTestConfig() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function saveDataToStore() {
 | 
					function saveDataToStore() {
 | 
				
			||||||
 | 
					  // test()
 | 
				
			||||||
  const daodanDataRaw = toRaw(daodanData.value)
 | 
					  const daodanDataRaw = toRaw(daodanData.value)
 | 
				
			||||||
  const storeData = store.get('daodanData')
 | 
					  const storeData = store.get('daodanData')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  store.set('daodanData', {
 | 
					  store.set('daodanData', {
 | 
				
			||||||
    ...storeData,
 | 
					    ...storeData,
 | 
				
			||||||
    [daodanDataRaw.id]: {
 | 
					    [daodanDataRaw.id]: {
 | 
				
			||||||
      ...daodanDataRaw,
 | 
					      ...daodanDataRaw,
 | 
				
			||||||
      trajData: trajData.value,
 | 
					      trajData: trajData.value,
 | 
				
			||||||
 | 
					      boosterList: boosterList.value,
 | 
				
			||||||
      interceptData: interceptData.value,
 | 
					      interceptData: interceptData.value,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -174,20 +192,23 @@ function addDaodan(trajData, type = 0) {
 | 
				
			|||||||
    ddTrajData[0].alt
 | 
					    ddTrajData[0].alt
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  const hpRoll = new Cesium.HeadingPitchRoll()
 | 
					  const hpRoll = new Cesium.HeadingPitchRoll()
 | 
				
			||||||
 | 
					  // const fixedFrameTransform = Cesium.Transforms.eastNorthUpToFixedFrame
 | 
				
			||||||
  const fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator(
 | 
					  const fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator(
 | 
				
			||||||
    'north',
 | 
					    'north',
 | 
				
			||||||
    'west'
 | 
					    'west'
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  hpRoll.pitch = (90 * Math.PI) / 180
 | 
					  // hpRoll.pitch = (90 * Math.PI) / 180
 | 
				
			||||||
  const modelObj = Cesium.Model.fromGltf({
 | 
					  const modelObj = Cesium.Model.fromGltf({
 | 
				
			||||||
    url: './models/launchvehicle.glb',
 | 
					    // url: './models/launchvehicle.glb',
 | 
				
			||||||
 | 
					    url: './models/美三叉戟2动画.glb',
 | 
				
			||||||
    modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(
 | 
					    modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(
 | 
				
			||||||
      position,
 | 
					      position,
 | 
				
			||||||
      hpRoll,
 | 
					      hpRoll,
 | 
				
			||||||
      Cesium.Ellipsoid.WGS84,
 | 
					      Cesium.Ellipsoid.WGS84,
 | 
				
			||||||
      fixedFrameTransform
 | 
					      fixedFrameTransform
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    minimumPixelSize: 70,
 | 
					    scale: ddScale,
 | 
				
			||||||
 | 
					    minimumPixelSize: ddScale,
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const ddPrimitive = viewer.scene.primitives.add(modelObj)
 | 
					  const ddPrimitive = viewer.scene.primitives.add(modelObj)
 | 
				
			||||||
@ -210,17 +231,16 @@ function addDaodan(trajData, type = 0) {
 | 
				
			|||||||
  // })
 | 
					  // })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ddPrimitive.readyPromise.then(model => {
 | 
					  ddPrimitive.readyPromise.then(model => {
 | 
				
			||||||
 | 
					    console.log('model', model)
 | 
				
			||||||
    nodes = model.pickIds.map(item => item.object.detail.node)
 | 
					    nodes = model.pickIds.map(item => item.object.detail.node)
 | 
				
			||||||
    nodes.forEach(i => {
 | 
					    console.log('nodes', nodes)
 | 
				
			||||||
      // console.log(i._name, model.getNode(i._name))
 | 
					    // nodes.forEach(i => {
 | 
				
			||||||
      if (new RegExp(/SRB\d/).test(i._name)) {
 | 
					    //   // console.log(i._name, model.getNode(i._name))
 | 
				
			||||||
        model.getNode(i._name).show = false
 | 
					    //   if (new RegExp(/SRB\d/).test(i._name)) {
 | 
				
			||||||
      }
 | 
					    //     model.getNode(i._name).show = false
 | 
				
			||||||
    })
 | 
					    //   }
 | 
				
			||||||
 | 
					    // })
 | 
				
			||||||
    computePath(ddPrimitive, trajData, type)
 | 
					    computePath(ddPrimitive, trajData, type)
 | 
				
			||||||
    // setTimeout(() => {
 | 
					 | 
				
			||||||
    // playDaodan(ddPrimitive, nodes)
 | 
					 | 
				
			||||||
    // }, 3000)
 | 
					 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -229,16 +249,16 @@ function initDaodan() {
 | 
				
			|||||||
  saveDataToStore()
 | 
					  saveDataToStore()
 | 
				
			||||||
  minTime = getMinTime([
 | 
					  minTime = getMinTime([
 | 
				
			||||||
    ...toRaw(trajData.value.data),
 | 
					    ...toRaw(trajData.value.data),
 | 
				
			||||||
    ...toRaw(interceptData.value.map(item => toRaw(item.data))).flat(Infinity),
 | 
					    // ...toRaw(interceptData.value.map(item => toRaw(item.data))).flat(Infinity),
 | 
				
			||||||
  ])
 | 
					  ])
 | 
				
			||||||
  // console.log(minTime)
 | 
					  // console.log(minTime)
 | 
				
			||||||
  addDaodan(trajData.value)
 | 
					  addDaodan(trajData.value)
 | 
				
			||||||
  aniIndexMap.set(trajData.value.id, 0)
 | 
					  aniIndexMap.set(trajData.value.id, 0)
 | 
				
			||||||
  interceptData.value.forEach(item => {
 | 
					  // interceptData.value.forEach(item => {
 | 
				
			||||||
    const { id, data } = item
 | 
					  //   const { id, data } = item
 | 
				
			||||||
    addDaodan(item, 1)
 | 
					  //   addDaodan(item, 1)
 | 
				
			||||||
    aniIndexMap.set(id, 0)
 | 
					  //   aniIndexMap.set(id, 0)
 | 
				
			||||||
  })
 | 
					  // })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getMinTime(data) {
 | 
					function getMinTime(data) {
 | 
				
			||||||
@ -249,14 +269,16 @@ function getMinTime(data) {
 | 
				
			|||||||
  return minTime
 | 
					  return minTime
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const pathLine = new Map()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function computePath(daodan, trajData, type) {
 | 
					function computePath(daodan, trajData, type) {
 | 
				
			||||||
  const { data: ddTrajData } = trajData
 | 
					  const { id, data: ddTrajData } = trajData
 | 
				
			||||||
  const points = ddTrajData.map(item => {
 | 
					  const points = ddTrajData.map(item => {
 | 
				
			||||||
    const { time, lon, lat, alt, detached } = item
 | 
					    const { time, lon, lat, alt } = item
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      position: Cesium.Cartesian3.fromDegrees(lon, lat, alt),
 | 
					      position: Cesium.Cartesian3.fromDegrees(lon, lat, alt),
 | 
				
			||||||
      time: time - minTime,
 | 
					      time: time - minTime,
 | 
				
			||||||
      detached,
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  const totalAnimationTime = points.at(-1).time
 | 
					  const totalAnimationTime = points.at(-1).time
 | 
				
			||||||
@ -270,13 +292,13 @@ function computePath(daodan, trajData, type) {
 | 
				
			|||||||
      point.time / 1000,
 | 
					      point.time / 1000,
 | 
				
			||||||
      new Cesium.JulianDate()
 | 
					      new Cesium.JulianDate()
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    viewer.entities.add({
 | 
					    // const point = viewer.entities.add({
 | 
				
			||||||
      position: point.position,
 | 
					    //   position: point.position,
 | 
				
			||||||
      point: {
 | 
					    //   point: {
 | 
				
			||||||
        color: Cesium.Color.WHITE,
 | 
					    //     color: Cesium.Color.WHITE,
 | 
				
			||||||
        pixelSize: 5,
 | 
					    //     pixelSize: 5,
 | 
				
			||||||
      },
 | 
					    //   },
 | 
				
			||||||
    })
 | 
					    // })
 | 
				
			||||||
    positionProperty.addSample(time, point.position)
 | 
					    positionProperty.addSample(time, point.position)
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  positionProperty.setInterpolationOptions({
 | 
					  positionProperty.setInterpolationOptions({
 | 
				
			||||||
@ -285,7 +307,28 @@ function computePath(daodan, trajData, type) {
 | 
				
			|||||||
    // interpolationDegree: 5,
 | 
					    // interpolationDegree: 5,
 | 
				
			||||||
    // interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
 | 
					    // interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  createLine({ totalAnimationTime, startTime, positionProperty, type })
 | 
					  const line = createLine({
 | 
				
			||||||
 | 
					    totalAnimationTime,
 | 
				
			||||||
 | 
					    startTime,
 | 
				
			||||||
 | 
					    positionProperty,
 | 
				
			||||||
 | 
					    type,
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pathLine.set(id, line)
 | 
				
			||||||
 | 
					  if (type === 0) {
 | 
				
			||||||
 | 
					    computeBoosterOrInterceptPath({
 | 
				
			||||||
 | 
					      dataList: boosterList.value,
 | 
				
			||||||
 | 
					      startTime,
 | 
				
			||||||
 | 
					      positionProperty,
 | 
				
			||||||
 | 
					      type: 'booster',
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    computeBoosterOrInterceptPath({
 | 
				
			||||||
 | 
					      dataList: interceptData.value,
 | 
				
			||||||
 | 
					      startTime,
 | 
				
			||||||
 | 
					      positionProperty,
 | 
				
			||||||
 | 
					      type: 'intercept',
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  daodanAnimation({
 | 
					  daodanAnimation({
 | 
				
			||||||
    totalAnimationTime,
 | 
					    totalAnimationTime,
 | 
				
			||||||
    startTime,
 | 
					    startTime,
 | 
				
			||||||
@ -295,11 +338,140 @@ function computePath(daodan, trajData, type) {
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const boosterMap = new Map()
 | 
				
			||||||
 | 
					const interceptMap = new Map()
 | 
				
			||||||
 | 
					const interceptTime = ref()
 | 
				
			||||||
 | 
					function computeBoosterOrInterceptPath({
 | 
				
			||||||
 | 
					  dataList,
 | 
				
			||||||
 | 
					  startTime,
 | 
				
			||||||
 | 
					  positionProperty,
 | 
				
			||||||
 | 
					  type,
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					  dataList.forEach((dataItem, index) => {
 | 
				
			||||||
 | 
					    const { id, data } = dataItem
 | 
				
			||||||
 | 
					    let points = []
 | 
				
			||||||
 | 
					    data.forEach(item => {
 | 
				
			||||||
 | 
					      const { time, lon, lat, alt } = item
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const position = getOnePositionFromTime(
 | 
				
			||||||
 | 
					        startTime,
 | 
				
			||||||
 | 
					        (time - minTime) / 1000,
 | 
				
			||||||
 | 
					        positionProperty
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // points.push({
 | 
				
			||||||
 | 
					      //   position,
 | 
				
			||||||
 | 
					      //   time: time - minTime,
 | 
				
			||||||
 | 
					      // })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const lonlat = cartesian32LonLat(position)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const pointTime = time - minTime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const aniPointTime = pointTime + (type === 'booster' ? 10000 : -10000)
 | 
				
			||||||
 | 
					      type === 'intercept' && (interceptTime.value = pointTime / 1000)
 | 
				
			||||||
 | 
					      const pointInline = {
 | 
				
			||||||
 | 
					        position: Cesium.Cartesian3.fromDegrees(lon, lat, alt),
 | 
				
			||||||
 | 
					        time: aniPointTime,
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      // points.push(pointInline)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      points = createTrajectory(
 | 
				
			||||||
 | 
					        [lon, lat, alt, aniPointTime],
 | 
				
			||||||
 | 
					        [...lonlat, time - minTime],
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          useEndAsPeak: true,
 | 
				
			||||||
 | 
					          peakBias: 0.65,
 | 
				
			||||||
 | 
					          midOffset: 1000,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ).map(item => {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          position: Cesium.Cartesian3.fromDegrees(item.lon, item.lat, item.alt),
 | 
				
			||||||
 | 
					          time: item.t,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dataPositionProperty = new Cesium.SampledPositionProperty()
 | 
				
			||||||
 | 
					    points.forEach(point => {
 | 
				
			||||||
 | 
					      const time = Cesium.JulianDate.addSeconds(
 | 
				
			||||||
 | 
					        startTime,
 | 
				
			||||||
 | 
					        point.time / 1000,
 | 
				
			||||||
 | 
					        new Cesium.JulianDate()
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // viewer.entities.add({
 | 
				
			||||||
 | 
					      //   position: point.position,
 | 
				
			||||||
 | 
					      //   point: {
 | 
				
			||||||
 | 
					      //     color: Cesium.Color.ORANGE,
 | 
				
			||||||
 | 
					      //     pixelSize: 5,
 | 
				
			||||||
 | 
					      //   },
 | 
				
			||||||
 | 
					      // })
 | 
				
			||||||
 | 
					      dataPositionProperty.addSample(time, point.position)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    dataPositionProperty.setInterpolationOptions({
 | 
				
			||||||
 | 
					      interpolationDegree: 2,
 | 
				
			||||||
 | 
					      interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dataLine = createLine({
 | 
				
			||||||
 | 
					      totalAnimationTime: points.at(-1).time,
 | 
				
			||||||
 | 
					      startTime,
 | 
				
			||||||
 | 
					      positionProperty: dataPositionProperty,
 | 
				
			||||||
 | 
					      type: 2,
 | 
				
			||||||
 | 
					      color: type === 'booster' ? 'ORANGE' : 'RED',
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const modelUrl =
 | 
				
			||||||
 | 
					      type === 'booster'
 | 
				
			||||||
 | 
					        ? `./models/美三叉戟2第${['一', '二', '三'][index]}级.glb`
 | 
				
			||||||
 | 
					        : './models/美三叉戟2动画.glb'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dataLine.model = {
 | 
				
			||||||
 | 
					      show: true,
 | 
				
			||||||
 | 
					      uri: modelUrl,
 | 
				
			||||||
 | 
					      runAnimations: false,
 | 
				
			||||||
 | 
					      // uri: `./models/第${['一', '二', '三'][index]}级.glb`,
 | 
				
			||||||
 | 
					      scale: type === 'booster' ? ddScale / 4 : ddScale,
 | 
				
			||||||
 | 
					      minimumPixelSize: type === 'booster' ? ddScale / 4 : ddScale,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    dataLine.orientation = new Cesium.VelocityOrientationProperty(
 | 
				
			||||||
 | 
					      dataPositionProperty
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type === 'booster'
 | 
				
			||||||
 | 
					      ? boosterMap.set(id, dataLine)
 | 
				
			||||||
 | 
					      : interceptMap.set(id, dataLine)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function daodanAnimation(params) {
 | 
					function daodanAnimation(params) {
 | 
				
			||||||
  const { totalAnimationTime, startTime, positionProperty, daodan, trajData } =
 | 
					  const { totalAnimationTime, startTime, positionProperty, daodan, trajData } =
 | 
				
			||||||
    params
 | 
					    params
 | 
				
			||||||
  // const { data: ddTrajData } = trajData
 | 
					  // const { data: ddTrajData } = trajData
 | 
				
			||||||
  dianhuo(daodan)
 | 
					  // dianhuo(daodan)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // setTimeout(() => {
 | 
				
			||||||
 | 
					  //   modelAnimationController({
 | 
				
			||||||
 | 
					  //     primitive: daodan,
 | 
				
			||||||
 | 
					  //     type: '第一级发动机 MoveZ',
 | 
				
			||||||
 | 
					  //     initVal: 0,
 | 
				
			||||||
 | 
					  //     minVal: -450,
 | 
				
			||||||
 | 
					  //     step: -3,
 | 
				
			||||||
 | 
					  //     fn: () => {
 | 
				
			||||||
 | 
					  //       console.log(
 | 
				
			||||||
 | 
					  //         `一级脱离`,
 | 
				
			||||||
 | 
					  //         'color: red;font-size: 20px;border: 1px solid red'
 | 
				
			||||||
 | 
					  //       )
 | 
				
			||||||
 | 
					  //       nodes.forEach(i => {
 | 
				
			||||||
 | 
					  //         const nodeName = i._name
 | 
				
			||||||
 | 
					  //         if (new RegExp(/第一级发动机/).test(nodeName)) {
 | 
				
			||||||
 | 
					  //           daodan.getNode(nodeName).show = false
 | 
				
			||||||
 | 
					  //         }
 | 
				
			||||||
 | 
					  //       })
 | 
				
			||||||
 | 
					  //     },
 | 
				
			||||||
 | 
					  //   })
 | 
				
			||||||
 | 
					  // }, 3000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let lastFrameTime = performance.now()
 | 
					  let lastFrameTime = performance.now()
 | 
				
			||||||
  let customElapsedTime = 0
 | 
					  let customElapsedTime = 0
 | 
				
			||||||
@ -317,12 +489,17 @@ function daodanAnimation(params) {
 | 
				
			|||||||
    if (customElapsedTime >= totalAnimationTime) {
 | 
					    if (customElapsedTime >= totalAnimationTime) {
 | 
				
			||||||
      customElapsedTime = totalAnimationTime // 限制时间为总时长
 | 
					      customElapsedTime = totalAnimationTime // 限制时间为总时长
 | 
				
			||||||
      isAnimationRunning = false // 停止动画
 | 
					      isAnimationRunning = false // 停止动画
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setTimeout(() => {
 | 
				
			||||||
 | 
					        removeAllEntity()
 | 
				
			||||||
 | 
					      }, 6000)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ddNodesAnimationController({
 | 
					
 | 
				
			||||||
      ddPrimitive: daodan,
 | 
					    // ddNodesAnimationController({
 | 
				
			||||||
      curTime: minTime + customElapsedTime * 1000,
 | 
					    //   ddPrimitive: daodan,
 | 
				
			||||||
      trajData,
 | 
					    //   curTime: minTime + customElapsedTime * 1000,
 | 
				
			||||||
    })
 | 
					    //   trajData,
 | 
				
			||||||
 | 
					    // })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 计算自定义时间下的位置
 | 
					    // 计算自定义时间下的位置
 | 
				
			||||||
    const customTime = Cesium.JulianDate.addSeconds(
 | 
					    const customTime = Cesium.JulianDate.addSeconds(
 | 
				
			||||||
@ -340,17 +517,28 @@ function daodanAnimation(params) {
 | 
				
			|||||||
        new Cesium.JulianDate()
 | 
					        new Cesium.JulianDate()
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    if (position && !nextPosition && !explosion) {
 | 
					
 | 
				
			||||||
      const [lon, lat, height] = cartesian32LonLat(position)
 | 
					    if (interceptTime.value && customElapsedTime >= interceptTime.value) {
 | 
				
			||||||
      explosion = new ExplosionEffect(viewer, {
 | 
					      customElapsedTime = totalAnimationTime
 | 
				
			||||||
        lng: lon,
 | 
					      isAnimationRunning = false
 | 
				
			||||||
        lat: lat,
 | 
					      explosion = explosionEffect(position)
 | 
				
			||||||
        height,
 | 
					
 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      setTimeout(() => {
 | 
					      setTimeout(() => {
 | 
				
			||||||
        explosion && explosion.remove()
 | 
					        removeAllEntity()
 | 
				
			||||||
      }, 6000)
 | 
					      }, 6000)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (position && !nextPosition && !explosion) {
 | 
				
			||||||
 | 
					      // const [lon, lat, height] = cartesian32LonLat(position)
 | 
				
			||||||
 | 
					      // explosion = new ExplosionEffect(viewer, {
 | 
				
			||||||
 | 
					      //   lng: lon,
 | 
				
			||||||
 | 
					      //   lat: lat,
 | 
				
			||||||
 | 
					      //   height,
 | 
				
			||||||
 | 
					      // })
 | 
				
			||||||
 | 
					      // setTimeout(() => {
 | 
				
			||||||
 | 
					      //   explosion && explosion.remove()
 | 
				
			||||||
 | 
					      // }, 6000)
 | 
				
			||||||
 | 
					      explosion = explosionEffect(position)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (position && nextPosition) {
 | 
					    if (position && nextPosition) {
 | 
				
			||||||
      const fixedFrameTransform =
 | 
					      const fixedFrameTransform =
 | 
				
			||||||
        Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west')
 | 
					        Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west')
 | 
				
			||||||
@ -363,16 +551,22 @@ function daodanAnimation(params) {
 | 
				
			|||||||
        fixedFrameTransform,
 | 
					        fixedFrameTransform,
 | 
				
			||||||
        daodan.modelMatrix
 | 
					        daodan.modelMatrix
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Cesium.Matrix4.fromTranslationQuaternionRotationScale(
 | 
					 | 
				
			||||||
      //   position,
 | 
					 | 
				
			||||||
      //   orientation,
 | 
					 | 
				
			||||||
      //   new Cesium.Cartesian3(1.0, 1.0, 1.0), // 缩放比例,
 | 
					 | 
				
			||||||
      //   daodan.modelMatrix
 | 
					 | 
				
			||||||
      // )
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function explosionEffect(position) {
 | 
				
			||||||
 | 
					  const [lon, lat, height] = cartesian32LonLat(position)
 | 
				
			||||||
 | 
					  const explosion = new ExplosionEffect(viewer, {
 | 
				
			||||||
 | 
					    lng: lon,
 | 
				
			||||||
 | 
					    lat: lat,
 | 
				
			||||||
 | 
					    height,
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  setTimeout(() => {
 | 
				
			||||||
 | 
					    explosion && explosion.remove()
 | 
				
			||||||
 | 
					  }, 6000)
 | 
				
			||||||
 | 
					  return explosion
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
function dianhuo(ddPrimitive) {
 | 
					function dianhuo(ddPrimitive) {
 | 
				
			||||||
  modelAnimationController({
 | 
					  modelAnimationController({
 | 
				
			||||||
    primitive: ddPrimitive,
 | 
					    primitive: ddPrimitive,
 | 
				
			||||||
@ -392,14 +586,6 @@ function ddNodesAnimationController(params) {
 | 
				
			|||||||
  const { id: ddId, data: ddTrajData } = trajData
 | 
					  const { id: ddId, data: ddTrajData } = trajData
 | 
				
			||||||
  const nodeAniList = ddTrajData.filter(item => item.detached)
 | 
					  const nodeAniList = ddTrajData.filter(item => item.detached)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // console.log(
 | 
					 | 
				
			||||||
  //   curTime,
 | 
					 | 
				
			||||||
  //   aniIndex,
 | 
					 | 
				
			||||||
  //   nodeAniList[aniIndex].time,
 | 
					 | 
				
			||||||
  //   curTime >= nodeAniList[aniIndex].time,
 | 
					 | 
				
			||||||
  //   'curTime'
 | 
					 | 
				
			||||||
  // )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!ddPrimitive || !aniIndexMap.has(ddId)) return
 | 
					  if (!ddPrimitive || !aniIndexMap.has(ddId)) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const aniIndex = aniIndexMap.get(ddId)
 | 
					  const aniIndex = aniIndexMap.get(ddId)
 | 
				
			||||||
@ -595,38 +781,36 @@ function getHeadingPitchRoll(curPos, nextPos) {
 | 
				
			|||||||
  return hpr
 | 
					  return hpr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function createLine({ totalAnimationTime, startTime, positionProperty, type }) {
 | 
					function createLine({
 | 
				
			||||||
 | 
					  totalAnimationTime,
 | 
				
			||||||
 | 
					  startTime,
 | 
				
			||||||
 | 
					  positionProperty,
 | 
				
			||||||
 | 
					  type,
 | 
				
			||||||
 | 
					  color,
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
  const positionList = getPositionFromTime(
 | 
					  const positionList = getPositionFromTime(
 | 
				
			||||||
    startTime,
 | 
					    startTime,
 | 
				
			||||||
    positionProperty,
 | 
					    positionProperty,
 | 
				
			||||||
    totalAnimationTime
 | 
					    totalAnimationTime
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  viewer.entities.add({
 | 
					  // if (type === 2) {
 | 
				
			||||||
 | 
					  //   console.log('positionList', positionList)
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return viewer.entities.add({
 | 
				
			||||||
    position: positionProperty,
 | 
					    position: positionProperty,
 | 
				
			||||||
    polyline: {
 | 
					    polyline: {
 | 
				
			||||||
      positions: positionList,
 | 
					      positions: positionList,
 | 
				
			||||||
      width: 2,
 | 
					      width: 8,
 | 
				
			||||||
      material: type
 | 
					      material: new Cesium.PolylineGlowMaterialProperty({
 | 
				
			||||||
        ? Cesium.Color.RED.withAlpha(0.5)
 | 
					        glowPower: 0.1,
 | 
				
			||||||
        : Cesium.Color.BLUE.withAlpha(0.5),
 | 
					        color: type
 | 
				
			||||||
 | 
					          ? type === 2 && Cesium.Color[color].withAlpha(0.5)
 | 
				
			||||||
 | 
					          : Cesium.Color.BLUE.withAlpha(0.5),
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
// function getPositionFromTime(startTime, pos, totalAnimationTime) {
 | 
					 | 
				
			||||||
//   const points = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//   for (let i = 0; i <= totalAnimationTime / 100; i++) {
 | 
					 | 
				
			||||||
//     const time = Cesium.JulianDate.addSeconds(
 | 
					 | 
				
			||||||
//       startTime,
 | 
					 | 
				
			||||||
//       i,
 | 
					 | 
				
			||||||
//       new Cesium.JulianDate()
 | 
					 | 
				
			||||||
//     )
 | 
					 | 
				
			||||||
//     const point = pos.getValue(time)
 | 
					 | 
				
			||||||
//     point && points.push(point)
 | 
					 | 
				
			||||||
//   }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//   return points
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
function modelAnimationController(controller) {
 | 
					function modelAnimationController(controller) {
 | 
				
			||||||
  const { type, initVal, maxVal, fn, step, minVal, primitive } = controller
 | 
					  const { type, initVal, maxVal, fn, step, minVal, primitive } = controller
 | 
				
			||||||
@ -648,3 +832,25 @@ function modelAnimationController(controller) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  render()
 | 
					  render()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function removeAllEntity() {
 | 
				
			||||||
 | 
					  boosterMap.values().forEach(i => {
 | 
				
			||||||
 | 
					    viewer.entities.remove(i)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  boosterMap.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  interceptMap.values().forEach(i => {
 | 
				
			||||||
 | 
					    viewer.entities.remove(i)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  interceptMap.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pathLine.values().forEach(i => {
 | 
				
			||||||
 | 
					    viewer.entities.remove(i)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  pathLine.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ddMap.values().forEach(i => {
 | 
				
			||||||
 | 
					    viewer.scene.primitives.remove(i.primitive)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  ddMap.clear()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user