cesium吧 关注:176贴子:377
  • 0回复贴,共1

求助大佬,俯仰旋转用两种方法算都有问题

只看楼主收藏回复

这是开源代码加了一点修改
# 这是用点转换坐标根据球公式计算xyz相对坐标算的。
// 创建平面扇形函数,添加俯仰旋转
function createHorizontalSector(center, radius, startAngle, endAngle, pitchAngle, granularity = Cesium.Math.RADIANS_PER_DEGREE) {
const positions = [];
const centerCartesian = Cesium.Cartesian3.fromDegrees(center.longitude, center.latitude, center.height);
const pitch = Cesium.Math.toRadians(pitchAngle);
positions.push(centerCartesian);
for (let angle = startAngle; angle <= endAngle; angle += Cesium.Math.toDegrees(granularity)) {
const radians = Cesium.Math.toRadians(angle);
const delta_x = radius * Math.cos(radians) * Math.cos(pitch);
const delta_y = radius * Math.sin(radians) * Math.cos(pitch);
const delta_z = radius * Math.sin(pitch);
// 计算每个点的投影位置
const position = new Cesium.Cartesian3(centerCartesian.x + delta_x, centerCartesian.y + delta_y, centerCartesian.z + delta_z);
// 计算俯仰旋转后的新的点
const geodetic = Cesium.Cartographic.fromCartesian(position);
const finalPosition = Cesium.Cartesian3.fromRadians(geodetic.longitude, geodetic.latitude , geodetic.height);
positions.push(finalPosition);
}
positions.push(centerCartesian); // 连接到中心点,形成扇形
return positions;
}
# 这是根据三个角转换算的
// 计算每个点的heading、pitch和roll
function applyRotation(positions, center, pitchAngle) {
const pitch = Cesium.Math.toRadians(pitchAngle);
const centerCartesian = Cesium.Cartesian3.fromDegrees(center.longitude, center.latitude, center.height);
return positions.map(position => {
// 计算每个点相对于中心点的方位角(heading)和距离
const heading = Math.atan2(position.y - centerCartesian.y, position.x - centerCartesian.x);
const distance = Cesium.Cartesian3.distance(centerCartesian, position);
// 计算旋转后的新的点
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, 0);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(centerCartesian, hpr);
const rotationMatrix = Cesium.Matrix3.fromQuaternion(orientation);
const translatedPosition = Cesium.Cartesian3.subtract(position, centerCartesian, new Cesium.Cartesian3());
const rotatedPosition = Cesium.Matrix3.multiplyByVector(rotationMatrix, translatedPosition, new Cesium.Cartesian3());
return Cesium.Cartesian3.add(rotatedPosition, centerCartesian, new Cesium.Cartesian3());
});
}
# 这是完整代码
<!--********************************************************************
* by jiawanlong
*********************************************************************-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="./../../cesium/Cesium1.98/Widgets/widgets.css" />
<script type="text/javascript" src="./../../cesium/Cesium1.98/Cesium.js"></script>
</head>
<body style="
margin: 0;
overflow: hidden;
background: #fff;
width: 100%;
height: 100%;
position: absolute;
top: 0;
">
<div id="map" style="margin: 0 auto; width: 100%; height: 100%"></div>
<!-- ./video.mp4 -->
<script type="text/javascript">
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3ZjQ5ZGUzNC1jNWYwLTQ1ZTMtYmNjYS05YTY4ZTVmN2I2MDkiLCJpZCI6MTE3MTM4LCJpYXQiOjE2NzY0NDUyODB9.ZaNSBIfc1sGLhQd_xqhiSsc0yr8oS0wt1hAo9gbke6M";
const viewer = new Cesium.Viewer("map", {});
viewer.scene.debugShowFramesPerSecond = true;
viewer.scene.globe.depthTestAgainstTerrain = true;
// 地图视野定位
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(113, 30, 3000),
});
// 创建平面扇形函数,添加俯仰旋转
function createHorizontalSector(center, radius, startAngle, endAngle, pitchAngle, granularity = Cesium.Math.RADIANS_PER_DEGREE) {
const positions = [];
const centerCartesian = Cesium.Cartesian3.fromDegrees(center.longitude, center.latitude, center.height);
const pitch = Cesium.Math.toRadians(pitchAngle);
positions.push(centerCartesian);
for (let angle = startAngle; angle <= endAngle; angle += Cesium.Math.toDegrees(granularity)) {
const radians = Cesium.Math.toRadians(angle);
const x = radius * Math.cos(radians);
const y = radius * Math.sin(radians);
const delta_x = radius * Math.cos(radians) * Math.cos(pitch);
const delta_y = radius * Math.sin(radians) * Math.cos(pitch);
const delta_z = radius * Math.sin(pitch);
// 计算每个点的投影位置
const position = new Cesium.Cartesian3(centerCartesian.x + delta_x, centerCartesian.y + delta_y, centerCartesian.z + delta_z);
// 计算俯仰旋转后的新的点
const geodetic = Cesium.Cartographic.fromCartesian(position);
const finalPosition = Cesium.Cartesian3.fromRadians(geodetic.longitude, geodetic.latitude , geodetic.height);
positions.push(finalPosition);
}
positions.push(centerCartesian); // 连接到中心点,形成扇形
return positions;
}
// 应用旋转
// 计算每个点的heading、pitch和roll
function applyRotation(positions, center, pitchAngle) {
const pitch = Cesium.Math.toRadians(pitchAngle);
const centerCartesian = Cesium.Cartesian3.fromDegrees(center.longitude, center.latitude, center.height);
return positions.map(position => {
// 计算每个点相对于中心点的方位角(heading)和距离
const heading = Math.atan2(position.y - centerCartesian.y, position.x - centerCartesian.x);
const distance = Cesium.Cartesian3.distance(centerCartesian, position);
// 计算旋转后的新的点
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, 0);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(centerCartesian, hpr);
const rotationMatrix = Cesium.Matrix3.fromQuaternion(orientation);
const translatedPosition = Cesium.Cartesian3.subtract(position, centerCartesian, new Cesium.Cartesian3());
const rotatedPosition = Cesium.Matrix3.multiplyByVector(rotationMatrix, translatedPosition, new Cesium.Cartesian3());
return Cesium.Cartesian3.add(rotatedPosition, centerCartesian, new Cesium.Cartesian3());
});
}
// 创建动态材质的回调函数
function createDynamicMaterial() {
return new Cesium.ColorMaterialProperty(
new Cesium.CallbackProperty(function(time, result) {
const t = Cesium.JulianDate.secondsDifference(time, Cesium.JulianDate.fromDate(new Date(2024, 0, 1)));
const cycleTime = 4; // 4秒的周期
const normalizedTime = (t % cycleTime) / cycleTime;
const alpha = 0.1 + 0.9 * Math.abs(Math.sin(normalizedTime * Math.PI)); // 使用正弦函数并确保最小透明度为0.1
console.log(`Normalized Time: ${normalizedTime}, Alpha: ${alpha}`);
return Cesium.Color.fromBytes(173, 216, 230, alpha * 255); // 浅蓝色
}, false)
);
}
// 计算扇形的顶点
const center = { longitude: 113, latitude: 30, height: 1000 };
const radius = 1500.0;
const startAngle = 0;
const endAngle = 60;
// 创建平面扇形
let flatPositions = createHorizontalSector(center, radius, startAngle, endAngle,30);
// flatPositions = applyRotation(flatPositions, center, 60);
// 创建带俯仰角的扇形
let tiltedPositions = createHorizontalSector(center, radius, startAngle, endAngle,0);
// tiltedPositions = applyRotation(tiltedPositions, center, 30);
// 创建一个动态材质
const dynamicMaterial = createDynamicMaterial();
// 连接两个扇形的对应顶点
const leftLinePositions = [flatPositions[1], tiltedPositions[1]]; // 连接左边缘顶点
const rightLinePositions = [flatPositions[flatPositions.length - 2], tiltedPositions[tiltedPositions.length - 2]]; // 连接右边缘顶点
// 添加左边缘线条
viewer.entities.add({
polyline: {
positions: leftLinePositions,
width: 2,
material: dynamicMaterial
}
});
// 添加右边缘线条
viewer.entities.add({
polyline: {
positions: rightLinePositions,
width: 2,
material: dynamicMaterial
}
});
// 添加平面扇形的线条
viewer.entities.add({
polyline: {
positions: flatPositions,
width: 2,
material: dynamicMaterial
}
});
// 添加带俯仰角的扇形的线条
viewer.entities.add({
polyline: {
positions: tiltedPositions,
width: 2,
material: dynamicMaterial
}
});
// Function to create an axis line
function createAxis(viewer, start, end, color) {
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights([start.longitude, start.latitude, start.height, end.longitude, end.latitude, end.height]),
width: 2,
material: color
}
});
}
// Define the origin and axis endpoints
var origin = { longitude: 113, latitude: 30, height: 100 };
var xAxisEnd = { longitude: 112.9, latitude: 30, height: 100 };
var yAxisEnd = { longitude: 113, latitude: 30.1, height: 100 };
var zAxisEnd = { longitude: 113, latitude: 30, height: 1000 };
// Create the X, Y, Z axes
createAxis(viewer, origin, xAxisEnd, Cesium.Color.RED);
createAxis(viewer, origin, yAxisEnd, Cesium.Color.GREEN);
createAxis(viewer, origin, zAxisEnd, Cesium.Color.BLUE);
// Zoom to the origin
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(origin.longitude, origin.latitude, 5000)
});
// 将视角移动到扇形位置
viewer.zoomTo(viewer.scene.primitives);
</script>
</body>
</html>


IP属地:广东1楼2024-08-14 19:21回复