cesium 给与中心点 和 长宽绘制矩形

let rectangleEntity = null;

// 绘制矩形函数
function drawRectangle(centerLongitude,centerLatitude,length,width) {
    // 获取输入参数
    // const centerLongitude = parseFloat(document.getElementById('longitude').value);
    // const centerLatitude = parseFloat(document.getElementById('latitude').value);
    // const length = parseFloat(document.getElementById('length').value);
    // const width = parseFloat(document.getElementById('width').value);
    
    // 清除现有矩形
    if (rectangleEntity) {
        viewer.entities.remove(rectangleEntity);
    }
    
    // 计算矩形坐标
    const center = Cesium.Cartesian3.fromDegrees(centerLongitude, centerLatitude);
    const rectangle = calculateRectangle(center, length, width);
    
    // 创建矩形实体
    rectangleEntity = viewer.entities.add({
        rectangle: {
            coordinates: rectangle,
            material: Cesium.Color.RED,
            outline: true,
            outlineColor: Cesium.Color.RED,
            classificationType: Cesium.ClassificationType.BOTH,
            // height: 100,
            classificationType: Cesium.ClassificationType.TERRAIN
        }
    });
    
    // 飞向矩形区域
    viewer.flyTo(rectangleEntity);
}

// 计算矩形坐标函数
function calculateRectangle(center, length, width) {
    // 将笛卡尔坐标转换为经纬度
    const centerCartographic = Cesium.Cartographic.fromCartesian(center);
    const centerLongitude = Cesium.Math.toDegrees(centerCartographic.longitude);
    const centerLatitude = Cesium.Math.toDegrees(centerCartographic.latitude);
    
    // 计算半长和半宽(转换为度数)
    const semiLength = length / 2;
    const semiWidth = width / 2;
    
    // 计算经度方向的偏移(考虑纬度对距离的影响)
    const longitudeOffset = semiLength / (Cesium.Ellipsoid.WGS84.maximumRadius * 
        Math.cos(centerCartographic.latitude));
    
    // 计算纬度方向的偏移
    const latitudeOffset = semiWidth / Cesium.Ellipsoid.WGS84.maximumRadius;
    
    // 转换为度数
    const longitudeOffsetDeg = Cesium.Math.toDegrees(longitudeOffset);
    const latitudeOffsetDeg = Cesium.Math.toDegrees(latitudeOffset);
    
    // 返回矩形坐标
    return Cesium.Rectangle.fromDegrees(
        centerLongitude - longitudeOffsetDeg,
        centerLatitude - latitudeOffsetDeg,
        centerLongitude + longitudeOffsetDeg,
        centerLatitude + latitudeOffsetDeg
    );
}
drawRectangle(114,30,1000,1000)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cesium 可旋转矩形</title>
    <script src="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Cesium.js"></script>
    <link href="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
    <style>
        #cesiumContainer {
            width: 100%;
            height: 100vh;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
        .control-panel {
            position: absolute;
            top: 10px;
            left: 10px;
            background: rgba(42, 42, 42, 0.9);
            padding: 15px;
            border-radius: 8px;
            z-index: 1000;
            color: white;
            width: 300px;
        }
        .control-group {
            margin: 10px 0;
        }
        label {
            display: block;
            margin: 5px 0;
            font-weight: bold;
        }
        input, button {
            margin: 5px 0;
            padding: 8px;
            width: 100%;
            box-sizing: border-box;
        }
        button {
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-weight: bold;
        }
        button:hover {
            background: #45a049;
        }
        #clearAll {
            background: #f44336;
        }
        #clearAll:hover {
            background: #da190b;
        }
        .slider-container {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .slider-value {
            min-width: 40px;
            text-align: center;
            background: #555;
            padding: 4px;
            border-radius: 4px;
        }
    </style>
</head>
<body>
    <div id="cesiumContainer"></div>
    <div class="control-panel">
        <h3>矩形参数控制</h3>

        <div class="control-group">
            <label>中心经度: </label>
            <input type="number" id="longitude" value="116.39" step="0.0001">
        </div>

        <div class="control-group">
            <label>中心纬度: </label>
            <input type="number" id="latitude" value="39.91" step="0.0001">
        </div>

        <div class="control-group">
            <label>长度(米): </label>
            <input type="number" id="length" value="5000">
        </div>

        <div class="control-group">
            <label>宽度(米): </label>
            <input type="number" id="width" value="3000">
        </div>

        <div class="control-group">
            <label>旋转角度(度): </label>
            <div class="slider-container">
                <input type="range" id="rotation" min="0" max="360" value="30" step="1">
                <span class="slider-value" id="rotationValue">30°</span>
            </div>
        </div>

        <div class="control-group">
            <button id="drawRectangle">绘制矩形</button>
            <button id="clearAll">清除矩形</button>
        </div>
    </div>

    <script>
        // 初始化Cesium Viewer
        Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI4YzZlOWI5ZC00YzZmLTQyYzItYmI4OS1lMTg0YmE0N2Q4MmMiLCJpZCI6MjgzMTExLCJpYXQiOjE3NDE2NjI2ODh9.NVF4Fvb98Kj7FoLhmGDK1kvXNVCuMTxjCop7onYihUc';
        const viewer = new Cesium.Viewer('cesiumContainer', {
            terrainProvider: Cesium.createWorldTerrain(),
            animation: false,
            timeline: false,
            homeButton: false,
            geocoder: false,
            baseLayerPicker: false,
            navigationHelpButton: false
        });

        // 存储当前矩形实体
        let rectangleEntity = null;

        // 更新旋转角度显示
        document.getElementById('rotation').addEventListener('input', function(e) {
            document.getElementById('rotationValue').textContent = e.target.value + '°';
        });

        // 绘制矩形函数
        function drawRectangle() {
            // 获取输入参数
            const centerLongitude = parseFloat(document.getElementById('longitude').value);
            const centerLatitude = parseFloat(document.getElementById('latitude').value);
            const length = parseFloat(document.getElementById('length').value);
            const width = parseFloat(document.getElementById('width').value);
            const rotationDegrees = parseFloat(document.getElementById('rotation').value);

            // 清除现有矩形
            // if (rectangleEntity) {
            //     viewer.entities.remove(rectangleEntity);
            // }

            // 创建旋转矩形
            createRotatedRectangle(centerLongitude, centerLatitude, length, width, rotationDegrees);

            // 飞向矩形区域
            if (rectangleEntity) {
                viewer.flyTo(rectangleEntity);
            }
        }

        // 创建旋转矩形
        function createRotatedRectangle(centerLon, centerLat, length, width, rotationDegrees) {
            const center = Cesium.Cartesian3.fromDegrees(centerLon, centerLat);
            const rotation = Cesium.Math.toRadians(rotationDegrees);

            // 计算半长和半宽
            const halfLength = length / 2;
            const halfWidth = width / 2;

            // 定义矩形的四个角点(在局部坐标系中)
            const corners = [
                new Cesium.Cartesian3(-halfLength, -halfWidth, 0), // 左下
                new Cesium.Cartesian3(halfLength, -halfWidth, 0),  // 右下
                new Cesium.Cartesian3(halfLength, halfWidth, 0),   // 右上
                new Cesium.Cartesian3(-halfLength, halfWidth, 0)    // 左上
            ];

            // 创建旋转矩阵
            const rotationMatrix = Cesium.Matrix3.fromRotationZ(rotation);

            // 旋转角点
            const rotatedCorners = corners.map(corner => {
                return Cesium.Matrix3.multiplyByVector(rotationMatrix, corner, new Cesium.Cartesian3());
            });

            // 将角点转换为世界坐标
            const enuToFixedFrame = Cesium.Transforms.eastNorthUpToFixedFrame(center);
            const worldPositions = rotatedCorners.map(corner => {
                return Cesium.Matrix4.multiplyByPoint(enuToFixedFrame, corner, new Cesium.Cartesian3());
            });

            // 提取经纬度坐标
            const cartographicPositions = worldPositions.map(pos => {
                return Cesium.Cartographic.fromCartesian(pos);
            });
            if(rectangleEntity){
                rectangleEntity.polygon.hierarchy=new Cesium.PolygonHierarchy(
                        cartographicPositions.map(cartographic => {
                            return Cesium.Cartesian3.fromRadians(
                                cartographic.longitude,
                                cartographic.latitude,
                                cartographic.height
                            );
                        })
                    );
                return
            }
            // 创建多边形实体
            rectangleEntity = viewer.entities.add({
                polygon: {
                    hierarchy: new Cesium.PolygonHierarchy(
                        cartographicPositions.map(cartographic => {
                            return Cesium.Cartesian3.fromRadians(
                                cartographic.longitude,
                                cartographic.latitude,
                                cartographic.height
                            );
                        })
                    ),
                    material: Cesium.Color.RED.withAlpha(0.6),
                    outline: true,
                    outlineColor: Cesium.Color.RED,
                    outlineWidth: 3,
                    height: 0,
                    classificationType: Cesium.ClassificationType.TERRAIN
                },
                label: {
                    text: `旋转角度: ${rotationDegrees}°`,
                    show: true,
                    font: '14pt monospace',
                    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                    outlineWidth: 2,
                    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                    pixelOffset: new Cesium.Cartesian2(0, -20)
                }
            });

            // 添加中心点标记
            viewer.entities.add({
                position: center,
                point: {
                    pixelSize: 10,
                    color: Cesium.Color.YELLOW,
                    outlineColor: Cesium.Color.BLACK,
                    outlineWidth: 2
                },
                label: {
                    text: '中心点',
                    show: true,
                    font: '12pt monospace',
                    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                    outlineWidth: 2,
                    pixelOffset: new Cesium.Cartesian2(0, 15)
                }
            });
        }

        // 清除所有图形
        function clearAll() {
            if (rectangleEntity) {
                viewer.entities.remove(rectangleEntity);
                rectangleEntity = null;
            }
            // 清除所有实体(包括中心点)
            viewer.entities.removeAll();
        }

        // 添加事件监听器
        document.getElementById('drawRectangle').addEventListener('click', drawRectangle);
        document.getElementById('clearAll').addEventListener('click', clearAll);

        // 初始绘制一个矩形
        drawRectangle();
    </script>
</body>
</html>
posted @ 2025-08-23 13:11  7c89  阅读(36)  评论(0)    收藏  举报