效果:

核心代码:
1. 检测碰撞点云:
/**
* 判断两点之间是否碰撞了点云
* @param {
* viewer
* curPosition: Cesium.Cartesian3 起点
* nextPosition: Cesium.Cartesian3 终点
* }
*/
export const hasCollision = (viewer, curPosition, nextPosition) => {
let isCollision = false;
let { pickArr } = pickFromRay(viewer, curPosition, nextPosition);
if (pickArr && pickArr.length) {
for (let idx = 0; idx < pickArr.length; idx++) {
let primitive = pickArr[idx]?.object?.primitive;
// 拾取到点云并且位于中间位置,即碰撞了点云
if(Cesium.defined(primitive) && primitive instanceof Cesium.Cesium3DTileset && idx != pickArr.length - 1) {
isCollision = true;
}
}
}
return isCollision;
}
/**
* A点到B点的射线,并拾取物体
* @param {
* viewer
* originPoint: Cesium.Cartesian3 起点
* sourcePoint: Cesium.Cartesian3 终点
* }
*/
export const pickFromRay = (viewer, originPoint, sourcePoint, limit = 20) => {
let dir = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(sourcePoint, originPoint, new Cesium.Cartesian3()), new Cesium.Cartesian3());
let error = !(dir.x && dir.y && dir.z); //如果两个点坐标一样,则计算出来的会是NaN
if(error) {
return {
ray: null,
pickArr: []
}
}
let ray = new Cesium.Ray(originPoint, dir);
let pickArr = error ? [] : viewer.scene.drillPickFromRay(ray, limit);
return {
ray,
pickArr
}
}
2. 绘制航线:
// Vue:
// 画线
const drawPolyline = function(entityArr) {
removeEntity(['line']);
let normalColor = new Cesium.Color.fromCssColorString('#006EFF').withAlpha(.8);
let warnColor = new Cesium.Color.fromCssColorString('#F25757').withAlpha(.8);
for (let idx = 0; idx < entityArr.length; idx++) {
if(idx == 0) continue;
let curPosition = entityArr[idx].position._value;
let prePosition = entityArr[idx - 1].position._value;
/* 风险判断 */
//判断是否碰撞
let isCollision = hasCollision(viewer, curPosition, prePosition);
viewer.entities.add({
name: "line",
show: true,
polyline: {
positions: [curPosition, prePosition],
width: 3,
material: isCollision ? warnColor : normalColor,
}
})
if(entityArr[idx].name == 'wayPoint') { // 航点名
entityArr[idx].point.outlineColor = isCollision ? warnColor : normalColor;
}
}
}
//根据name移除实体
const removeEntity = (nameArr) => {
for(let i = viewer.entities.values.length - 1; i >= 0; i-- ) {
if(nameArr.includes(viewer.entities.values[i].name)) {
viewer.entities.remove(viewer.entities.values[i]);
}
}
}