作者:kele
前言
之前分享过一篇《SuperMap iClient3D for WebGL绘制河流》(跳转)的文章,当时的思路是以 entity 中的 polyline 作为载体,给它添加流动材质来表达出河流效果,但是由于 polyline 对象是像素宽度,线宽始终是相对屏幕的固定大小,导致在场景放大缩小过程中,河流宽度与周围的山脉位置和大小不匹配,这个问题困扰了小编好久。最近想到了一个新的方案,并且能够支持实时更改河流宽度和高度,一起来看下如何实现吧~
为了解决这个问题,先后考虑过以下几种方案:
经过上面的分析,我们最终选择使用 polylineVolume 多段线柱体对象绘制河流,这个方案的关键所在就是需要一个合适的截面:
river = viewer.entities.add({
name : 'river',
polylineVolume : {
positions: new Cesium.Cartesian3.fromDegreesArrayHeights(positions), //节点坐标
shape: computeCircle(150.0), //截面形状
material : new Cesium.PolylineTrailLinkMaterialProperty(Cesium.Color.SKYBLUE,10000),
cornerType: Cesium.CornerType.MITERED,
}
})
function computeCircle(radius) { //设置截面长和宽的大小
var positions = [];
for(var i = 0; i < 180; i++) {
let x = radius * Math.cos(Math.PI * 2 * i / 360); //宽度参数radius可传入进行控制
let y = 0.1 * Math.sin(Math.PI * 2 * i / 360); //将高度尽可能设置小,达到面片效果
positions.push(new Cesium.Cartesian2(x, y));
}
return positions;
}
将截面设置为面片模拟河流
因为我们使用的是 polylineVolume 多段线柱体对象,他没有 width 属性,而是通过改变截面大小,来实现河流宽度的修改,配合着 CallbackProperty 属性,我们就可以实时改变河流宽度了。
shape: new Cesium.CallbackProperty(setWidth,false),
function setWidth() {
var positions = [];
for(var i = 0; i < 180; i++) {
let x = roverWidth * Math.cos(Math.PI * 2 * i / 360);
let y = 0.1 * Math.sin(Math.PI * 2 * i / 360);
positions.push(new Cesium.Cartesian2(x, y));
}
return positions;
}
$('#addwidth').click(function () {
roverWidth += 20
});
$('#reducewidth').click(function () {
roverWidth -= 20
});
同样的,polylineVolume 多段线柱体对象没有高度属性,想要改变数据的高度,需要改变传入坐标的 z 值,同样需要使用 CallbackProperty 属性来实现
positions: new Cesium.CallbackProperty(setHeight,false),
function setHeight() {
return new Cesium.Cartesian3.fromDegreesArrayHeights(positions)
}
$('#addheight').click(function () {
for(let i=0;i<positions.length/3;i++){
positions[i*3+2] += 20;
}
});
$('#reduceheight').click(function () {
for(let i=0;i<positions.length/3;i++){
positions[i*3+2] -= 20;
}
});
demo地址:
链接:https://pan.baidu.com/s/1e8zxMY31GUVFwmQAyx7BqA
提取码:6655