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>