PolygonGeometry+Primitive+PerInstanceColorAppearance专门渲染MULTIPOLYGON Z 带逐点高程三维空间面(当前项目当前使用) 区分:
PolygonGeometry:三维空间面,支持perPositionHeight:true,每个顶点独立 Z 高程 ✅GroundPolygonGeometry:贴地面,丢弃顶点高程,强制贴地形,不能用在 MultiPolygon‑Z 数据❌
一、核心 API 说明
PolygonGeometry 参数
const fillGeo = new Cesium.PolygonGeometry({ polygonHierarchy: hierarchy, // 多边形层级:外环 + 内环(洞) perPositionHeight: true, // ✅开启逐点高程,MULTIPOLYGON‑Z必须打开 vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT });polygonHierarchy:PolygonHierarchy(外环Cartesian3[], 内环洞数组),支持挖洞perPositionHeight:true:每个顶点使用自身 Cartesian3 的高度,形成起伏三维面vertexFormat:使用PerInstanceColorAppearance必须配套这个顶点格式
GeometryInstance(实现每个面不同颜色)
new Cesium.GeometryInstance({ geometry: fillGeo, id: item.id, //拾取ID attributes: { // 每个实例独立颜色 color: Cesium.ColorGeometryInstanceAttribute.fromColor(fillColor) } })Primitive + PerInstanceColorAppearance
const prim = new Cesium.Primitive({ geometryInstances: instances, appearance: new Cesium.PerInstanceColorAppearance({ translucent: true, //支持透明度 closed: true //几何体闭合 }), asynchronous: true });⚠️重要限制
PerInstanceColorAppearance不支持 depthFailAppearance,面被地形埋住直接看不见,不能切换地下材质- 如果需要被遮挡也可见:
prim.depthTestEnabled = false;关闭深度测试(会浮在最上层,牺牲三维真实感) - 依靠
attributes.color,实现同一个 Primitive 里面多个面各自不同颜色。
| 属性 | 说明 |
|---|---|
| geometryInstances | GeometryInstance 数组,一个面 = 一个实例 |
| appearance | PerInstanceColorAppearance,支持实例独立颜色 |
| asynchronous | true 异步构建几何体,大数据不阻塞页面 |
| prim.depthTestEnabled | true 开启深度测试;false 关闭,永远显示在顶层 |
二、基础完整示例(单一个三维面,带洞)
// 1.外环顶点,带高程Z const outerRing = [ Cesium.Cartesian3.fromDegrees(102.48, 24.70, 1600), Cesium.Cartesian3.fromDegrees(102.49, 24.71, 1620), Cesium.Cartesian3.fromDegrees(102.50, 24.70, 1580), Cesium.Cartesian3.fromDegrees(102.48, 24.70, 1600), // 闭合,首尾相同 ]; // 2.内环(挖洞,可选) const holeRing = [ Cesium.Cartesian3.fromDegrees(102.485, 24.703, 1605), Cesium.Cartesian3.fromDegrees(102.488, 24.706, 1610), Cesium.Cartesian3.fromDegrees(102.486, 24.702, 1602), Cesium.Cartesian3.fromDegrees(102.485, 24.703, 1605), ]; // 3.构建层级,外环 + 多个内环洞 const hierarchy = new Cesium.PolygonHierarchy(outerRing, [ new Cesium.PolygonHierarchy(holeRing) ]); // 4.生成几何体,开启逐点高程 const polygonGeo = new Cesium.PolygonGeometry({ polygonHierarchy: hierarchy, perPositionHeight: true, vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }); // 5.包装实例,设置本面颜色 const instance = new Cesium.GeometryInstance({ geometry: polygonGeo, id: "poly_001", attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE.withAlpha(0.35)) } }); // 6.创建Primitive const prim = new Cesium.Primitive({ geometryInstances: instance, appearance: new Cesium.PerInstanceColorAppearance({ translucent: true, closed: true }), asynchronous: true }); // 如果需要被地形遮挡也可见,打开下面 // prim.depthTestEnabled = false; this.viewer.scene.primitives.add(prim);三、批量渲染(多面,你项目 MULTIPOLYGON Z 逻辑)
const tempFillInstances: Cesium.GeometryInstance[] = []; // wktGeo.coordinates MULTIPOLYGON‑Z结构 wktGeo.coordinates.forEach((polygonParts: number[][][]) => { if (!Array.isArray(polygonParts) || polygonParts.length === 0) return; // polygonParts[0] = 外环;polygonParts[1...] = 内环洞 const outerRingCoord = polygonParts[0]; if (!Array.isArray(outerRingCoord) || outerRingCoord.length < 3) return; //外环转Cartesian3 const outerPositions = outerRingCoord.map(([lon, lat, h]) => Cesium.Cartesian3.fromDegrees(lon, lat, h ?? 0) ); //处理挖洞内环 const holes: Cesium.PolygonHierarchy[] = []; for (let i = 1; i < polygonParts.length; i++) { const innerCoord = polygonParts[i]; if (!Array.isArray(innerCoord) || innerCoord.length < 3) continue; const innerPositions = innerCoord.map(([lon, lat, h]) => Cesium.Cartesian3.fromDegrees(lon, lat, h ?? 0) ); holes.push(new Cesium.PolygonHierarchy(innerPositions)); } const hierarchy = new Cesium.PolygonHierarchy(outerPositions, holes); const fillGeo = new Cesium.PolygonGeometry({ polygonHierarchy: hierarchy, perPositionHeight: true, vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }); const fillColor = Cesium.Color.fromCssColorString(colorStr).withAlpha(0.35); tempFillInstances.push(new Cesium.GeometryInstance({ geometry: fillGeo, id: item.id, attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(fillColor) } })); }); // 渲染Primitive if(tempFillInstances.length > 0){ const prim = new Cesium.Primitive({ geometryInstances: tempFillInstances, appearance: new Cesium.PerInstanceColorAppearance({ translucent: true, closed: true }), asynchronous: true }); // prim.depthTestEnabled = false; //需要强制可见打开 this.viewer.scene.primitives.add(prim); this.polygonPrimitiveMap.set(`fill_${Math.random()}`, prim); }四、拾取点击
const handler = new Cesium.ScreenSpaceEventHandler(this.viewer.canvas); handler.setInputAction((click) => { const pick = this.viewer.scene.pick(click.position); if (Cesium.defined(pick)) { console.log('面要素ID', pick.id); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK);五、销毁清除(内存泄漏)
private polygonPrimitiveMap = new Map<string, Cesium.Primitive>(); public clearPolygonPrimitive(){ this.polygonPrimitiveMap.forEach(prim=>{ this.viewer.scene.primitives.remove(prim); }) this.polygonPrimitiveMap.clear(); }六、重要坑清单
perPositionHeight:true只对 PolygonGeometry 生效;GroundPolygonGeometry 不支持,会丢失 Z 高程。PerInstanceColorAppearance没有 depthFailAppearance,三维面埋进山体直接看不见,没有地下半透明方案。兜底:prim.depthTestEnabled=false。- 多边形顶点最少 3 个;WKT 解析要校验,少于 3 个直接跳过,否则渲染崩溃。
- 外环 / 内环建议首尾闭合,即使不闭合 Cesium 内部会自动闭合。
- Primitive 一旦创建,不能修改顶点坐标、不能修改单一面颜色;更新数据必须全部销毁重新构建。
- 想要每个面不同颜色:必须给每个
GeometryInstance设置attributes.color,不能改 appearance 材质。 - 透明度依靠
withAlpha();PerInstanceColorAppearance构造参数translucent:true必须打开,否则透明度失效。
七、对比总表(线 / 点 / 面)
| 要素 | 几何体 | Appearance | 地下遮挡变色 | 支持独立高程 Z |
|---|---|---|---|---|
| 三维折线 | PolylineGeometry | PolylineMaterialAppearance | ✅ depthFailAppearance | ✅ |
| 节点点 | PointPrimitiveCollection | - | ✅ depthFailColor | ✅ |
| 三维空间面 | PolygonGeometry | PerInstanceColorAppearance | ❌无 API,只能关闭 depthTestEnabled | ✅ |
| 贴地面 | GroundPolygonGeometry | PerInstanceColorAppearance | ❌ | ❌丢弃高程 |
业务选型总结
- MultiLineString‑Z 三维线:
PolylineGeometry + Primitive + depthFailAppearance - 折线上节点:
PointPrimitiveCollection + depthFailColor - MultiPolygon‑Z 带高程面:
PolygonGeometry + PerInstanceColorAppearance,地下看不见只能depthTestEnabled=false兜底