CesiumJS中如何旋转墙体?设置orientation后未生效求解决
问题:CesiumJS中墙体旋转功能无法实现
我尝试通过设置orientation属性来实现墙体旋转,但不清楚问题出在哪里,恳请告知解决方法。
我的代码如下:
const coordinates1 = [103.63489648850312,29.78399543240111,103.63494150663065,29.78333590922089,103.635553885046,29.783280635414627,103.63574287140266,29.783196010558108, 103.63620765390426,29.783160361213504,103.63656871959176,29.783150670758086,103.63687253364753,29.783122359794692, 103.63703689114861,29.783125411914874,103.63722310083804,29.78321706433821,103.63729821843017,29.78323540821292, 103.63693308223041,29.783680207069843,103.63629639553365,29.78406369054707,103.635696188705 ,29.7842438403505, 103.63532376388201,29.784315674969854,103.63487784803836,29.7843448268703,103.63489648850312,29.78399543240111] let heading = Cesium.Math.toRadians(90) let pitch = Cesium.Math.toRadians(45) let roll = Cesium.Math.toRadians(45) let hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll) var center = Cesium.Cartesian3.fromDegrees(103.63722310083804,29.78321706433821) let orientation = Cesium.Transforms.headingPitchRollQuaternion(center, hpr) var maximumHeights = new Array(coordinates1.length).fill(16); var minimumHeights = new Array(coordinates1.length).fill(0); var wall = viewer.entities.add({ positions: center, orientation:orientation, wall:{ positions: Cesium.Cartesian3.fromDegreesArray(coordinates1), maximumHeights: maximumHeights, minimumHeights: minimumHeights, outline:false, material : Cesium.Color.BLUE.withAlpha(0.4), } }) console.log(wall)
原因分析
Cesium中Entity的orientation属性仅对**模型(Model)、广告牌(Billboard)、标签(Label)**等具有"朝向"属性的组件生效,Wall组件不支持通过orientation直接旋转。因为Wall的位置是基于绝对地理坐标定义的,不会继承Entity的orientation变换逻辑。
解决方法
手动将墙体的所有坐标点围绕指定中心点进行旋转变换,生成新的坐标后再赋值给Wall的positions。具体步骤如下:
- 编写坐标旋转函数,实现点围绕中心点的旋转变换;
- 将原始经纬度坐标转换为笛卡尔坐标数组;
- 对坐标数组执行旋转操作;
- 使用旋转后的坐标创建Wall。
修改后的完整代码
const coordinates1 = [103.63489648850312,29.78399543240111,103.63494150663065,29.78333590922089,103.635553885046,29.783280635414627,103.63574287140266,29.783196010558108, 103.63620765390426,29.783160361213504,103.63656871959176,29.783150670758086,103.63687253364753,29.783122359794692, 103.63703689114861,29.783125411914874,103.63722310083804,29.78321706433821,103.63729821843017,29.78323540821292, 103.63693308223041,29.783680207069843,103.63629639553365,29.78406369054707,103.635696188705 ,29.7842438403505, 103.63532376388201,29.784315674969854,103.63487784803836,29.7843448268703,103.63489648850312,29.78399543240111] // 旋转函数:将点数组围绕中心点按指定HeadingPitchRoll旋转 function rotatePointsAroundCenter(points, center, hpr) { // 根据HPR创建旋转四元数 const rotationQuaternion = Cesium.Transforms.headingPitchRollQuaternion(Cesium.Cartesian3.ZERO, hpr); const rotatedPoints = []; for (const point of points) { // 计算点相对于中心点的偏移向量 const offset = Cesium.Cartesian3.subtract(point, center, new Cesium.Cartesian3()); // 旋转偏移向量 const rotatedOffset = Cesium.Quaternion.multiplyByVector(rotationQuaternion, offset, new Cesium.Cartesian3()); // 计算旋转后的点坐标 const rotatedPoint = Cesium.Cartesian3.add(center, rotatedOffset, new Cesium.Cartesian3()); rotatedPoints.push(rotatedPoint); } return rotatedPoints; } // 配置旋转参数 let heading = Cesium.Math.toRadians(90); let pitch = Cesium.Math.toRadians(45); let roll = Cesium.Math.toRadians(45); let hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll); const center = Cesium.Cartesian3.fromDegrees(103.63722310083804,29.78321706433821); // 转换原始坐标为笛卡尔数组并旋转 const originalPositions = Cesium.Cartesian3.fromDegreesArray(coordinates1); const rotatedPositions = rotatePointsAroundCenter(originalPositions, center, hpr); // 创建墙体 const maximumHeights = new Array(originalPositions.length).fill(16); const minimumHeights = new Array(originalPositions.length).fill(0); const wall = viewer.entities.add({ wall: { positions: rotatedPositions, maximumHeights: maximumHeights, minimumHeights: minimumHeights, outline: false, material: Cesium.Color.BLUE.withAlpha(0.4), } });
关键说明
- 旋转函数通过计算每个点相对于中心点的偏移向量,对偏移向量执行旋转后再叠加回中心点,实现整体旋转效果;
- 移除了原代码中无效的
positions和orientation属性,因为它们对Wall组件不起作用; - 注意
maximumHeights和minimumHeights的长度要与旋转后的坐标数组长度一致(原代码中coordinates1是经纬度对的数组,长度是坐标点数的2倍,这里修正为与笛卡尔坐标数组长度匹配)。
内容的提问来源于stack exchange,提问作者Summer Llyed
相关产品推荐
相关产品推荐

