Cesium 比较常用的几个方法
根据经纬度获取高程
/**
* 根据经纬度获取高程
* @param { mars3d.Map } map
* @param {number} lng
* @param {number} lat
*/
async function getHeightByLngLat(map, lng, lat) {
if (!lng || !lat) return undefined;
let positions = [
Cesium.Cartographic.fromDegrees(lng, lat)
];
await Cesium.sampleTerrainMostDetailed(map.viewer.terrainProvider, positions).catch(err => {
console.info("根据经纬度获取高程异常", err);
});
return positions[0].height;
}
方法二:
/**
* 根据经纬度获取高程
* @param { mars3d.Map } map
* @param {number} lng
* @param {number} lat
*/
async function getHeightByLngLat2(map, lng, lat) {
if (!lng || !lat) return undefined;
let positions = [
Cesium.Cartographic.fromDegrees(lng, lat)
];
await map.viewer.scene.sampleHeightMostDetailed(positions).catch(err => {
console.info("根据经纬度获取高程异常", err);
});
return positions[0].height;
}
拾取经纬度
/**
* 拾取经纬度
* @param { Cesium.Cartesian3 } position
* @param { mars3d.Map } map
* @returns
*/
function pickLngLat(position, map) {
let cartesian = map.viewer.camera.pickEllipsoid(
position,
map.viewer.scene.globe.ellipsoid
);
if (!cartesian) return undefined;
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
let lng = Cesium.Math.toDegrees(cartographic.longitude);
let lat = Cesium.Math.toDegrees(cartographic.latitude);
return { lng, lat };
}
根据经纬度、方向、距离,计算另一个点的经纬度坐标
/**
* 根据经纬度、方向、距离,计算另一个点的经纬度坐标
* @param { number } lng 经度
* @param { number } lat 纬度
* @param { number } angle 方向角度
* @param { number } length 距离(单位:米)
* @returns
*/
function getNextPosition(lng, lat, angle, length) {
let cartesian3 = Cesium.Cartesian3.fromDegrees(lng, lat);
let transform = Cesium.Transforms.eastNorthUpToFixedFrame(cartesian3);
let matrix3 = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(angle || 0));
let rotationZ = Cesium.Matrix4.fromRotationTranslation(matrix3);
Cesium.Matrix4.multiply(transform, rotationZ, transform);
let result = Cesium.Matrix4.multiplyByPoint(transform, new Cesium.Cartesian3(0, length, 0), new Cesium.Cartesian3());
return result;
}
世界坐标转经纬度
/**
* 世界坐标转经纬度
* @param { mars3d.Map } map
* @param { Cesium.Cartesian3 } cartesian3
*/
function toDegrees(map, cartesian3) {
// 世界坐标转换为弧度
let ellipsoid = map.scene.globe.ellipsoid;
let cartographic = ellipsoid.cartesianToCartographic(cartesian3);
// 弧度转换为经纬度
let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
let alt = cartographic.height; // 高度
return { lng, lat, alt }
}
计算经纬度直线距离
/**
* 计算经纬度直线距离(单位:米)
* @param { { lng:number, lat:number } } position1 位置1
* @param { { lng:number, lat:number } } position2 位置2
* @returns { number } 距离(单位:米)
*/
function calcDistance(position1, position2) {
let from = turf.point([position1.lng, position1.lat]);
let to = turf.point([position2.lng, position2.lat]);
let options = { units: 'kilometers' };
let distance = turf.distance(from, to, options);
return distance * 1000;
}
二分查找并计算position
根据航迹数据(时间点和坐标信息集合),查找某个时间点对应的坐标。
/**
* 二分查找并计算position
* @param { dayjs } time 时间
* @param { [{ time:string, lng:number, lat:number, height:number }] } positions 坐标集合
* @returns { { time:string, lng:number, lat:number, height:number } }
*/
function findPosition(time, positions) {
let left = 0;
let right = positions.length - 1;
let leftPosition = positions[left];
let rightPosition = positions[right];
let leftTime = string2Dayjs(leftPosition.time);
let rightTime = string2Dayjs(rightPosition.time);
if (time.valueOf() < leftTime.valueOf() || time.valueOf() > rightTime.valueOf()) {
return undefined;
}
while (left <= right) {
let middle = Math.floor((left + right) / 2);
let middlePosition = positions[middle];
let middleTime = string2Dayjs(middlePosition.time);
let heading = undefined;
let pitch = undefined;
let roll = undefined;
if (time.valueOf() === leftTime.valueOf()) {
return leftPosition;
} else if (time.valueOf() === middleTime.valueOf()) {
return middlePosition;
}
else if (time.valueOf() === rightTime.valueOf()) {
return rightPosition;
}
else {
if (time.valueOf() < middleTime.valueOf()) {
right = middle;
rightPosition = positions[right];
rightTime = string2Dayjs(rightPosition.time);
} else {
left = middle;
leftPosition = positions[left];
leftTime = string2Dayjs(leftPosition.time);
}
if (right - left == 1) {
let ratio = (time.valueOf() - leftTime.valueOf()) / (rightTime.valueOf() - leftTime.valueOf());
let lng = leftPosition.lng + (rightPosition.lng - leftPosition.lng) * ratio;
let lat = leftPosition.lat + (rightPosition.lat - leftPosition.lat) * ratio;
let height = leftPosition.height + (rightPosition.height - leftPosition.height) * ratio;
if (leftPosition.heading && rightPosition.heading) {
heading = leftPosition.heading + (rightPosition.heading - leftPosition.heading) * ratio;
}
if (leftPosition.pitch && rightPosition.pitch) {
pitch = leftPosition.pitch + (rightPosition.pitch - leftPosition.pitch) * ratio;
}
if (leftPosition.roll && rightPosition.roll) {
roll = leftPosition.roll + (rightPosition.roll - leftPosition.roll) * ratio;
}
// 计算速度
let distance = calcDistance({ lng: leftPosition.lng, lat: leftPosition.lat }, { lng: rightPosition.lng, lat: rightPosition.lat });
let deltaTime = (rightTime.valueOf() - leftTime.valueOf()) / 1000;
let speed = distance / deltaTime;
return {
time: time.format('YYYY-MM-DD HH:mm:ss.SSS'),
lng,
lat,
height,
heading,
pitch,
roll,
speed,
}
} else if (right - left == 0) {
return undefined;
}
}
}
}