/**
* 计算a点和b点的角度(偏行角)
* @param lng_a a点经度
* @param lat_a a点维度
* @param lng_b b点经度
* @param lat_b b点维度
* @returns 角度
*/
function courseAngle(lng_a, lat_a, lng_b, lat_b) {
//以a点为原点建立局部坐标系(东方向为x轴,北方向为y轴,垂直于地面为z轴),得到一个局部坐标到世界坐标转换的变换矩阵
var localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(lng_a, lat_a));
//求世界坐标到局部坐标的变换矩阵
var worldToLocal_Matrix = Cesium.Matrix4.inverse(localToWorld_Matrix, new Cesium.Matrix4());
//a点在局部坐标的位置,其实就是局部坐标原点
var localPosition_A = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, new Cesium.Cartesian3.fromDegrees(lng_a, lat_a), new Cesium.Cartesian3());
//B点在以A点为原点的局部的坐标位置
var localPosition_B = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, new Cesium.Cartesian3.fromDegrees(lng_b, lat_b), new Cesium.Cartesian3());
//弧度
var angle = Math.atan2((localPosition_B.y-localPosition_A.y), (localPosition_B.x-localPosition_A.x))
//角度
var theta = angle*(180/Math.PI);
if (theta < 0) {
theta = theta + 360;
}
return theta;
}
/**
* 计算a点和b点的角度(俯仰角)
* @param lng_a a点经度
* @param lat_a a点维度
* @param lng_b b点经度
* @param lat_b b点维度
* @returns 角度
*/
function coursePitchAngle(lng_a, lat_a, alt_a, lng_b, lat_b, alt_b) {
//以a点为原点建立局部坐标系(东方向为x轴,北方向为y轴,垂直于地面为z轴),得到一个局部坐标到世界坐标转换的变换矩阵
var localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(lng_a, lat_a, alt_a));
//求世界坐标到局部坐标的变换矩阵
var worldToLocal_Matrix = Cesium.Matrix4.inverse(localToWorld_Matrix, new Cesium.Matrix4());
//a点在局部坐标的位置,其实就是局部坐标原点
var localPosition_A = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, new Cesium.Cartesian3.fromDegrees(lng_a, lat_a, alt_a), new Cesium.Cartesian3());
//B点在以A点为原点的局部的坐标位置
var localPosition_B = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, new Cesium.Cartesian3.fromDegrees(lng_b, lat_b, alt_b), new Cesium.Cartesian3());
//弧度
var angle = Math.atan2((localPosition_B.z-localPosition_A.z), (localPosition_B.x-localPosition_A.x))
//角度
var theta = angle*(180/Math.PI);
if (theta < 0) {
theta = theta + 360;
}
return theta;
}
/**
* 计算a点和b点的角度(俯仰角)
* @param lng_a a点经度
* @param lat_a a点维度
* @param lng_b b点经度
* @param lat_b b点维度
* @returns 角度
*/
function coursePitchAngle(lng_a, lat_a, alt_a, lng_b, lat_b, alt_b) {
//以a点为原点建立局部坐标系(东方向为x轴,北方向为y轴,垂直于地面为z轴),得到一个局部坐标到世界坐标转换的变换矩阵
var localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(lng_a, lat_a));
//求世界坐标到局部坐标的变换矩阵
var worldToLocal_Matrix = Cesium.Matrix4.inverse(localToWorld_Matrix, new Cesium.Matrix4());
//a点在局部坐标的位置,其实就是局部坐标原点
var localPosition_A = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, new Cesium.Cartesian3.fromDegrees(lng_a, lat_a), new Cesium.Cartesian3());
//B点在以A点为原点的局部的坐标位置
var localPosition_B = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, new Cesium.Cartesian3.fromDegrees(lng_b, lat_b), new Cesium.Cartesian3());
let distance = Math.sqrt(Math.pow((localPosition_B.x-localPosition_A.x),2)+ Math.pow((localPosition_B.y-localPosition_A.y),2))
let dz = alt_b - alt_a;
var angle = 0;
if(distance != 0){
angle = Math.tanh(dz/distance);
}
var theta = angle*(180/Math.PI);
return theta;
}
/**
* 更新目标的位置及方位
*/
function updateOrientation(targetEntity){
var pathPosition = targetEntity.pathPosition;
// 前一个坐标点
var preIndex = 0;
if(pathPosition.length > 1){
preIndex = pathPosition.length-2;
}
var prevPosition = Cesium.Cartesian3.fromDegrees(pathPosition[preIndex][0], pathPosition[preIndex][1], pathPosition[preIndex][2]);
// 当前坐标点
var currentIndex = pathPosition.length-1;
var currentPosition = Cesium.Cartesian3.fromDegrees(pathPosition[currentIndex][0], pathPosition[currentIndex][1], pathPosition[currentIndex][2]);
// 计算a点和b点的角度(偏行角)
var angle = courseAngle(pathPosition[preIndex][0], pathPosition[preIndex][1],pathPosition[currentIndex][0], pathPosition[currentIndex][1]);
angle = 360 - Number(angle.toFixed(0));
// 计算a点和b点的角度(俯仰角)
var pitchAngle = coursePitchAngle(pathPosition[currentIndex][0], pathPosition[currentIndex][1], pathPosition[currentIndex][2], pathPosition[preIndex][0], pathPosition[preIndex][1], pathPosition[preIndex][2]);
pitchAngle = Number(pitchAngle.toFixed(0));
if(pitchAngle > 180){
pitchAngle = 360 - pitchAngle;
}else{
pitchAngle = 180 + pitchAngle;
}
// 根据“俯仰角、偏行角、滚转角”得到目标方位
var gheading = Cesium.Math.toRadians(angle);
var gpitch = Cesium.Math.toRadians(pitchAngle);
var groll = Cesium.Math.toRadians(0);
var hpr = new Cesium.HeadingPitchRoll(gheading, gpitch, groll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(prevPosition, hpr);
targetEntity.orientation = orientation;
}
// 计算四元数
var _angle = targetEntity.orientation.getValue(viewer.clock.currentTime);
// 计算旋转角(弧度)
var hpr = Cesium.HeadingPitchRoll.fromQuaternion(_angle);
// 得到角度
var heading = Cesium.Math.toDegrees(hpr.heading);
var pitch = Cesium.Math.toDegrees(hpr.pitch);
var roll = Cesium.Math.toDegrees(hpr.roll);
console.log('heading : ' + heading, 'pitch : ' + pitch, 'roll : ' + roll);
注: