Cesium 比較常用的幾個方法

0611163發表於2024-09-15

根據經緯度獲取高程

/**
 * 根據經緯度獲取高程
 * @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;
            }
        }
    }
}

相關文章