SuperMap iClient3D for Cesium绘制河流(二)

发布时间:2024年01月03日

作者:kele

前言
之前分享过一篇《SuperMap iClient3D for WebGL绘制河流》(跳转)的文章,当时的思路是以 entity 中的 polyline 作为载体,给它添加流动材质来表达出河流效果,但是由于 polyline 对象是像素宽度,线宽始终是相对屏幕的固定大小,导致在场景放大缩小过程中,河流宽度与周围的山脉位置和大小不匹配,这个问题困扰了小编好久。最近想到了一个新的方案,并且能够支持实时更改河流宽度和高度,一起来看下如何实现吧~

一、解决思路

为了解决这个问题,先后考虑过以下几种方案:

  • corridor 走廊对象:
    大小正常,但水流方向为统一方向,不是沿线流动方向
    在这里插入图片描述
  • polygon 面对象:
    大小正常,但水流方向为统一方向,不是沿线流动,适合用来表达湖泊效果
  • wall 墙对象:
    大小正常,水流方向沿墙体方向流动,但是墙体为向上拉伸只能竖着,河流表面应该是水平面,所以无法表达河流效果在这里插入图片描述
  • polylineVolume 多段线柱体对象:
    多段线柱体对象类似于截面放样功能,通常是用来表达管道和墙体,我们先制作一个圆管看看效果
    在这里插入图片描述
    如上所示,河流大小正常,水流方向为沿线方向,这两方面都是符合预期的。接下来我们可以将管道截面改为一条横线,最终得到结果就是一个面片,感觉这个方式可行

二、实现代码

2.1 绘制河流

经过上面的分析,我们最终选择使用 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;
}

将截面设置为面片模拟河流
在这里插入图片描述

2.2 调整河流宽度

因为我们使用的是 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
});

2.3 调整河流高度

同样的,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

文章来源:https://blog.csdn.net/supermapsupport/article/details/135354563
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。