Cesium.js使用多边形裁剪3DTile遇渲染停止错误,求助
Cesium 3DTile多边形裁剪报错解决
报错原因分析
你遇到的TypeError: Cannot read properties of undefined (reading '_target')主要由代码中的拼写错误、坐标格式错误及矩阵处理逻辑问题导致,以下是具体修正方案:
代码修正点
1. 修复函数名拼写错误
原代码中functi createClippingPlanes少写了字母o,正确函数名应为function createClippingPlanes,否则函数无法被正确调用。
2. 修正Matrix4常量拼写错误
Cesium中单位矩阵的正确常量是Cesium.Matrix4.IDENTITY,而非IDENTIFY,拼写错误会导致矩阵比较逻辑失效,进而引发transform初始化错误。
3. 修正变量名拼写错误
const martrix4 = new Cesium.Matrix4()中的martrix4应为matrix4,虽然变量名不影响运行,但保持规范可避免后续维护问题。
4. 确保输入坐标为Cartesian3格式
coordinatesDegrees是经纬度坐标的话,需要先转换为Cesium的Cartesian3坐标再传入函数,否则Matrix4.multiplyByPoint无法正确处理:
// 转换经纬度数组为Cartesian3数组 const coordinatesCartesian = coordinatesDegrees.map(coord => { return Cesium.Cartesian3.fromDegrees(coord.lon, coord.lat, coord.height || 0); }); // 再调用函数 tileset.clippingPlanes = createClippingPlanes(Cesium, coordinatesCartesian, tileset);
5. 修正裁剪平面法线方向(可选)
原代码中使用固定up = new Cesium.Cartesian3(0, 0, 10)计算法线,可能导致裁剪方向不符合预期,建议调整叉乘顺序确保法线朝向要保留的区域:
// 调整叉乘顺序,确保法线朝向正确 const normal = Cesium.Cartesian3.cross(up, right, new Cesium.Cartesian3());
完整修正后的代码
function getInverseTransform(Cesium, tileset) { let transform; const tmp = tileset.root.transform; // 修正IDENTITY拼写 if ((tmp && tmp.equals(Cesium.Matrix4.IDENTITY)) || !tmp) { const center = tileset.boundingSphere.center; transform = Cesium.Transforms.eastNorthUpToFixedFrame(center); } else { transform = Cesium.Matrix4.fromArray(tileset.root.transform); } // 修正变量名拼写 const matrix4 = new Cesium.Matrix4(); return Cesium.Matrix4.inverseTransformation(transform, matrix4); } // 修正函数名拼写 function createClippingPlanes(Cesium, positions, tileset) { const clippingPlanes = []; const inverseTransform = getInverseTransform(Cesium, tileset); const length = positions.length; for (let i = 0; i < length; i++) { const nextIndex = (i + 1) % length; const next = Cesium.Matrix4.multiplyByPoint(inverseTransform, positions[nextIndex], new Cesium.Cartesian3()); const now = Cesium.Matrix4.multiplyByPoint(inverseTransform, positions[i], new Cesium.Cartesian3()); const up = new Cesium.Cartesian3(0, 0, 10); let right = Cesium.Cartesian3.subtract(next, now, new Cesium.Cartesian3()); right = Cesium.Cartesian3.normalize(right, right); // 调整叉乘顺序确保法线方向正确 const normal = Cesium.Cartesian3.cross(up, right, new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(normal, normal); const planeTmp = Cesium.Plane.fromPointNormal(now, normal); const clipPlane = Cesium.ClippingPlane.fromPlane(planeTmp); clippingPlanes.push(clipPlane); } const clipPlanes = new Cesium.ClippingPlaneCollection({ planes: clippingPlanes, edgeWidth: 1, edgeColor: Cesium.Color.white, enabled: true }); return clipPlanes; }
额外注意事项
- 确保
tileset已正确加载完成后再设置clippingPlanes,可通过tileset.readyPromise等待加载完成:
tileset.readyPromise.then(() => { const coordinatesCartesian = coordinatesDegrees.map(coord => Cesium.Cartesian3.fromDegrees(coord.lon, coord.lat)); tileset.clippingPlanes = createClippingPlanes(Cesium, coordinatesCartesian, tileset); });
- 若3DTile有自定义变换,需确保
getInverseTransform逻辑正确处理了tileset的根变换。
内容的提问来源于stack exchange,提问作者mmc19
相关产品推荐
相关产品推荐

