本文介绍了如何通过Cesium库实现模拟导航功能。首先,定义了一系列的坐标点数据,包括经度、纬度和高度。接着,通过计算每两个坐标点之间的距离,结合设定的速度,计算出到达每个点所需的时间,并生成累计时间。随后,利用这些数据创建了一条贴地线,用于显示导航路径。同时,通过设置Cesium的时钟功能,模拟了时间轴上的导航过程。最后,添加了一个3D模型(如消防车)并使其沿着导航路径移动,模型的方向根据速度动态调整。整个过程展示了如何通过Cesium实现动态的模拟导航效果。
1.模拟导航
//模拟路线坐标点
let dataPoint = [
{ longitude: 109.10940332613728, latitude: 21.063021559971105, height: -0.018210332475859903},
{ longitude: 109.10890385351232, latitude: 21.06264649001574, height: -0.023490247563135298},
{ longitude: 109.10830449220843, latitude: 21.062224533643434, height: -0.027616728839422656},
{ longitude: 109.1076551972276, latitude: 21.061943238477614, height: -0.033035825192262225},
{ longitude: 109.10675617432534, latitude: 21.061333745075743, height: -0.03666834593656051},
{ longitude: 109.10500811055132, latitude: 21.0606773656621, height: -0.0377448671315091},
{ longitude: 109.10435883764646, latitude: 21.060255406032777, height: -0.037464542291758954},
{ longitude: 109.1037095723677, latitude: 21.05973967483185, height: -0.0348058333458437},
{ longitude: 109.10246098820474, latitude: 21.059411471210336, height: -0.02912268299172091},
{ longitude: 109.10151207670951, latitude: 21.058989500904566, height: -0.023347508321239645},
{ longitude: 109.10086282074256, latitude: 21.058848833206724, height: -0.01760441366121883},
{ longitude: 109.09966417601746, latitude: 21.05880193839097, height: -0.018748862709937857},
{ longitude: 109.09761655265744, latitude: 21.057770472672964, height: -0.017732579033211893},
{ longitude: 109.09661768771777, latitude: 21.057629800343154, height: -0.016932503375052844},
{ longitude: 109.09591850484162, latitude: 21.05716096178261, height: -0.0218609057546871},
{ longitude: 109.09521934210356, latitude: 21.056551467251015, height: -0.023294948953261733},
{ longitude: 109.09491974865989, latitude: 21.055895094018496, height: -0.018901449204320953},
{ longitude: 109.09442047294675, latitude: 21.05444171143661, height: -0.0073312502499514745},
{ longitude: 109.09427073032217, latitude: 21.053316554121054, height: -0.017887585849186906},
{ longitude: 109.0942708405191, latitude: 21.051863236784147, height: -0.029326492911395243},
{ longitude: 109.09417103760084, latitude: 21.050925604819682, height: -0.02905589491884606},
{ longitude: 109.0939214751148, latitude: 21.04956602653295, height: -0.009549508213138101},
{ longitude: 109.09347206091091, latitude: 21.04825332824284, height: -0.02876338632112541},
{ longitude: 109.09302265240453, latitude: 21.04725952953718, height: -0.016500826484963357},
{ longitude: 109.09247337865216, latitude: 21.045946789554343, height: -0.021589876226085977},
{ longitude: 109.09202395106423, latitude: 21.045055986542557, height: -0.02851851686722392},
{ longitude: 109.09187423161869, latitude: 21.043790149919957, height: -0.021921030727149036},
{ longitude: 109.09182439598999, latitude: 21.042524320038623, height: -0.012849565673008842},
{ longitude: 109.09192432237573, latitude: 21.04153978052041, height: -0.02073328093493618},
{ longitude: 109.09232388593985, latitude: 21.04060214608472, height: -0.02915003947347011},
{ longitude: 109.09292322432559, latitude: 21.039476996741403, height: -0.03209960068536177},
{ longitude: 109.09392210207515, latitude: 21.03835190514942, height: -0.01691279628864906},
{ longitude: 109.09487097716028, latitude: 21.0373674217739, height: -0.019936340925176935},
{ longitude: 109.09532043855774, latitude: 21.036523526407322, height: -0.02787392565305291},
{ longitude: 109.09616943925492, latitude: 21.03521083977135, height: -0.0182813502759573},
{ longitude: 109.09711827104574, latitude: 21.034179422206115, height: -0.02367647993025185},
{ longitude: 109.09846658847107, latitude: 21.034038868663817, height: -0.01982439069763755},
{ longitude: 109.09961514190948, latitude: 21.03394516524597, height: -0.01913418547329436},
{ longitude: 109.10181235891513, latitude: 21.03417970835646, height: -0.00850045106589409},
{ longitude: 109.10435910828028, latitude: 21.034226617887434, height: -0.017508919759048232},
{ longitude: 109.10610687709547, latitude: 21.033945305244437, height: -0.015091322390747626},
{ longitude: 109.10750508959528, latitude: 21.033663979775913, height: -0.008998798050895282},
{ longitude: 109.10925286684723, latitude: 21.03314815128293, height: -0.01798715975121182}
];
if(dataPoint.length == 0){
return;
}
let speed = 160;
let allSeconds = 0;
//计算每两点之间需要的时间和到达每个点的累计时间以及累计需要的总时间
const newArr1 = [];
for (let i = 0; i < dataPoint.length; i++) {
let distance = 0;
if (i > 0) {
distance = countDistance(dataPoint[i], dataPoint[i - 1]);
}
let s = ((distance / 1000) / speed) * 60 * 60;
allSeconds += s;
dataPoint[i].time = s;
if (i > 0) {
dataPoint[i].times = dataPoint[i - 1].times + s;
} else {
dataPoint[i].times = 0;
}
newArr1.push(dataPoint[i].longitude);
newArr1.push(dataPoint[i].latitude);
}
// 创建贴地线
let lineDataSource = viewer.scene.primitives.add(new Cesium.GroundPolylinePrimitive({
geometryInstances : new Cesium.GeometryInstance({
geometry : new Cesium.GroundPolylineGeometry({
positions : Cesium.Cartesian3.fromDegreesArray(newArr1),
width : 10.0,//线宽
vertexFormat : Cesium.PolylineColorAppearance.VERTEX_FORMAT
}),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(
new Cesium.Color.fromCssColorString("#00B38B")
),
},
}),
appearance : new Cesium.PolylineColorAppearance({
translucent : false
})
}));
// 获取时间
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要加1
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
// 开始时间
let start = Cesium.JulianDate.fromDate(new Date(year, month, day, hours, minutes, seconds));
// 结束时间
let stop = Cesium.JulianDate.addSeconds(start, allSeconds, new Cesium.JulianDate());
// 设置始时钟始时间
viewer.clock.startTime = start.clone();
// 设置时钟当前时间
viewer.clock.currentTime = start.clone();
// 设置始终停止时间
viewer.clock.stopTime = stop.clone();
// 时间速率,数字越大时间过的越快
viewer.clock.multiplier = 2;
// 循环执行,即为2,到达终止时间,重新从起点时间开始
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
let property = computeTrack(dataPoint, start);
let modelPath = "model/firetruck.glb";
// 添加模型
let planeModel = viewer.entities.add({
id: "firetruck",
name: "firetruck",
// 和时间轴关联
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
stop: stop
})
]),
position: property,
// 根据所提供的速度计算模型的朝向
orientation: new Cesium.VelocityOrientationProperty(property),
// 模型数据
model: {
uri: modelPath,
scale: 1.5,
minimumPixelSize: 30,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,//贴地
}
});
2.坐标点坐标、方位处理
const computeTrack = (pointList, start) => {
let property = new Cesium.SampledPositionProperty();
for (let i = 0; i < pointList.length; i++) {
let time = Cesium.JulianDate.addSeconds(
start,
pointList[i].times,
new Cesium.JulianDate()
);
let position = Cesium.Cartesian3.fromDegrees(
pointList[i].longitude,
pointList[i].latitude,
pointList[i].height
);
// 添加位置,和时间对应
property.addSample(time, position);
}
return property;
}
3.计算两个坐标点距离
const countDistance = (start, end) => {
const cartesian1 = Cesium.Cartesian3.fromDegrees(start.longitude, start.latitude, start.height);
const cartesian2 = Cesium.Cartesian3.fromDegrees(end.longitude, end.latitude, end.height);
const distance = Cesium.Cartesian3.distance(cartesian1, cartesian2);
return distance;
}