原文链接及内容

效果如下视频所示:

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/**
* 关于追踪参考系-TrackingReferenceFrame,请参考以下官方文档进一步学习:
* https://cesium.com/learn/cesiumjs/ref-doc/global.html?classFilter=TrackingReferenceFrame#TrackingReferenceFrame
* - AUTODETECT: 自动检测算法。
* 用于跟踪实体的参考系将根据其轨迹自动选择:
* - 近表面缓慢移动的物体将在实体的本地东北天(ENU)参考系中进行跟踪,
* - 而卫星等较快的物体将使用 VVLH(Vehicle Velocity, Local Horizontal,飞行器速度-本地水平坐标系)。
* - 关于VVLH,VV,这里称为V轴,V轴指向飞行器的的瞬时速度方向;
* - H轴垂直于地心到飞行器的连线,并指向轨道平面的水平方向,与速度方向共同构成轨道平面。
* - 由上述V轴和H轴计算得出第三轴,这里称为L轴,即轨道平面的法线方向。
* 通用场景。
* - INERTIAL: 适用于卫星、航天器,不考虑地球自转,但在没有定义方向时会回退到AUTODETECT。
* - VELOCITY: 适用于导弹、飞机等,始终对齐速度方向,满足了特定领域(如航空航天)的精确控制需求。
* - ENU: 适用于地面车辆,建筑物等,固定于当地地理方向。
*/

const viewer = new Cesium.Viewer("cesiumContainer", {
geocoder: false,
homeButton: false,
sceneModePicker: false,
navigationHelpButton: false,
navigationInstructionsInitiallyVisible: false,
animation: false,
timeline: true,
fullscreenButton: false,
selectionIndicator: false,
skyBox: false,
shouldAnimate: true,
infoBox: false,
baseLayerPicker: false,
terrain: Cesium.Terrain.fromWorldTerrain(),
});
viewer.cesiumWidget.creditContainer.style.display = "none";

//根据太阳位置启用光照
viewer.scene.globe.enableLighting = true;
//启用深度测试,使地形后面的物体消失。
viewer.scene.globe.depthTestAgainstTerrain = true;

//设置随机数种子(seed,初始值)以获得一致的结果。
Cesium.Math.setRandomNumberSeed(3);

//设置模拟时间的范围
const start = Cesium.JulianDate.fromDate(new Date(2015, 2, 25, 16)); //开始时间为2015年3月25日下午4点(16:00)
//结束时间增加360秒,即6分钟,即结束时间为2015年3月25日16:06:00
const stop = Cesium.JulianDate.addSeconds(start, 360, new Cesium.JulianDate());

//确保观看者处于所需的时间点。
viewer.clock.startTime = start.clone();
viewer.clock.stopTime = stop.clone();
viewer.clock.currentTime = start.clone();
//https://cesium.com/learn/cesiumjs/ref-doc/global.html?classFilter=ClockRange#ClockRange
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //结束后循环
viewer.clock.multiplier = 10; //10倍速

//将时间轴设置为模拟边界
viewer.timeline.zoomTo(start, stop);

//生成一个具有不同高度的随机圆形图案。
function computeCirclularFlight(lon, lat, radius) {
const property = new Cesium.SampledPositionProperty();
for (let i = 0; i <= 360; i += 45) {
const radians = Cesium.Math.toRadians(i);
const time = Cesium.JulianDate.addSeconds(
start,
i,
new Cesium.JulianDate()
);
const position = Cesium.Cartesian3.fromDegrees(
lon + radius * 1.5 * Math.cos(radians),
lat + radius * Math.sin(radians),
Cesium.Math.nextRandomNumber() * 500 + 1750
);
property.addSample(time, position);

//同时为我们生成的每个样本创建一个点。
viewer.entities.add({
position,
point: {
pixelSize: 8,
color: Cesium.Color.TRANSPARENT,
outlineColor: Cesium.Color.YELLOW,
outlineWidth: 3,
},
});
}
return property;
}

//根据经纬度和半径生成一个圆形图案
const position = computeCirclularFlight(-112.110693, 36.0994841, 0.03);

const entity = viewer.entities.add({
//将实体可用性(availability)设置为与模拟时间相同的间隔。
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({ start, stop }),
]),
position,
//根据位置移动自动计算方向。
orientation: new Cesium.VelocityOrientationProperty(position),
//加载 Cesium 飞机模型
model: {
uri: "../SampleData/models/CesiumAir/Cesium_Air.glb",
minimumPixelSize: 64,
},
//以粉色线条显示路径,采样间隔为 1 秒。
path: {
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: Cesium.Color.YELLOW,
}),
width: 10,
},
});

//添加按钮以从上向下查看路径
Sandcastle.addDefaultToolbarButton("从上向下查看(路径)", function () {
viewer.trackedEntity = undefined;
viewer.zoomTo(
viewer.entities,
new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90))
);
});

//添加按钮以从侧面查看路径
Sandcastle.addToolbarButton("从侧面查看(路径)", function () {
viewer.trackedEntity = undefined;
viewer.zoomTo(
viewer.entities,
new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(-90),
Cesium.Math.toRadians(-15),
7500
)
);
});

//添加按钮以追踪实体移动
Sandcastle.addToolbarButton("追踪飞机模型", function () {
viewer.trackedEntity = entity;
});

Sandcastle.addToolbarMenu([
{
text: "跟踪参考框架: 东北天坐标系",
onselect: function () {
//ENU:实体的本地东北天参考坐标系。
entity.trackingReferenceFrame = Cesium.TrackingReferenceFrame.ENU;
},
},
{
text: "跟踪参考框架: 惯性参考坐标系",
onselect: function () {
//INERTIAL:实体的惯性参考坐标系。若实体未定义方向属性,则回退至自动检测算法,即AUTODETECT。
entity.trackingReferenceFrame = Cesium.TrackingReferenceFrame.INERTIAL;
},
},
]);

//添加一个下拉框以选择每种插值模式。
Sandcastle.addToolbarMenu(
[
{
text: "线性插值",
onselect: function () {
/**
* SampledPositionProperty.setInterpolationOptions({interpolationAlgorithm, interpolationDegree})方法
* - interpolationAlgorithm:插值算法
* - interpolationDegree:插值多项式的阶数,影响插值曲线的平滑度和计算复杂度。
*/
entity.position.setInterpolationOptions({
interpolationDegree: 1,//线性插值的阶数显然为1,插值点间直线相连
interpolationAlgorithm: Cesium.LinearApproximation,
});
},
},
{
text: "拉格朗日多项式插值",
onselect: function () {
entity.position.setInterpolationOptions({
interpolationDegree: 5,//使用5阶多项式,意味着插值会考虑更多数据点,生成更平滑的曲线。
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
});
},
},
{
text: "埃尔米特多项式插值",
onselect: function () {
entity.position.setInterpolationOptions({
interpolationDegree: 2,//使用2阶多项式,平衡了平滑度和计算复杂度。
interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
});
},
},
],
"interpolationMenu"
);