Compare commits
No commits in common. "2c0b750b87eeada0fee0cf6a8a91ea5bf5760e7a" and "e5dc139a6b3938b1628c7bce36bf7c489826d9c8" have entirely different histories.
2c0b750b87
...
e5dc139a6b
Binary file not shown.
Before Width: | Height: | Size: 756 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,15 +2,6 @@ export default class ExplosionEffect {
|
||||
constructor(viewer, obj) {
|
||||
this.viewer = viewer
|
||||
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,
|
||||
gravity: 0.0, //设置重力参数
|
||||
minimumParticleLife: 1,
|
||||
@ -19,7 +10,7 @@ export default class ExplosionEffect {
|
||||
maximumSpeed: 4.0, //粒子发射的最大速度
|
||||
startScale: 0.0,
|
||||
endScale: 8.0,
|
||||
particleSize: 10.0,
|
||||
particleSize: 25.0,
|
||||
}
|
||||
this.emitterModelMatrix = new Cesium.Matrix4()
|
||||
this.translation = new Cesium.Cartesian3()
|
||||
@ -42,8 +33,7 @@ export default class ExplosionEffect {
|
||||
// this.viewer.trackedEntity = this.entity;
|
||||
let particleSystem = this.scene.primitives.add(
|
||||
new Cesium.ParticleSystem({
|
||||
// image: './images/explosion.png', //生成所需粒子的图片路径
|
||||
image: './images/fire.png', //生成所需粒子的图片路径
|
||||
image: './images/explosion.png', //生成所需粒子的图片路径
|
||||
//粒子在生命周期开始时的颜色
|
||||
startColor: Cesium.Color.RED.withAlpha(0.7),
|
||||
//粒子在生命周期结束时的颜色
|
||||
@ -71,33 +61,14 @@ export default class ExplosionEffect {
|
||||
lifetime: 16.0,
|
||||
//设置粒子的大小是否以米或像素为单位
|
||||
sizeInMeters: false,
|
||||
// sizeInMeters: true,
|
||||
//系统的粒子发射器
|
||||
// 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)
|
||||
},
|
||||
emitter: new Cesium.CircleEmitter(5.0), //BoxEmitter 盒形发射器,ConeEmitter 锥形发射器,SphereEmitter 球形发射器,CircleEmitter圆形发射器
|
||||
})
|
||||
)
|
||||
this.particleSystem = particleSystem
|
||||
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() {
|
||||
let _this = this
|
||||
|
101
src/utils/pos.js
101
src/utils/pos.js
@ -32,107 +32,6 @@ export function getPositionFromTime(
|
||||
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) {
|
||||
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,14 +9,8 @@ const panels = ['手动配置', 'STK轨迹文件配置']
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const { daodanData, showOrHideDdConfig } = useDaodan()
|
||||
const {
|
||||
trajData,
|
||||
boosterList,
|
||||
interceptData,
|
||||
loadStoreData,
|
||||
addIntercept,
|
||||
initDaodan,
|
||||
} = useTestConfig()
|
||||
const { trajData, interceptData, loadStoreData, addIntercept, initDaodan } =
|
||||
useTestConfig()
|
||||
|
||||
watch(daodanData, newval => {
|
||||
loadStoreData()
|
||||
@ -60,19 +54,8 @@ export default defineComponent({
|
||||
<div class="detail-container">
|
||||
{panel === '手动配置' ? (
|
||||
<>
|
||||
<div class="flex flex-col gap-4 rounded border border-blue-500 p-4">
|
||||
<TrajTable
|
||||
title="轨迹点"
|
||||
data={trajData.value}
|
||||
showPosIcon={false}
|
||||
/>
|
||||
{boosterList.value.map((booster, index) => (
|
||||
<TrajTable
|
||||
title={`${['一', '二', '三'][index]}级助推器`}
|
||||
data={booster}
|
||||
showPosIcon={false}
|
||||
/>
|
||||
))}
|
||||
<div class="rounded border border-blue-500 p-4">
|
||||
<TrajTable title="轨迹点" data={trajData.value} />
|
||||
</div>
|
||||
<div class="flex flex-col gap-4 rounded border border-red-500 p-4">
|
||||
{interceptData.value.map(data => (
|
||||
@ -80,7 +63,6 @@ export default defineComponent({
|
||||
title="拦截"
|
||||
data={data}
|
||||
onRemoveIntercept={removeIntercept}
|
||||
showPosIcon={false}
|
||||
/>
|
||||
))}
|
||||
<div>
|
||||
@ -93,9 +75,6 @@ export default defineComponent({
|
||||
) : (
|
||||
<>
|
||||
<TrajUpload title="轨迹点" />
|
||||
<TrajUpload title="一级助推器" />
|
||||
<TrajUpload title="二级助推器" />
|
||||
<TrajUpload title="三级助推器" />
|
||||
<TrajUpload title="拦截" />
|
||||
</>
|
||||
)}
|
||||
|
@ -38,7 +38,7 @@ export default defineComponent({
|
||||
render(row) {
|
||||
return (
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div>{row.name}</div>
|
||||
<div>{row.name} </div>
|
||||
{props.showPosIcon && (
|
||||
<NButton
|
||||
// quaternary
|
||||
@ -75,7 +75,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
{
|
||||
title: getTitle('lon'),
|
||||
title: '经度',
|
||||
key: 'lon',
|
||||
render(row) {
|
||||
return (
|
||||
@ -88,7 +88,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
{
|
||||
title: getTitle('lat'),
|
||||
title: '纬度',
|
||||
key: 'lat',
|
||||
render(row) {
|
||||
return (
|
||||
@ -109,7 +109,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
{
|
||||
title: getTitle('time'),
|
||||
title: '时间',
|
||||
key: 'time',
|
||||
render(row) {
|
||||
return (
|
||||
@ -117,27 +117,52 @@ 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>
|
||||
) : (
|
||||
'-'
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
function getTitle(key) {
|
||||
const isIntercept = props.title.indexOf('拦截') > -1
|
||||
const isBooster = props.title.indexOf('助推器') > -1
|
||||
|
||||
const dict = {
|
||||
time: isIntercept ? '命中时间' : isBooster ? '脱离时间' : '时间',
|
||||
lat: isIntercept ? '发射纬度' : isBooster ? '落点纬度' : '纬度',
|
||||
lon: isIntercept ? '发射经度' : isBooster ? '落点经度' : '经度',
|
||||
alt: '高度',
|
||||
}
|
||||
return dict[key] || key
|
||||
const addFeaturePoint = () => {
|
||||
trajData.value.splice(trajData.value.length - 1, 0, {
|
||||
name: '中间特征点',
|
||||
lon: 0,
|
||||
lat: 0,
|
||||
alt: 0,
|
||||
time: Date.now(),
|
||||
detached: false,
|
||||
})
|
||||
}
|
||||
|
||||
if (props.title.indexOf('助推器') > -1) {
|
||||
columns.splice(3, 1)
|
||||
} else if (props.title.indexOf('拦截') > -1) {
|
||||
columns.splice(3, 1)
|
||||
}
|
||||
|
||||
const dialog = useDialog()
|
||||
const remove = () => {
|
||||
dialog.warning({
|
||||
@ -155,6 +180,9 @@ export default defineComponent({
|
||||
<div class="flex justify-between">
|
||||
<div class="detail-item-title">{props.title}</div>
|
||||
<div>
|
||||
<NButton quaternary type="primary" onClick={addFeaturePoint}>
|
||||
添加特征点
|
||||
</NButton>
|
||||
{props.title.indexOf('拦截') > -1 && (
|
||||
<NButton quaternary type="error" onClick={remove}>
|
||||
删除拦截
|
||||
|
@ -1,20 +1,12 @@
|
||||
import { ref, toRaw } from 'vue'
|
||||
import { useDaodan } from '../../ddHooks'
|
||||
import {
|
||||
cartesian32LonLat,
|
||||
getPositionFromTime,
|
||||
getOnePositionFromTime,
|
||||
test,
|
||||
createTrajectory,
|
||||
} from '@/utils/pos'
|
||||
import { cartesian32LonLat, getPositionFromTime } from '@/utils/pos'
|
||||
import ExplosionEffect from '@/js/Explosion'
|
||||
import { generateId } from '@/utils/id'
|
||||
import store from 'store2'
|
||||
import { lineString, bezierSpline } from '@turf/turf'
|
||||
// import { getPositionFromTime } from '@/utils/pos'
|
||||
// import { useDaodan } from '../../ddHooks'
|
||||
|
||||
const ddScale = 30
|
||||
|
||||
const trajData = ref({
|
||||
id: 'dd',
|
||||
data: [
|
||||
@ -26,69 +18,63 @@ const trajData = ref({
|
||||
time: 1183135260000,
|
||||
},
|
||||
{
|
||||
name: '最高点',
|
||||
lon: 125,
|
||||
lat: 25,
|
||||
name: '中间特征点',
|
||||
lon: 122,
|
||||
lat: 21,
|
||||
alt: 1000000,
|
||||
time: 1183135265000,
|
||||
detached: true,
|
||||
},
|
||||
{
|
||||
name: '中间特征点',
|
||||
lon: 124,
|
||||
lat: 21,
|
||||
alt: 1500000,
|
||||
time: 1183135270000,
|
||||
detached: true,
|
||||
},
|
||||
{
|
||||
name: '中间特征点',
|
||||
lon: 128,
|
||||
lat: 21,
|
||||
alt: 2000000,
|
||||
time: 1183135280000,
|
||||
detached: true,
|
||||
},
|
||||
{
|
||||
name: '落点',
|
||||
lon: 160,
|
||||
lat: 40,
|
||||
alt: 0,
|
||||
time: 1183135300000,
|
||||
lon: 135,
|
||||
lat: 21,
|
||||
alt: 1500000,
|
||||
time: 1183135290000,
|
||||
},
|
||||
],
|
||||
})
|
||||
const boosterList = ref([
|
||||
{
|
||||
id: 'booster-1',
|
||||
data: [
|
||||
{
|
||||
// name: '落点',
|
||||
lon: 130,
|
||||
lat: 23,
|
||||
alt: 0,
|
||||
time: 1183135265000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'booster-2',
|
||||
data: [
|
||||
{
|
||||
// name: '落点',
|
||||
lon: 135,
|
||||
lat: 28,
|
||||
alt: 0,
|
||||
time: 1183135270000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'booster-3',
|
||||
data: [
|
||||
{
|
||||
// name: '落点',
|
||||
lon: 140,
|
||||
lat: 35,
|
||||
alt: 0,
|
||||
time: 1183135275000,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
const interceptData = ref([
|
||||
{
|
||||
id: 'intercept-1',
|
||||
id: 'dd1',
|
||||
data: [
|
||||
{
|
||||
// name: '起始点',
|
||||
name: '起始点',
|
||||
lon: 137,
|
||||
lat: 25,
|
||||
alt: 0,
|
||||
time: 1183135285000,
|
||||
time: 1183135270000,
|
||||
},
|
||||
{
|
||||
name: '中间特征点',
|
||||
lon: 138,
|
||||
lat: 24,
|
||||
alt: 1000000,
|
||||
time: 1183135280000,
|
||||
detached: true,
|
||||
},
|
||||
{
|
||||
name: '落点',
|
||||
lon: 135,
|
||||
lat: 21,
|
||||
alt: 1500000,
|
||||
time: 1183135290000,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -99,7 +85,6 @@ const { daodanData, showDdConfigCom } = useDaodan()
|
||||
export function useTestConfig() {
|
||||
return {
|
||||
trajData,
|
||||
boosterList,
|
||||
interceptData,
|
||||
loadStoreData,
|
||||
addIntercept,
|
||||
@ -109,16 +94,13 @@ export function useTestConfig() {
|
||||
}
|
||||
|
||||
function saveDataToStore() {
|
||||
// test()
|
||||
const daodanDataRaw = toRaw(daodanData.value)
|
||||
const storeData = store.get('daodanData')
|
||||
|
||||
store.set('daodanData', {
|
||||
...storeData,
|
||||
[daodanDataRaw.id]: {
|
||||
...daodanDataRaw,
|
||||
trajData: trajData.value,
|
||||
boosterList: boosterList.value,
|
||||
interceptData: interceptData.value,
|
||||
},
|
||||
})
|
||||
@ -192,23 +174,20 @@ function addDaodan(trajData, type = 0) {
|
||||
ddTrajData[0].alt
|
||||
)
|
||||
const hpRoll = new Cesium.HeadingPitchRoll()
|
||||
// const fixedFrameTransform = Cesium.Transforms.eastNorthUpToFixedFrame
|
||||
const fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator(
|
||||
'north',
|
||||
'west'
|
||||
)
|
||||
// hpRoll.pitch = (90 * Math.PI) / 180
|
||||
hpRoll.pitch = (90 * Math.PI) / 180
|
||||
const modelObj = Cesium.Model.fromGltf({
|
||||
// url: './models/launchvehicle.glb',
|
||||
url: './models/美三叉戟2动画.glb',
|
||||
url: './models/launchvehicle.glb',
|
||||
modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
position,
|
||||
hpRoll,
|
||||
Cesium.Ellipsoid.WGS84,
|
||||
fixedFrameTransform
|
||||
),
|
||||
scale: ddScale,
|
||||
minimumPixelSize: ddScale,
|
||||
minimumPixelSize: 70,
|
||||
})
|
||||
|
||||
const ddPrimitive = viewer.scene.primitives.add(modelObj)
|
||||
@ -231,16 +210,17 @@ function addDaodan(trajData, type = 0) {
|
||||
// })
|
||||
|
||||
ddPrimitive.readyPromise.then(model => {
|
||||
console.log('model', model)
|
||||
nodes = model.pickIds.map(item => item.object.detail.node)
|
||||
console.log('nodes', nodes)
|
||||
// nodes.forEach(i => {
|
||||
// // console.log(i._name, model.getNode(i._name))
|
||||
// if (new RegExp(/SRB\d/).test(i._name)) {
|
||||
// model.getNode(i._name).show = false
|
||||
// }
|
||||
// })
|
||||
nodes.forEach(i => {
|
||||
// console.log(i._name, model.getNode(i._name))
|
||||
if (new RegExp(/SRB\d/).test(i._name)) {
|
||||
model.getNode(i._name).show = false
|
||||
}
|
||||
})
|
||||
computePath(ddPrimitive, trajData, type)
|
||||
// setTimeout(() => {
|
||||
// playDaodan(ddPrimitive, nodes)
|
||||
// }, 3000)
|
||||
})
|
||||
}
|
||||
|
||||
@ -249,16 +229,16 @@ function initDaodan() {
|
||||
saveDataToStore()
|
||||
minTime = getMinTime([
|
||||
...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)
|
||||
addDaodan(trajData.value)
|
||||
aniIndexMap.set(trajData.value.id, 0)
|
||||
// interceptData.value.forEach(item => {
|
||||
// const { id, data } = item
|
||||
// addDaodan(item, 1)
|
||||
// aniIndexMap.set(id, 0)
|
||||
// })
|
||||
interceptData.value.forEach(item => {
|
||||
const { id, data } = item
|
||||
addDaodan(item, 1)
|
||||
aniIndexMap.set(id, 0)
|
||||
})
|
||||
}
|
||||
|
||||
function getMinTime(data) {
|
||||
@ -269,16 +249,14 @@ function getMinTime(data) {
|
||||
return minTime
|
||||
}
|
||||
|
||||
const pathLine = new Map()
|
||||
|
||||
function computePath(daodan, trajData, type) {
|
||||
const { id, data: ddTrajData } = trajData
|
||||
const { data: ddTrajData } = trajData
|
||||
const points = ddTrajData.map(item => {
|
||||
const { time, lon, lat, alt } = item
|
||||
|
||||
const { time, lon, lat, alt, detached } = item
|
||||
return {
|
||||
position: Cesium.Cartesian3.fromDegrees(lon, lat, alt),
|
||||
time: time - minTime,
|
||||
detached,
|
||||
}
|
||||
})
|
||||
const totalAnimationTime = points.at(-1).time
|
||||
@ -292,13 +270,13 @@ function computePath(daodan, trajData, type) {
|
||||
point.time / 1000,
|
||||
new Cesium.JulianDate()
|
||||
)
|
||||
// const point = viewer.entities.add({
|
||||
// position: point.position,
|
||||
// point: {
|
||||
// color: Cesium.Color.WHITE,
|
||||
// pixelSize: 5,
|
||||
// },
|
||||
// })
|
||||
viewer.entities.add({
|
||||
position: point.position,
|
||||
point: {
|
||||
color: Cesium.Color.WHITE,
|
||||
pixelSize: 5,
|
||||
},
|
||||
})
|
||||
positionProperty.addSample(time, point.position)
|
||||
})
|
||||
positionProperty.setInterpolationOptions({
|
||||
@ -307,28 +285,7 @@ function computePath(daodan, trajData, type) {
|
||||
// interpolationDegree: 5,
|
||||
// interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
|
||||
})
|
||||
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',
|
||||
})
|
||||
}
|
||||
createLine({ totalAnimationTime, startTime, positionProperty, type })
|
||||
daodanAnimation({
|
||||
totalAnimationTime,
|
||||
startTime,
|
||||
@ -338,140 +295,11 @@ 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) {
|
||||
const { totalAnimationTime, startTime, positionProperty, daodan, trajData } =
|
||||
params
|
||||
// const { data: ddTrajData } = trajData
|
||||
// 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)
|
||||
dianhuo(daodan)
|
||||
|
||||
let lastFrameTime = performance.now()
|
||||
let customElapsedTime = 0
|
||||
@ -489,17 +317,12 @@ function daodanAnimation(params) {
|
||||
if (customElapsedTime >= totalAnimationTime) {
|
||||
customElapsedTime = totalAnimationTime // 限制时间为总时长
|
||||
isAnimationRunning = false // 停止动画
|
||||
|
||||
setTimeout(() => {
|
||||
removeAllEntity()
|
||||
}, 6000)
|
||||
}
|
||||
|
||||
// ddNodesAnimationController({
|
||||
// ddPrimitive: daodan,
|
||||
// curTime: minTime + customElapsedTime * 1000,
|
||||
// trajData,
|
||||
// })
|
||||
ddNodesAnimationController({
|
||||
ddPrimitive: daodan,
|
||||
curTime: minTime + customElapsedTime * 1000,
|
||||
trajData,
|
||||
})
|
||||
|
||||
// 计算自定义时间下的位置
|
||||
const customTime = Cesium.JulianDate.addSeconds(
|
||||
@ -517,27 +340,16 @@ function daodanAnimation(params) {
|
||||
new Cesium.JulianDate()
|
||||
)
|
||||
)
|
||||
|
||||
if (interceptTime.value && customElapsedTime >= interceptTime.value) {
|
||||
customElapsedTime = totalAnimationTime
|
||||
isAnimationRunning = false
|
||||
explosion = explosionEffect(position)
|
||||
|
||||
setTimeout(() => {
|
||||
removeAllEntity()
|
||||
}, 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)
|
||||
const [lon, lat, height] = cartesian32LonLat(position)
|
||||
explosion = new ExplosionEffect(viewer, {
|
||||
lng: lon,
|
||||
lat: lat,
|
||||
height,
|
||||
})
|
||||
setTimeout(() => {
|
||||
explosion && explosion.remove()
|
||||
}, 6000)
|
||||
}
|
||||
if (position && nextPosition) {
|
||||
const fixedFrameTransform =
|
||||
@ -551,22 +363,16 @@ function daodanAnimation(params) {
|
||||
fixedFrameTransform,
|
||||
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) {
|
||||
modelAnimationController({
|
||||
primitive: ddPrimitive,
|
||||
@ -586,6 +392,14 @@ function ddNodesAnimationController(params) {
|
||||
const { id: ddId, data: ddTrajData } = trajData
|
||||
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
|
||||
|
||||
const aniIndex = aniIndexMap.get(ddId)
|
||||
@ -781,36 +595,38 @@ function getHeadingPitchRoll(curPos, nextPos) {
|
||||
return hpr
|
||||
}
|
||||
|
||||
function createLine({
|
||||
totalAnimationTime,
|
||||
startTime,
|
||||
positionProperty,
|
||||
type,
|
||||
color,
|
||||
}) {
|
||||
function createLine({ totalAnimationTime, startTime, positionProperty, type }) {
|
||||
const positionList = getPositionFromTime(
|
||||
startTime,
|
||||
positionProperty,
|
||||
totalAnimationTime
|
||||
)
|
||||
// if (type === 2) {
|
||||
// console.log('positionList', positionList)
|
||||
// }
|
||||
|
||||
return viewer.entities.add({
|
||||
viewer.entities.add({
|
||||
position: positionProperty,
|
||||
polyline: {
|
||||
positions: positionList,
|
||||
width: 8,
|
||||
material: new Cesium.PolylineGlowMaterialProperty({
|
||||
glowPower: 0.1,
|
||||
color: type
|
||||
? type === 2 && Cesium.Color[color].withAlpha(0.5)
|
||||
: Cesium.Color.BLUE.withAlpha(0.5),
|
||||
}),
|
||||
width: 2,
|
||||
material: type
|
||||
? Cesium.Color.RED.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) {
|
||||
const { type, initVal, maxVal, fn, step, minVal, primitive } = controller
|
||||
@ -832,25 +648,3 @@ function modelAnimationController(controller) {
|
||||
}
|
||||
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