Cesium高阶学习九、管道图元

一、简介
管道图元在Cesium中可以通过PolylineVolumeGraphics实现,但是PolylineVolumeGraphics有个问题,就是到只能实现水平管道,而当管道的点是垂直的时候,就会出现问题。
在这里插入图片描述

管道通常是指地下管道,一般情况下应该是通过各种专业的建模软件批量构建模型最后转为3dtiles在Cesium中使用,但是出于灵活性的考虑,有时需要自己实现动态的管道绘制,因为PolylineVolumeGraphics不能满足某些需求,所以我们需要自定义管道图元。自定义管道图元其实也比较简单,从建模的角度来看,一根管子的构造如下:
在这里插入图片描述

一根管子由很多个三角面构造,而这些三角面又是由多个点构成:
在这里插入图片描述

所以自定义管道图元的难点其实在于计算这些顶点数据,因为这些顶点是由管道的起点和终点计算而来,所以必须能够输入任意的起点和终点。

二、生成顶点数据

生成管道的顶点数据我们一般先在坐标系的原点进行顶点计算,然后经过旋转平移变换将其移动到正确的位置。

1、假定一个管道的起点和终点如下,设管道半径为30

let a = Cesium.Cartesian3.fromDegrees(121.11086303602546, 31.142151406236606, 40);
  let b = Cesium.Cartesian3.fromDegrees(121.11086303602546, 31.142351406236606, 120);

2、有了起点和终点,我们可以计算出管道的长度,然后在坐标原点进行顶点生成,将其封装成一个方法

function generateVertics(start, end, radius) {
   
     let height= Cesium.Cartesian3.distance(start, end);
     let vertices = [];//生成的顶点数组
     let thetaStart = 0, thetaLength = Math.PI * 2;
     for (let y = 0; y <= 1; y++) {
   
         const v = y / 1;
         for (let x = 0; x <= 120; x++) {
   
             const u = x / 120;
             const theta = u * thetaLength + thetaStart;
             const sinTheta = Math.sin(theta);
             const cosTheta = Math.cos(theta);

             let vertex = new Cesium.Cartesian3();
             vertex.x = radius * sinTheta;
             vertex.y = radius * cosTheta;
             vertex.z = v * height;
             vertices.push(vertex);
         }
     }
     return vertices;
 }

3、调用此方法,传入参数

 let vs = this.generateVertics(a, b, 30);

4、查看生成的顶点数据,我们可以先将其添加到场景中显示出来

let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(a);
vs.forEach(v => {
   
    let p = Cesium.Matrix4.multiplyByPoint(
        modelMatrix,
        v,
        new Cesium.Cartesian3()
    )
    viewer.entities.add({
   
        position: p,
        point: {
   
            pixelSize: 10,
            color: Cesium.Color.BLUE
        }
    })
 })

在这里插入图片描述

三、变换顶点数据

上一节我们封装了生成顶点数据的方法,因为顶点数据是在坐标系的原点构建的,所以我们需要经过旋转平移变换,将其变换到和起点终点匹配的位置,平移变换其实在上一节就做过了。
 function generateVertics(start, end, radius) {
   
      let height = Cesium.Cartesian3.distance(start, end);
      let vertices = [];//生成的顶点数组
      let thetaStart = 0, thetaLength = Math.PI * 2;

      //旋转操作
      let dir1 = new Cesium.Cartesian3(0, 0, height);
      let dir2 = Cesium.Cartesian3.subtract(end, start, new Cesium.Cartesian3());
      let angle = Cesium.Cartesian3.angleBetween(dir1, dir2);
      //旋转轴
      let axis = Cesium.Cartesian3.cross(dir1, dir2, new Cesium.Cartesian3());
      //旋转角度
      let rotation = Cesium.Quaternion.fromAxisAngle(axis, angle, new Cesium.Quaternion());
      const m = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
          new Cesium.Cartesian3(0, 0, 0),
          rotation,
          new Cesium.Cartesian3(1, 1, 1),
          new Cesium.Matrix4); 

      for (let y = 0; y <= 1; y++) {
   
          const v = y / 1;
          for (let x = 0; x <= 120; x++) {
   
              const u = x / 120;
              const theta = u * thetaLength + thetaStart;
              const sinTheta = Math.sin(theta);
              const cosTheta = Math.cos(theta);

              let vertex = new Cesium.Cartesian3();
              vertex.x = radius * sinTheta;
              vertex.y = radius * cosTheta;
              vertex.z = v * height;

              //旋转
              let resut = Cesium.Matrix4.multiplyByPoint(
                  m,
                  vertex,
                  new Cesium.Cartesian3()
              )
              //平移
              Cesium.Cartesian3.add(resut, start, resut)

              vertices.push(resut);
          }
      }
      return vertices;
  }

在这里插入图片描述

四、组装顶点数据
顶点数据生成以后,我们需要将其组装成三角面,三角面的顺序是根据索引创建的,所以我们是需要生成索引,再次改造构造顶点的方法。

function generateVertics(start, end, radius) {
   
     let height = Cesium.Cartesian3.distance(start, end);
     let vertices = [];//生成的顶点数组
     let thetaStart = 0, thetaLength = Math.PI * 2;

     //旋转操作
     let dir1 = new Cesium.Cartesian3(0, 0, height);
     let dir2 = Cesium.Cartesian3.subtract(end, start, new Cesium.Cartesian3());
     let angle = Cesium.Cartesian3.angleBetween(dir1, dir2);
     //旋转轴
     let axis = Cesium.Cartesian3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cesium进阶学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值