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) {
|
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,
|
||||||
@ -19,7 +10,7 @@ export default class ExplosionEffect {
|
|||||||
maximumSpeed: 4.0, //粒子发射的最大速度
|
maximumSpeed: 4.0, //粒子发射的最大速度
|
||||||
startScale: 0.0,
|
startScale: 0.0,
|
||||||
endScale: 8.0,
|
endScale: 8.0,
|
||||||
particleSize: 10.0,
|
particleSize: 25.0,
|
||||||
}
|
}
|
||||||
this.emitterModelMatrix = new Cesium.Matrix4()
|
this.emitterModelMatrix = new Cesium.Matrix4()
|
||||||
this.translation = new Cesium.Cartesian3()
|
this.translation = new Cesium.Cartesian3()
|
||||||
@ -42,8 +33,7 @@ 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),
|
||||||
//粒子在生命周期结束时的颜色
|
//粒子在生命周期结束时的颜色
|
||||||
@ -71,33 +61,14 @@ 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,107 +32,6 @@ 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,14 +9,8 @@ const panels = ['手动配置', 'STK轨迹文件配置']
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
const { daodanData, showOrHideDdConfig } = useDaodan()
|
const { daodanData, showOrHideDdConfig } = useDaodan()
|
||||||
const {
|
const { trajData, interceptData, loadStoreData, addIntercept, initDaodan } =
|
||||||
trajData,
|
useTestConfig()
|
||||||
boosterList,
|
|
||||||
interceptData,
|
|
||||||
loadStoreData,
|
|
||||||
addIntercept,
|
|
||||||
initDaodan,
|
|
||||||
} = useTestConfig()
|
|
||||||
|
|
||||||
watch(daodanData, newval => {
|
watch(daodanData, newval => {
|
||||||
loadStoreData()
|
loadStoreData()
|
||||||
@ -60,19 +54,8 @@ export default defineComponent({
|
|||||||
<div class="detail-container">
|
<div class="detail-container">
|
||||||
{panel === '手动配置' ? (
|
{panel === '手动配置' ? (
|
||||||
<>
|
<>
|
||||||
<div class="flex flex-col gap-4 rounded border border-blue-500 p-4">
|
<div class="rounded border border-blue-500 p-4">
|
||||||
<TrajTable
|
<TrajTable title="轨迹点" data={trajData.value} />
|
||||||
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 => (
|
||||||
@ -80,7 +63,6 @@ export default defineComponent({
|
|||||||
title="拦截"
|
title="拦截"
|
||||||
data={data}
|
data={data}
|
||||||
onRemoveIntercept={removeIntercept}
|
onRemoveIntercept={removeIntercept}
|
||||||
showPosIcon={false}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<div>
|
<div>
|
||||||
@ -93,9 +75,6 @@ export default defineComponent({
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<TrajUpload title="轨迹点" />
|
<TrajUpload title="轨迹点" />
|
||||||
<TrajUpload title="一级助推器" />
|
|
||||||
<TrajUpload title="二级助推器" />
|
|
||||||
<TrajUpload title="三级助推器" />
|
|
||||||
<TrajUpload title="拦截" />
|
<TrajUpload title="拦截" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -75,7 +75,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: getTitle('lon'),
|
title: '经度',
|
||||||
key: 'lon',
|
key: 'lon',
|
||||||
render(row) {
|
render(row) {
|
||||||
return (
|
return (
|
||||||
@ -88,7 +88,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: getTitle('lat'),
|
title: '纬度',
|
||||||
key: 'lat',
|
key: 'lat',
|
||||||
render(row) {
|
render(row) {
|
||||||
return (
|
return (
|
||||||
@ -109,7 +109,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: getTitle('time'),
|
title: '时间',
|
||||||
key: 'time',
|
key: 'time',
|
||||||
render(row) {
|
render(row) {
|
||||||
return (
|
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 addFeaturePoint = () => {
|
||||||
const isIntercept = props.title.indexOf('拦截') > -1
|
trajData.value.splice(trajData.value.length - 1, 0, {
|
||||||
const isBooster = props.title.indexOf('助推器') > -1
|
name: '中间特征点',
|
||||||
|
lon: 0,
|
||||||
const dict = {
|
lat: 0,
|
||||||
time: isIntercept ? '命中时间' : isBooster ? '脱离时间' : '时间',
|
alt: 0,
|
||||||
lat: isIntercept ? '发射纬度' : isBooster ? '落点纬度' : '纬度',
|
time: Date.now(),
|
||||||
lon: isIntercept ? '发射经度' : isBooster ? '落点经度' : '经度',
|
detached: false,
|
||||||
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({
|
||||||
@ -155,6 +180,9 @@ 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,20 +1,12 @@
|
|||||||
import { ref, toRaw } from 'vue'
|
import { ref, toRaw } from 'vue'
|
||||||
import { useDaodan } from '../../ddHooks'
|
import { useDaodan } from '../../ddHooks'
|
||||||
import {
|
import { cartesian32LonLat, getPositionFromTime } from '@/utils/pos'
|
||||||
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 { lineString, bezierSpline } from '@turf/turf'
|
// import { getPositionFromTime } from '@/utils/pos'
|
||||||
// import { useDaodan } from '../../ddHooks'
|
// import { useDaodan } from '../../ddHooks'
|
||||||
|
|
||||||
const ddScale = 30
|
|
||||||
|
|
||||||
const trajData = ref({
|
const trajData = ref({
|
||||||
id: 'dd',
|
id: 'dd',
|
||||||
data: [
|
data: [
|
||||||
@ -26,69 +18,63 @@ const trajData = ref({
|
|||||||
time: 1183135260000,
|
time: 1183135260000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '最高点',
|
name: '中间特征点',
|
||||||
lon: 125,
|
lon: 122,
|
||||||
lat: 25,
|
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,
|
alt: 2000000,
|
||||||
time: 1183135280000,
|
time: 1183135280000,
|
||||||
|
detached: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '落点',
|
name: '落点',
|
||||||
lon: 160,
|
lon: 135,
|
||||||
lat: 40,
|
lat: 21,
|
||||||
alt: 0,
|
alt: 1500000,
|
||||||
time: 1183135300000,
|
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([
|
const interceptData = ref([
|
||||||
{
|
{
|
||||||
id: 'intercept-1',
|
id: 'dd1',
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
// name: '起始点',
|
name: '起始点',
|
||||||
lon: 137,
|
lon: 137,
|
||||||
lat: 25,
|
lat: 25,
|
||||||
alt: 0,
|
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() {
|
export function useTestConfig() {
|
||||||
return {
|
return {
|
||||||
trajData,
|
trajData,
|
||||||
boosterList,
|
|
||||||
interceptData,
|
interceptData,
|
||||||
loadStoreData,
|
loadStoreData,
|
||||||
addIntercept,
|
addIntercept,
|
||||||
@ -109,16 +94,13 @@ 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,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -192,23 +174,20 @@ 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
|
||||||
),
|
),
|
||||||
scale: ddScale,
|
minimumPixelSize: 70,
|
||||||
minimumPixelSize: ddScale,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const ddPrimitive = viewer.scene.primitives.add(modelObj)
|
const ddPrimitive = viewer.scene.primitives.add(modelObj)
|
||||||
@ -231,16 +210,17 @@ 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)
|
||||||
console.log('nodes', nodes)
|
nodes.forEach(i => {
|
||||||
// nodes.forEach(i => {
|
// console.log(i._name, model.getNode(i._name))
|
||||||
// // console.log(i._name, model.getNode(i._name))
|
if (new RegExp(/SRB\d/).test(i._name)) {
|
||||||
// if (new RegExp(/SRB\d/).test(i._name)) {
|
model.getNode(i._name).show = false
|
||||||
// model.getNode(i._name).show = false
|
}
|
||||||
// }
|
})
|
||||||
// })
|
|
||||||
computePath(ddPrimitive, trajData, type)
|
computePath(ddPrimitive, trajData, type)
|
||||||
|
// setTimeout(() => {
|
||||||
|
// playDaodan(ddPrimitive, nodes)
|
||||||
|
// }, 3000)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,16 +229,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) {
|
||||||
@ -269,16 +249,14 @@ function getMinTime(data) {
|
|||||||
return minTime
|
return minTime
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathLine = new Map()
|
|
||||||
|
|
||||||
function computePath(daodan, trajData, type) {
|
function computePath(daodan, trajData, type) {
|
||||||
const { id, data: ddTrajData } = trajData
|
const { data: ddTrajData } = trajData
|
||||||
const points = ddTrajData.map(item => {
|
const points = ddTrajData.map(item => {
|
||||||
const { time, lon, lat, alt } = item
|
const { time, lon, lat, alt, detached } = 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
|
||||||
@ -292,13 +270,13 @@ function computePath(daodan, trajData, type) {
|
|||||||
point.time / 1000,
|
point.time / 1000,
|
||||||
new Cesium.JulianDate()
|
new Cesium.JulianDate()
|
||||||
)
|
)
|
||||||
// const point = viewer.entities.add({
|
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({
|
||||||
@ -307,28 +285,7 @@ function computePath(daodan, trajData, type) {
|
|||||||
// interpolationDegree: 5,
|
// interpolationDegree: 5,
|
||||||
// interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
|
// interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
|
||||||
})
|
})
|
||||||
const line = createLine({
|
createLine({ totalAnimationTime, startTime, positionProperty, type })
|
||||||
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,
|
||||||
@ -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) {
|
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
|
||||||
@ -489,17 +317,12 @@ function daodanAnimation(params) {
|
|||||||
if (customElapsedTime >= totalAnimationTime) {
|
if (customElapsedTime >= totalAnimationTime) {
|
||||||
customElapsedTime = totalAnimationTime // 限制时间为总时长
|
customElapsedTime = totalAnimationTime // 限制时间为总时长
|
||||||
isAnimationRunning = false // 停止动画
|
isAnimationRunning = false // 停止动画
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
removeAllEntity()
|
|
||||||
}, 6000)
|
|
||||||
}
|
}
|
||||||
|
ddNodesAnimationController({
|
||||||
// ddNodesAnimationController({
|
ddPrimitive: daodan,
|
||||||
// ddPrimitive: daodan,
|
curTime: minTime + customElapsedTime * 1000,
|
||||||
// curTime: minTime + customElapsedTime * 1000,
|
trajData,
|
||||||
// trajData,
|
})
|
||||||
// })
|
|
||||||
|
|
||||||
// 计算自定义时间下的位置
|
// 计算自定义时间下的位置
|
||||||
const customTime = Cesium.JulianDate.addSeconds(
|
const customTime = Cesium.JulianDate.addSeconds(
|
||||||
@ -517,27 +340,16 @@ function daodanAnimation(params) {
|
|||||||
new Cesium.JulianDate()
|
new Cesium.JulianDate()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (interceptTime.value && customElapsedTime >= interceptTime.value) {
|
|
||||||
customElapsedTime = totalAnimationTime
|
|
||||||
isAnimationRunning = false
|
|
||||||
explosion = explosionEffect(position)
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
removeAllEntity()
|
|
||||||
}, 6000)
|
|
||||||
}
|
|
||||||
if (position && !nextPosition && !explosion) {
|
if (position && !nextPosition && !explosion) {
|
||||||
// const [lon, lat, height] = cartesian32LonLat(position)
|
const [lon, lat, height] = cartesian32LonLat(position)
|
||||||
// explosion = new ExplosionEffect(viewer, {
|
explosion = new ExplosionEffect(viewer, {
|
||||||
// lng: lon,
|
lng: lon,
|
||||||
// lat: lat,
|
lat: lat,
|
||||||
// height,
|
height,
|
||||||
// })
|
})
|
||||||
// setTimeout(() => {
|
setTimeout(() => {
|
||||||
// explosion && explosion.remove()
|
explosion && explosion.remove()
|
||||||
// }, 6000)
|
}, 6000)
|
||||||
explosion = explosionEffect(position)
|
|
||||||
}
|
}
|
||||||
if (position && nextPosition) {
|
if (position && nextPosition) {
|
||||||
const fixedFrameTransform =
|
const fixedFrameTransform =
|
||||||
@ -551,21 +363,15 @@ function daodanAnimation(params) {
|
|||||||
fixedFrameTransform,
|
fixedFrameTransform,
|
||||||
daodan.modelMatrix
|
daodan.modelMatrix
|
||||||
)
|
)
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function explosionEffect(position) {
|
// Cesium.Matrix4.fromTranslationQuaternionRotationScale(
|
||||||
const [lon, lat, height] = cartesian32LonLat(position)
|
// position,
|
||||||
const explosion = new ExplosionEffect(viewer, {
|
// orientation,
|
||||||
lng: lon,
|
// new Cesium.Cartesian3(1.0, 1.0, 1.0), // 缩放比例,
|
||||||
lat: lat,
|
// daodan.modelMatrix
|
||||||
height,
|
// )
|
||||||
|
}
|
||||||
})
|
})
|
||||||
setTimeout(() => {
|
|
||||||
explosion && explosion.remove()
|
|
||||||
}, 6000)
|
|
||||||
return explosion
|
|
||||||
}
|
}
|
||||||
function dianhuo(ddPrimitive) {
|
function dianhuo(ddPrimitive) {
|
||||||
modelAnimationController({
|
modelAnimationController({
|
||||||
@ -586,6 +392,14 @@ 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)
|
||||||
@ -781,36 +595,38 @@ function getHeadingPitchRoll(curPos, nextPos) {
|
|||||||
return hpr
|
return hpr
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLine({
|
function createLine({ totalAnimationTime, startTime, positionProperty, type }) {
|
||||||
totalAnimationTime,
|
|
||||||
startTime,
|
|
||||||
positionProperty,
|
|
||||||
type,
|
|
||||||
color,
|
|
||||||
}) {
|
|
||||||
const positionList = getPositionFromTime(
|
const positionList = getPositionFromTime(
|
||||||
startTime,
|
startTime,
|
||||||
positionProperty,
|
positionProperty,
|
||||||
totalAnimationTime
|
totalAnimationTime
|
||||||
)
|
)
|
||||||
// if (type === 2) {
|
viewer.entities.add({
|
||||||
// console.log('positionList', positionList)
|
|
||||||
// }
|
|
||||||
|
|
||||||
return viewer.entities.add({
|
|
||||||
position: positionProperty,
|
position: positionProperty,
|
||||||
polyline: {
|
polyline: {
|
||||||
positions: positionList,
|
positions: positionList,
|
||||||
width: 8,
|
width: 2,
|
||||||
material: new Cesium.PolylineGlowMaterialProperty({
|
material: type
|
||||||
glowPower: 0.1,
|
? Cesium.Color.RED.withAlpha(0.5)
|
||||||
color: type
|
|
||||||
? type === 2 && Cesium.Color[color].withAlpha(0.5)
|
|
||||||
: Cesium.Color.BLUE.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
|
||||||
@ -832,25 +648,3 @@ 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