先看效果
航迹模拟-----模拟真实无人机飞行的轨迹和云台的拍摄方向,到达指定的拍摄点返回拍摄点的ID,用于显示对应拍摄点的照片或者视频
实现过程
创建一条轨迹和拍摄点
/**
* @param {*} Lines 无人机坐标点和云台的角度的坐标数组
* @memberof TrackPath
*/
TrackPath(Lines) {
var lins = [];
this.dataSource = new Cesium.CustomDataSource('TrackPath');
for (let i = 0; i < Lines.length; i++) {
let LinesIndex = new Cesium.Cartesian3.fromDegrees(Lines[i].aircraftLongitude, Lines[i].aircraftLatitude, Lines[i].aircraftAltitude);
this.dataSource.entities.add({ // 绘制拍摄点位置实体小球
position: LinesIndex,
point: {
pixelSize: 8,
color: Cesium.Color.RED
},
});
lins.push(Lines[i].aircraftLongitude);
lins.push(Lines[i].aircraftLatitude);
lins.push(Lines[i].aircraftAltitude);
}
this.dataSource.entities.add({ // 绘制线段
polyline: {
positions: new Cesium.Cartesian3.fromDegreesArrayHeights(lins),
width: 2,
material: Cesium.Color.YELLOW
}
})
this.viewer.dataSources.add(this.dataSource);
this.ChangePerspective('ViewSide');
}
复制代码
设置观看角度,并定位相关位置
/**
* 改变观看角度
* @param {*} name string
* ViewTopDown:顶视图
* ViewSide :正视图
* trackedEntity:跟随模型
* @memberof Track
*/
ChangePerspective(name) {
if (name === "ViewTopDown") {
this.viewer.trackedEntity = undefined;
this.viewer.flyTo(
this.dataSource, {
offset: {
heading: 0,
pitch: Cesium.Math.toRadians(-90),
range: 35
}
}
);
} else if (name === "ViewSide") {
this.viewer.trackedEntity = undefined;
this.viewer.flyTo(
this.dataSource, {
offset: {
heading: Cesium.Math.toRadians(-90),
pitch: Cesium.Math.toRadians(-15),
range: 50
}
}
);
} else if (name === "trackedEntity") {
this.viewer.trackedEntity = this.entity;
}
}
复制代码
调用new Track().StartFlying() 开始模拟飞行
StartFlying() {
this.property = this.ComputeRoamingLineProperty(this.Lines); // 返回每个点的时钟
this.InitRoaming(this.property.property, this.property.startTime,this.property.stopTime); // 添加无人机模型
}
复制代码
/**
* @param {*} Lines 点集合
* @returns
* @memberof ComputeRoamingLineProperty
*/
ComputeRoamingLineProperty(Lines) {
this.onTickstate = true;
let startTime = Cesium.JulianDate.fromDate(new Date()); // 创建开始时间
let stopTime;
let property = new Cesium.SampledPositionProperty(); // 利用Cesium的 SampledPositionProperty来动态控制模型的位置,达到模型沿轨迹平滑移动的目的
let startWaiting, endWaiting;
let Waiting = [];
for (let i = 0, t = 0; i < Lines.length; i++) { //通过计算出每个拍摄点的时间及停留时间
if (i == 0) {
t = 0;
} else {
let p1 = new Cesium.Cartesian3.fromDegrees(Lines[i - 1].aircraftLongitude, Lines[i - 1].aircraftLatitude, Lines[i - 1].aircraftAltitude);
let p2 = new Cesium.Cartesian3.fromDegrees(Lines[i].aircraftLongitude, Lines[i].aircraftLatitude, Lines[i].aircraftAltitude);
let d = Cesium.Cartesian3.distance(p1, p2);
t += d / this.speed;
}
let LinesIndex = new Cesium.Cartesian3.fromDegrees(Lines[i].aircraftLongitude, Lines[i].aircraftLatitude, Lines[i].aircraftAltitude);
property.addSample(Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate()), LinesIndex);
if (Lines[i].isShoot == true) {
startWaiting = Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate())
t += this.stayTime || 1;
property.addSample(Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate()), LinesIndex);
endWaiting = Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate())
Waiting.push({
startWaiting,
endWaiting,
shootId: Lines[i].shootId
})
}
if (i == Lines.length - 1) {
stopTime = Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate())
}
}
let k = true
this.viewer.clock.onTick.addEventListener((e) => { //监听时钟检测是否到达拍摄点位
if (this.onTickstate) {
let finds = false
for (let i = 0; i < Waiting.length; i++) {
if (Waiting[i].startWaiting.secondsOfDay < e.currentTime.secondsOfDay && Waiting[i].endWaiting.secondsOfDay > e.currentTime.secondsOfDay) {
if (k) {// 开关变量 避免频繁执行
this.shootCallback(Waiting[i].shootId) // 执行拍摄点回调函数
this.SetLookCone(Waiting[i].shootId) // 绘制视椎体
}
finds = true
break;
}
}
if (finds) {
k = false
} else {
k = true
}
}
})
this.viewer.clock.startTime = startTime.clone();
this.viewer.clock.stopTime = stopTime.clone();
this.viewer.clock.currentTime = startTime.clone();
this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
this.viewer.clock.multiplier = 1;
this.viewer.clock.shouldAnimate = true;
return {
property,
startTime,
stopTime
}
}
复制代码
添加模型
InitRoaming(position, start, stop) {
this.entity = this.viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start: start,
stop: stop
})]),
// 位置
position: position,
// 计算朝向
// orientation: new Cesium.VelocityOrientationProperty(position),
// 加载模型
model: {
// 模型路径
uri: "./air.glb",
// 模型最小刻度
minimumPixelSize: 64,
maximumSize: 128,
// 设置模型最大放大大小
maximumScale: 200,
// 模型是否可见
show: true,
// 模型轮廓颜色
silhouetteColor: Cesium.Color.WHITE,
// 模型颜色 ,这里可以设置颜色的变化
// color: color,
// 仅用于调试,显示魔仙绘制时的线框
debugWireframe: false,
// 仅用于调试。显示模型绘制时的边界球。
debugShowBoundingVolume: false,
scale: 0.02,
runAnimations: false // 是否运行模型中的动画效果(由于我的模型是不会动所以就很呆哈哈哈)
},
path: {
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: Cesium.Color.RED
}),
width: 10,
show: false
}
})
//
// this.viewer.trackedEntity = this.entity
}
复制代码
绘制视椎体
SetLookCone(value) {
// this.RemovePrimitives()
setTimeout(() => {
this.RemovePrimitives() //离开拍摄点 删除视椎体
}, this.stayTime * 1000)
value = this.Lines.filter(function (item) {// 过滤出是拍摄点的位置
return item.shootId == value;
});
value = value[0]
let positions = new Cesium.Cartesian3.fromDegrees(value.aircraftLongitude, value.aircraftLatitude, value.aircraftAltitude)
this.spotLightCamera = new Cesium.Camera(this.viewer.scene);
let spotLightCamera = this.spotLightCamera
spotLightCamera.setView({ // 设置视椎体的俯仰角度
destination: positions,
orientation: {
heading: Cesium.Math.toRadians(value.gimbalYawValue),
pitch: Cesium.Math.toRadians(value.gimbalPitchValue),
roll: Cesium.Math.toRadians(0.0)
}
});
let scratchRight = new Cesium.Cartesian3();
let scratchRotation = new Cesium.Matrix3();
var scratchOrientation = new Cesium.Quaternion();
let position = spotLightCamera.positionWC;
let directions = spotLightCamera.directionWC;
let up = spotLightCamera.upWC;
let right = spotLightCamera.rightWC;
right = Cesium.Cartesian3.negate(right, scratchRight);
let rotation = scratchRotation;
Cesium.Matrix3.setColumn(rotation, 0, right, rotation);
Cesium.Matrix3.setColumn(rotation, 1, up, rotation);
Cesium.Matrix3.setColumn(rotation, 2, directions, rotation);
//计算视锥姿态
let orientation = Cesium.Quaternion.fromRotationMatrix(rotation, scratchOrientation);
spotLightCamera.frustum.near = 0.1;
spotLightCamera.frustum.far = this.frustumFar;
// 视锥轮廓线图形
let instanceOutline = new Cesium.GeometryInstance({
geometry: new Cesium.FrustumGeometry({
frustum: spotLightCamera.frustum,
origin: position,
orientation: orientation
}),
material: Cesium.Color.RED.withAlpha(1),
id: "pri" + this.viewer.scene.primitives.length + 1,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 0.0, 0.5)),
show: new Cesium.ShowGeometryInstanceAttribute(true)
}
});
let instance = new Cesium.GeometryInstance({
geometry: new Cesium.FrustumOutlineGeometry({
frustum: spotLightCamera.frustum,
origin: position,
orientation: orientation
}),
material: Cesium.Color.RED.withAlpha(0.1),
id: "pri0" + this.viewer.scene.primitives.length + 1,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 0.0, 0.0, 1)),
show: new Cesium.ShowGeometryInstanceAttribute(true)
}
});
this.primitivesone = this.viewer.scene.primitives.add(new Cesium.Primitive({// 视椎体
geometryInstances: instance,
appearance: new Cesium.PerInstanceColorAppearance({
translucent: true,
flat: true
}),
asynchronous: false
}));
this.primitivestwo = this.viewer.scene.primitives.add(new Cesium.Primitive({// 轮廓
geometryInstances: instanceOutline,
appearance: new Cesium.PerInstanceColorAppearance({
translucent: true,
flat: true
}),
asynchronous: false
}));
}
复制代码
以上就是实现航迹模拟的大致过程,详细代码下面,记得点星星不要白嫖哟
代码下载地址: github.com/weshmily/ce…
记得点星星哈