Cesium开发基础篇 | 04空间数据可视化之Entity

前面介绍了Cesium如何加载影像数据、地形数据、以及矢量数据,但是作为一个完整的三维系统,仅仅包括这些数据还是远远不够的。当然,还需要一些其他数据,比如空间可视化数据、三维数据数据等,今天我们先从空间数据的可视化说起,后面会有专门的章节介绍三维数据方面的加载。

Cesium在空间数据可视化方面提供了两种类型的API,一种是面向图形开发人员的低级(原始)API,通过Primitive类实现,对于那些对计算机图形学知识很了解的同学可以采用Primitive API,后面章节会有详细介绍;另一种是用于数据驱动的高级(实体)API,通过Entity类实现,相对于Primitive API,Entity API实现起来更简单一些,特别建议初学者使用。Entity API 实际上是对Primitive API的二次封装,底层调用的仍然是Primitive API,目的就是为我们提供灵活的、易学、易用的高性能可视化界面。本章节内容主要介绍后者Entity API,Primitive API放在后面的高级篇里讲解。

Entity支持的图形类型

通过在Cesium API文档中查看Entity类的构造函数,我们发现Entity支持的图形类型都是以Graphics结尾的,一共有17种类型。如下图所示,列出了Entity支持的图形类型以及对应的js类。

下面,简单介绍一下每一种类型的Graphic添加方式。
1)billboard 广告牌

 var entity = viewer.entities.add({
      // id: "",
      name: "billboard",
      // show: true,
      // description: "",
      // orientation: "",
      position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
      billboard: {
        show: true, // default
        image: "./images/Cesium_Logo_overlay.png", // default: undefined
        scale: 2.0, // default: 1.0
        //像素偏移    type: Cartesian2    default:Cartesian2.ZERO
        pixelOffset: new Cesium.Cartesian2(0, -50),
        //眼睛偏移    type: Cartesian3    default:Cartesian3.ZERO
        eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0),

        // 水平对齐方式  type: HorizontalOrigin  default:HorizontalOrigin.CENTER
        // CENTER 原点在对象的水平中心;LEFT 原点在对象的左侧;RIGHT 原点在对象的右侧
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        // 垂直对齐方式  type: VerticalOrigin  default:VerticalOrigin.CENTER
        // CENTER 原点位于 BASELINE 和 TOP 之间的垂直中心;BOTTOM 原点在对象的底部;
        // BASELINE 如果对象包含文本,则原点位于文本的基线,否则原点位于对象的底部;TOP 原点在对象的顶部
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // default: CENTER 垂直对齐位置 参考Cesium.VerticalOrigin

        // 获取或设置此广告牌的高度参考    type: HeightReference    default:HeightReference.NONE
        // NONE 位置绝对;CLAMP_TO_GROUND 位置固定在地形上;RELATIVE_TO_GROUND 位置高度是指地形上方的高度
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,

        // 颜色  type: Color  default:Color.WHITE
        color: Cesium.Color.LIME,
        // 获取或设置以弧度为单位的旋转角度  type: number  default:0
        rotation: Cesium.Math.PI_OVER_FOUR,
        // 获取或设置世界空间中的对齐轴  type:Cartesian3  default:Cartesian3.ZERO
        alignedAxis: Cesium.Cartesian3.ZERO,
        width: 100, // default: undefined
        height: 25, // default: undefined

        // 根据广告牌与相机的距离获取或设置广告牌的近和远缩放属性  type:NearFarScalar
        scaleByDistance: new Cesium.NearFarScalar(1.0e3, 2.0, 2.0e3, 1.0),
        // 根据广告牌到相机的距离,获取或设置广告牌的近和远半透明属性  type:NearFarScalar
        translucencyByDistance: new Cesium.NearFarScalar(
          1.0e3,
          1.0,
          1.5e6,
          0.5
        ),
        // 根据广告牌与摄像头的距离,获取或设置广告牌的近像素偏移量和远像素偏移量缩放属性  type:NearFarScalar
        pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
          1.0e3,
          1.0,
          1.5e6,
          0.0
        ),

        // 设置1000米和2000米之间可见  type:DistanceDisplayCondition
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
        // 获取或设置与相机的距离,在深度处禁用深度测试,例如,以防止剪切地形。
        // 设置为零时,将始终应用深度测试。设置为Number.POSITIVE_INFINITY时,永远不会应用深度测试。
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      },
    });

2)box 盒子

    var entity = viewer.entities.add({
      name: "box",
      position: Cesium.Cartesian3.fromDegrees(-107.0, 40.0, 300000.0),
      box: {
        show: true,
        dimensions: new Cesium.Cartesian3(400000.0, 300000.0, 500000.0), // Cartesian3类型,用于指定框的长度,宽度和高度
        // 指定距实体位置的高度是相对于什么的高度。 default: HeightReference.NONE
        // NONE 位置绝对;CLAMP_TO_GROUND    位置固定在地形上;RELATIVE_TO_GROUND 位置高度是指地形上方的高度。
        heightReference: Cesium.HeightReference.NONE,
        fill: true,
        // MaterialProperty|Color  default:Color.WHITE
        material: Cesium.Color.RED.withAlpha(0.5),
        outline: true,
        // type:Property|Color  default:Color.BLACK
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 1.0,

        // type:ShadowMode  default:ShadowMode.DISABLED
        // DISABLED 对象不投射或接收阴影;ENABLED  对象投射并接收阴影;CAST_ONLY 对象仅投射阴影;RECEIVE_ONLY 该对象仅接收阴影。
        shadows: Cesium.ShadowMode.DISABLED,
        // type:DistanceDisplayCondition
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
      },
    });

3)corridor 走廊

    var entity = viewer.entities.add({
      name: "corridor",
      corridor: {
        // show: true,
        // 指定定义走廊中心线的 Cartesian3 位置的数组  type: Cartesian3
        positions: Cesium.Cartesian3.fromDegreesArray([
          -80.0,
          40.0,
          -85.0,
          40.0,
          -85.0,
          35.0,
        ]),
        width: 200000.0,
        height: 200000.0,
        heightReference: Cesium.HeightReference.NONE,
        extrudedHeight: 100000.0,
        extrudedHeightReference: Cesium.HeightReference.NONE,

        // 拐角的样式  type:CornerType  default:CornerType.ROUNDED
        // ROUNDED  角有光滑的边缘;MITERED 拐角点是相邻边的交点;BEVELED  角被修剪
        cornerType: Cesium.CornerType.ROUNDED,
        granularity: Cesium.Math.RADIANS_PER_DEGREE, // 每个纬度和经度之间的距离
        fill: true,
        // 材质  type:MaterialProperty|Color  default:Color.WHITE
        material: Cesium.Color.BLUE.withAlpha(0.5),
        outline: true, // height or extrudedHeight must be set for outlines to display
        outlineColor: Cesium.Color.WHITE,
        outlineWidth: 1.0,
        shadows: Cesium.ShadowMode.DISABLED,
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
        // 走廊在地面上时将对地形,3D tiles还是对两者进行分类  type:ClassificationType  default:ClassificationType.BOTH
        // TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH    将同时对Terrain和3D Tiles进行分类。
        classificationType: Cesium.ClassificationType.BOTH,
      },
    });

4)cylinder 圆柱、圆锥

    var entity = viewer.entities.add({
      name: "cylinder",
      position: Cesium.Cartesian3.fromDegrees(-105.0, 40.0, 200000.0),
      cylinder: {
        // show: true,
        length: 400000.0, // 圆柱体长度
        topRadius: 200000.0, // 圆柱体顶部半径
        bottomRadius: 200000.0, // 圆柱体底部半径
        heightReference: Cesium.HeightReference.NONE,
        fill: true,
        material: Cesium.Color.GREEN.withAlpha(0.5),
        outline: true,
        outlineColor: Cesium.Color.DARK_GREEN,
        outlineWidth: 1.0,
        numberOfVerticalLines: 16, // 沿轮廓的周长绘制的垂直线的数量
        shadows: Cesium.ShadowMode.DISABLED,
        slices: 128, // 圆柱周围的边缘数量
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
      },
    });

5)ellipse 椭圆或拉伸的椭圆

    var entity = viewer.entities.add({
      name: "Circles and Ellipses",
      position: Cesium.Cartesian3.fromDegrees(-95.0, 40.0, 100000.0),
      ellipse: {
        show: true,
        semiMajorAxis: 300000.0, // 长半轴距离
        semiMinorAxis: 150000.0, // 短半轴距离

        height: 20000.0,
        heightReference: Cesium.HeightReference.NONE,
        extrudedHeight: 20000.0,
        extrudedHeightReference: Cesium.HeightReference.NONE,

        // rotation: Cesium.Math.toRadians(45), // 从北方逆时针旋转
        stRotation: 0.0, // 纹理从北方逆时针旋转
        granularity: Cesium.Math.RADIANS_PER_DEGREE, // 椭圆上各点之间的角距离
        material: Cesium.Color.BLUE.withAlpha(0.5),
        fill: true,
        outline: true,
        outlineColor: Cesium.Color.DARK_GREEN,
        outlineWidth: 1.0,
        numberOfVerticalLines: 16, // 沿轮廓的周长绘制的垂直线的数量
        shadows: Cesium.ShadowMode.DISABLED,
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),

        // 在地面上时将对地形,3D tiles还是对两者进行分类  type:ClassificationType  default:ClassificationType.BOTH
        // TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D瓷砖进行分类;BOTH    将同时对Terrain和3D Tile进行分类。
        classificationType: Cesium.ClassificationType.BOTH,
      },
    });

6)ellipsoid 椭球体

    var entity = viewer.entities.add({
      name: "Spheres and Ellipsoids",
      position: Cesium.Cartesian3.fromDegrees(-100.0, 40.0, 300000.0),
      ellipsoid: {
        show: true,
        radii: new Cesium.Cartesian3(200000.0, 200000.0, 300000.0), // 椭球半径
        // innerRadii: new Cesium.Cartesian3(0.0, 0.0, 0.0), // 椭球内部半径
        minimumClock: 0.0, // 最小时钟角度
        maximumClock: 2 * Math.PI, // 最大时钟角度
        minimumCone: 0.0, // 最小圆锥角
        maximumCone: Math.PI, // 最大圆锥角
        heightReference: Cesium.HeightReference.NONE,
        fill: true,
        material: Cesium.Color.BLUE.withAlpha(0.5),
        outline: true,
        outlineColor: Cesium.Color.YELLOW,
        outlineWidth: 1.0,

        stackPartitions: 64, // 延纬度线切割的次数
        slicePartitions: 64, // 延经度线切割的次数
        subdivisions: 128, // 每个轮廓环的样本数,确定曲率的粒度

        shadows: Cesium.ShadowMode.DISABLED,
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
      },
    });

7)label 标签

    var entity = viewer.entities.add({
      name: "label",
      position: Cesium.Cartesian3.fromDegrees(
        -75.1641667,
        39.9522222,
        300000.0
      ),
      label: {
        show: true,
        text: "label标签",
        font: "24px Helvetica",
        // FILL 填充;OUTLINE 只显示边框;FILL_AND_OUTLINE 既有填充又有边框
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        scale: 1.0,
        showBackground: true,
        backgroundColor: Cesium.Color.BLUE,
        backgroundPadding: new Cartesian2(7, 5),
        pixelOffset: Cartesian2.ZERO,
        eyeOffset: Cartesian3.ZERO,
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.CENTER,
        heightReference: Cesium.HeightReference.NONE,
        fillColor: Cesium.Color.SKYBLUE,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 2,
        translucencyByDistance: new Cesium.NearFarScalar(
          1.0e3,
          1.0,
          1.5e6,
          0.5
        ),
        pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
          1.0e3,
          1.0,
          1.5e6,
          0.0
        ),
        scaleByDistance: new Cesium.NearFarScalar(1.0e3, 2.0, 2.0e3, 1.0),
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      },
    });

8)model 模型

var position = Cesium.Cartesian3.fromDegrees(
      -123.0744619,
      44.0503706,
      5000.0
    );
    var heading = Cesium.Math.toRadians(135);
    var pitch = 0;
    var roll = 0;
    var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
    var orientation = Cesium.Transforms.headingPitchRollQuaternion(
      position,
      hpr
    );

    var url = "./data/models/CesiumAir/Cesium_Air.glb";
    var entity = viewer.entities.add({
      name: "model",
      position: position,
      orientation: orientation,
      model: {
        show: true,
        uri: url,
        scale: 1.0,
        minimumPixelSize: 128, // 模型的最小最小像素大小,而不考虑缩放
        maximumScale: 20000, // 模型的最大比例尺大小。 minimumPixelSize的上限
        incrementallyLoadTextures: true, // 确定在加载模型后纹理是否可以继续流入
        runAnimations: true, // 是否应启动模型中指定的glTF动画
        clampAnimations: true, // glTF动画是否应在没有关键帧的持续时间内保持最后一个姿势
        shadows: Cesium.ShadowMode.DISABLED,
        heightReference: Cesium.HeightReference.NONE,
        silhouetteColor: Cesium.Color.RED, // 轮廓的颜色
        silhouetteSize: 0.0, // 轮廓的宽度
        color: Cesium.Color.WHITE, // 模型的颜色

        // 目标颜色和图元的源颜色之间混合的不同模式
        // HIGHLIGHT 将源颜色乘以目标颜色;REPLACE 将源颜色替换为目标颜色;MIX 将源颜色和目标颜色混合在一起
        colorBlendMode: Cesium.ColorBlendMode.HIGHLIGHT,
        // 用于指定 colorBlendMode 为 MIX 时的颜色强度。值0.0会产生模型的着色,而值1.0会导致纯色,介于两者之间的任何值都会导致两者混合
        colorBlendAmount: 0.5,
        imageBasedLightingFactor: new Cesium.Cartesian2(1.0, 1.0), // 指定基于漫反射和镜面反射的图像照明的贡献
        lightColor: undefined, // 为模型着色时指定浅色的属性。如果 undefined ,则使用场景的浅色。
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
      },
    });

9)tileset 3D Tiles瓦片集

  var tileset = viewer.entities.add({
      name: "3D Tiles",
      position: Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0),
      tileset: {
        show: true,
        uri: new Cesium.Plane(Cesium.Cartesian3.UNIT_X, 0.0),
      },
    });

10)path 路径

    var entityPath = viewer.entities.add({
      position: pathPosition,
      name: "path",
      path: {
        show: true,
        leadTime: 0,
        trailTime: 60,
        width: 10,
        resolution: 1,
        material: new Cesium.PolylineGlowMaterialProperty({
          glowPower: 0.3,
          taperPower: 0.3,
          color: Cesium.Color.PALEGOLDENROD,
        }),
      },
    });

11)plane 平面

    var bluePlane = viewer.entities.add({
      name: "Blue plane",
      position: Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0),
      plane: {
        show: true,
        // 用于指定平面的法线和距离
        plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_X, 0.0),
        dimensions: new Cesium.Cartesian2(400000.0, 300000.0), // 指定平面的宽度和高度
        fill: true,
        material: Cesium.Color.BLUE,
        outline: false,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 1.0,
        shadows: Cesium.ShadowMode.DISABLED,
        // type:DistanceDisplayCondition
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
      },
    });

12)point 点

   viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
      point: {
        show: true,
        pixelSize: 10, // 像素大小
        heightReference: Cesium.HeightReference.NONE,
        color: Cesium.Color.YELLOW,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 0,
        scaleByDistance: new Cesium.NearFarScalar(1.0e3, 10.0, 2.0e3, 1.0),
        translucencyByDistance: new Cesium.NearFarScalar(
          1.0e3,
          1.0,
          1.5e6,
          0.5
        ),
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
        // 获取或设置与相机的距离,在深度处禁用深度测试,例如,以防止剪切地形。
        // 设置为零时,将始终应用深度测试。设置为Number.POSITIVE_INFINITY时,永远不会应用深度测试。
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      },
    });

13)polygon 多边形

   var redPolygon = viewer.entities.add({
      name: "Red polygon on surface",
      polygon: {
        show: true,
        // 指定PolygonHierarchy
        hierarchy: Cesium.Cartesian3.fromDegreesArray([
          -115.0,
          37.0,
          -115.0,
          32.0,
          -107.0,
          33.0,
          -102.0,
          31.0,
          -102.0,
          35.0,
        ]),
        height: 0, // 多边形相对于椭球面的高度
        heightReference: Cesium.HeightReference.NONE,
        // extrudedHeight: 0, // 多边形的凸出面相对于椭球面的高度
        // extrudedHeightReference: Cesium.HeightReference.NONE,
        stRotation: 0.0, // 多边形纹理从北方逆时针旋转
        granularity: Cesium.Math.RADIANS_PER_DEGREE, // 每个纬度和经度点之间的角距离
        fill: true,
        material: Cesium.Color.RED,
        outline: false,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 1.0,
        perPositionHeight: false, // 是否使用每个位置的高度

        closeTop: true, // 如果为false,则将挤出的多边形顶部留空
        closeBottom: true, // 如果为false,则将挤出的多边形的底部保留为开放状态

        // 多边形边缘必须遵循的线型    type:ArcType 定义连接顶点应采用的路径。
        // NONE 与椭圆表面不符的直线;GEODESIC 遵循测地路径;RHUMB    遵循大黄蜂或恶魔般的道路。
        arcType: Cesium.ArcType.GEODESIC,
        shadows: Cesium.ShadowMode.DISABLED,
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
        // 在地面上时将对地形,3D tiles还是对两者进行分类  type:ClassificationType  default:ClassificationType.BOTH
        // TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH    将同时对Terrain和3D Tiles进行分类。
        classificationType: Cesium.ClassificationType.BOTH,
        // 指定用于订购地面几何形状的z索引。仅在多边形为常数且未指定高度或拉伸高度的情况下才有效  type:ConstantProperty
        zIndex: 0,
      },
    });

14)polyline 多线段

    var redLine = viewer.entities.add({
      name: "Red line on terrain",
      polyline: {
        show: true,

        // 定义线条的 Cartesian3 位置的数组
        positions: Cesium.Cartesian3.fromDegreesArray([-75, 35, -125, 35]),

        width: 5,
        // 如果arcType不是ArcType.NONE,则指定每个纬度和经度之间的角距离
        // granularity: Cesium.Math.RADIANS_PER_DEGREE,

        material: Cesium.Color.RED,
        // 线低于地形时用于绘制折线的材质
        // depthFailMaterial: Cesium.Color.WHITE,

        // 折线段必须遵循的线型
        // arcType: Cesium.ArcType.GEODESIC,

        clampToGround: true, // 是否贴地

        shadows: Cesium.ShadowMode.DISABLED, // 折线是投射还是接收光源的阴影

        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),

        // 在地面上时将对地形,3D tiles还是对两者进行分类  type:ClassificationType  default:ClassificationType.BOTH
        // TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH    将同时对Terrain和3D Tiles进行分类。
        classificationType: Cesium.ClassificationType.BOTH,

        // 指定用于订购地面几何形状的z索引。仅在多边形为常数且未指定高度或拉伸高度的情况下才有效  type:ConstantProperty
        // zIndex: 0,
      },
    });

15)polylineVolume 多线段柱体

    function computeCircle(radius) {
      var positions = [];
      for (var i = 0; i < 360; i++) {
        var radians = Cesium.Math.toRadians(i);
        positions.push(
          new Cesium.Cartesian2(
            radius * Math.cos(radians),
            radius * Math.sin(radians)
          )
        );
      }
      return positions;
    }

    var redTube = viewer.entities.add({
      name: "Red tube with rounded corners",
      polylineVolume: {
        show: true,

        // 定义线带的 Cartesian3 位置的数组
        positions: Cesium.Cartesian3.fromDegreesArray([
          -85.0,
          32.0,
          -85.0,
          36.0,
          -89.0,
          36.0,
        ]),

        // 指定 Cartesian2 位置的数组,这些位置定义了要拉伸的形状
        shape: computeCircle(60000.0),

        // 拐角的样式  type:CornerType
        // ROUNDED  拐角有光滑的边缘;MITERED 拐角点是相邻边的交点;BEVELED 拐角被修剪。
        cornerType: Cesium.CornerType.ROUNDED,

        // 如果arcType不是ArcType.NONE,则指定每个纬度和经度之间的角距离
        // granularity: Cesium.Math.RADIANS_PER_DEGREE,

        fill: true,

        material: Cesium.Color.RED,

        outline: false,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 1.0,

        shadows: Cesium.ShadowMode.DISABLED, // 体积是投射还是接收光源的阴影

        // type:DistanceDisplayCondition
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
      },
    });

16)rectangle 矩形

    var redRectangle = viewer.entities.add({
      name: "Red translucent rectangle",
      rectangle: {
        show: true,

        coordinates: Cesium.Rectangle.fromDegrees(-110.0, 20.0, -80.0, 25.0),

        // height: 0, // 矩形相对于椭球面的高度
        // heightReference: Cesium.HeightReference.NONE,

        // extrudedHeight: 0, // 矩形的拉伸面相对于椭球面的高度
        // extrudedHeightReference: Cesium.HeightReference.NONE,

        rotation: 0.0, // 矩形从北方向顺时针方向的旋转
        stRotation: 0.0, // 矩形纹理从北方逆时针旋转
        granularity: Cesium.Math.RADIANS_PER_DEGREE, // 指定矩形上各点之间的角度距离
        fill: true,
        material: Cesium.Color.RED.withAlpha(0.5),

        outline: false,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 1.0,

        shadows: Cesium.ShadowMode.DISABLED,
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
        // 在地面上时将对地形,3D tiles还是对两者进行分类  type:ClassificationType  default:ClassificationType.BOTH
        // TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH    将同时对Terrain和3D Tiles进行分类。
        classificationType: Cesium.ClassificationType.BOTH,
        // 指定用于订购地面几何形状的z索引。仅在多边形为常数且未指定高度或拉伸高度的情况下才有效  type:ConstantProperty
        zIndex: 0,
      },
    });

17)wall 墙

    var redWall = viewer.entities.add({
      name: "Red wall at height",
      wall: {
        show: true,

        positions: Cesium.Cartesian3.fromDegreesArrayHeights([
          -115.0,
          44.0,
          200000.0,
          -90.0,
          44.0,
          200000.0,
        ]),

        // 用于墙底而不是地球表面的高度数组
        minimumHeights: [100000.0, 100000.0],
        // 用于墙顶的高度数组,而不是每个位置的高度
        // maximumHeights: [],

        granularity: Cesium.Math.RADIANS_PER_DEGREE, // 指定矩形上各点之间的角度距离
        fill: true,
        material: Cesium.Color.RED,

        outline: false,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 1.0,

        shadows: Cesium.ShadowMode.DISABLED,
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        //   1.0e3,
        //   2.0e3
        // ),
      },
    });

Entity 聚合

同时,针对Billboard、Label、Point,Cesium 提供了 EntityCluster 类用于实现聚合效果,但必须结合 PinBuilder 类实现。下面为实现聚合效果的核心代码:

    var options = {
      camera: viewer.scene.camera,
      canvas: viewer.scene.canvas,
    };
    var dataSourcePromise = viewer.dataSources.add(
      Cesium.KmlDataSource.load("./data/kml/facilities/facilities.kml", options)
    );
    dataSourcePromise.then(function (dataSource) {
      var pixelRange = 15;
      var minimumClusterSize = 3;
      var enabled = true;

      dataSource.clustering.enabled = enabled;
      dataSource.clustering.pixelRange = pixelRange; // 扩展屏幕空间边界框的像素范围
      dataSource.clustering.minimumClusterSize = minimumClusterSize; // 可以聚合的最小屏幕空间对象

      var removeListener;

      var pinBuilder = new Cesium.PinBuilder();
      var pin50 = pinBuilder.fromText("50+", Cesium.Color.RED, 48).toDataURL();
      var pin40 = pinBuilder
        .fromText("40+", Cesium.Color.ORANGE, 48)
        .toDataURL();
      var pin30 = pinBuilder
        .fromText("30+", Cesium.Color.YELLOW, 48)
        .toDataURL();
      var pin20 = pinBuilder
        .fromText("20+", Cesium.Color.GREEN, 48)
        .toDataURL();
      var pin10 = pinBuilder.fromText("10+", Cesium.Color.BLUE, 48).toDataURL();

      var singleDigitPins = new Array(8);
      for (var i = 0; i < singleDigitPins.length; ++i) {
        singleDigitPins[i] = pinBuilder
          .fromText("" + (i + 2), Cesium.Color.VIOLET, 48)
          .toDataURL();
      }

      function customStyle() {
        if (Cesium.defined(removeListener)) {
          removeListener();
          removeListener = undefined;
        } else {
          removeListener = dataSource.clustering.clusterEvent.addEventListener(
            function (clusteredEntities, cluster) {
              cluster.label.show = false;
              cluster.billboard.show = true;
              cluster.billboard.id = cluster.label.id;
              cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;

              if (clusteredEntities.length >= 50) {
                cluster.billboard.image = pin50;
              } else if (clusteredEntities.length >= 40) {
                cluster.billboard.image = pin40;
              } else if (clusteredEntities.length >= 30) {
                cluster.billboard.image = pin30;
              } else if (clusteredEntities.length >= 20) {
                cluster.billboard.image = pin20;
              } else if (clusteredEntities.length >= 10) {
                cluster.billboard.image = pin10;
              } else {
                cluster.billboard.image =
                  singleDigitPins[clusteredEntities.length - 2];
              }
            }
          );
        }

        // force a re-cluster with the new styling
        var pixelRange = dataSource.clustering.pixelRange;
        dataSource.clustering.pixelRange = 0;
        dataSource.clustering.pixelRange = pixelRange;
      }

      // start with custom style
      customStyle();

      var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
      handler.setInputAction(function (movement) {
        var pickedLabel = viewer.scene.pick(movement.position);
        if (Cesium.defined(pickedLabel)) {
          var ids = pickedLabel.id;
          if (Array.isArray(ids)) {
            for (var i = 0; i < ids.length; ++i) {
              ids[i].billboard.color = Cesium.Color.RED;
            }
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    });

Entity 管理

上面介绍了Entity的图形类型,有这么多类型的实体,Cesium是如何管理这些实体对象的呢,这就需要我们从初始化Viewer对象开始说起了。当我们初始化Viewer类之后,会得到一个实例化对象viewer,这个viewer会包含一个属性 entities ,它的类型是 EntityCollection ,也就是 Entity 的集合,它包括了 EntityCollection 类里面的所有属性和方法。所以 Cesium 管理 Entity 本质上是通过 EntityCollection 类进行管理的,比如add(添加Entity)、contains(是否存在某个Entity)、getById(通过ID获取Entity)、remove(移除某个Entity)、removeAll(移除所有的Entity)、removeById(通过ID移除Entity)方法等。

    var point = viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(-105.0, 41, 50010),
      point: {
        show: true,
        pixelSize: 10, // 像素大小
      },
    });

    var entity = viewer.entities.getById("entity_1");
    viewer.entities.remove(entity);
    // viewer.entities.removeById("entity_1");
    // viewer.entities.removeAll();

Entity 拾取

在三维场景种,很常见的一种交互方式,就是鼠标点击三维场景种某一个几何图形,查看该图形的包含的属性信息,并显示在对应的信息窗体中。单击事件通过 ScreenSpaceEventHandler 类注册,拾取到的信息可通过以下两种方式获取。

  • scene.pick:获取窗体坐标处最顶部的实体;
  • scene.drillPick:窗体坐标处的实体列表。
    // 添加拾取事件
    var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
    handler.setInputAction(function (movement) {
      var pickedEntity = pickEntity(viewer, movement.position);
      console.log(pickedEntity);

      var pickedEntities = drillPickEntities(viewer, movement.position);
      console.log(pickedEntities);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    function pickEntity(viewer, windowPosition) {
      var picked = viewer.scene.pick(windowPosition);
      if (Cesium.defined(picked)) {
        var id = Cesium.defaultValue(picked.id, picked.primitive.id);
        if (id instanceof Cesium.Entity) {
          return id;
        }
      }
      return undefined;
    }
    function drillPickEntities(viewer, windowPosition) {
      var i;
      var entity;
      var picked;
      var pickedPrimitives = viewer.scene.drillPick(windowPosition);
      var length = pickedPrimitives.length;
      var result = [];
      var hash = {};

      for (i = 0; i < length; i++) {
        picked = pickedPrimitives[i];
        entity = Cesium.defaultValue(picked.id, picked.primitive.id);
        if (
          entity instanceof Cesium.Entity &&
          !Cesium.defined(hash[entity.id])
        ) {
          result.push(entity);
          hash[entity.id] = true;
        }
      }
      return result;
    }

Entity 固定

在实际的应用系统中,会有这样的需求,要求画的实体附着在地形表面、或三维建筑表面(比如视频融合),这时候就需要设置xxGraphics的相关属性了,可通过 heightReference 或 classificationType 这两个属性去控制。属性值描述如下:

  • heightReference属性值:
    NONE:位置绝对(默认值);
    CLAMP_TO_GROUND:位置固定在地形上;
    RELATIVE_TO_GROUND:位置高度是指地形上方的高度

  • classificationType属性值:
    TERRAIN:将仅对地形进行分类;
    CESIUM_3D_TILE:将仅对3D Tiles进行分类;
    BOTH :将同时对Terrain和3D Tiles进行分类。

其中corridor 、 ellipse 、 polygon 、 polyline 、 rectangle 可通过设置 classificationType 属性值显示仅贴地、仅贴建筑或者两者都贴的效果,billboard 、 box 、 corridor 、 cylinder 、 ellipse 、 ellipsoid 、 label 、 model 、 point 、 polygon 、 tectangle通过设置 heightReference 属性值为 CLAMP_TO_GROUND 显示贴地效果。这里需要注意的是,如果是polyline必须设置 clampToGround 属性为 true 。

    // set the heightReference to CLAMP_TO_GROUND
    // billboard box corridor cylinder ellipse ellipsoid label model point polygon tectangle
    // 其中corridor ellipse polygon retangle会自动贴地
    viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(-122.1958, 46.1915),
      billboard: {
        image: "./images/facility.gif",
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
      },
      point: {
        color: Cesium.Color.SKYBLUE,
        pixelSize: 10,
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
      },
      label: {
        text: "Clamped to ground",
        font: "14pt sans-serif",
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
        verticalOrigin: Cesium.VerticalOrigin.BASELINE,
        fillColor: Cesium.Color.BLACK,
        showBackground: true,
        backgroundColor: new Cesium.Color(1, 1, 1, 0.7),
        backgroundPadding: new Cesium.Cartesian2(8, 4),
        disableDepthTestDistance: Number.POSITIVE_INFINITY, // draws the label in front of terrain
      },
    });
    viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(-122.1958, 46.1915),
      model: {
        uri: "./data/models/CesiumMan/Cesium_Man.glb",
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        minimumPixelSize: 128,
        maximumScale: 100,
      },
    });

    // corridors、ellipse、 polygons and rectangles will be clamped automatically 
    // if they are filled with a constant color and  has no height or extruded height.
    viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(-122.195, 46.1915),
      corridor: {
        positions: Cesium.Cartesian3.fromDegreesArray([
          -122.19,
          46.1914,
          -122.2,
          46.1924,
          -122.21,
          46.193,
        ]),
        width: 500.0,
        material: Cesium.Color.GREEN.withAlpha(0.5),
      },
      ellipse: {
        semiMajorAxis: 300.0, // 长半轴距离
        semiMinorAxis: 150.0, // 短半轴距离
        // heightReference: Cesium.HeightReference.NONE,
        material: Cesium.Color.BLUE.withAlpha(0.5),
        // material: "./images/Cesium_Logo_Color.jpg",
        // classificationType: Cesium.ClassificationType.BOTH,
      },
      polygon: {
        hierarchy: {
          positions: [
            new Cesium.Cartesian3(
              -2358138.847340281,
              -3744072.459541374,
              4581158.5714175375
            ),
            new Cesium.Cartesian3(
              -2357231.4925370603,
              -3745103.7886602185,
              4580702.9757762635
            ),
            new Cesium.Cartesian3(
              -2355912.902205431,
              -3744249.029778454,
              4582402.154378103
            ),
            new Cesium.Cartesian3(
              -2357208.0209552636,
              -3743553.4420488174,
              4581961.863286629
            ),
          ],
        },
        // material: Cesium.Color.BLUE.withAlpha(0.5),
        material: "./images/Cesium_Logo_Color.jpg",
      },
      rectangle: {
        coordinates: Cesium.Rectangle.fromDegrees(-122.2, 46.2, -122.1, 46.3),
        material: Cesium.Color.RED.withAlpha(0.5),
      },
    });

    // set the classificationType to TERRAIN
    // corridor ellipse polygon polyline rectangle
    // 其中polyline 必须 设置clampToGround = true
    viewer.entities.add({
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([
          -122.1968,
          46.1915,
          -122.1968,
          46.2015,
          -122.1968,
          46.2015,
        ]),
        clampToGround: true,
        width: 5,
        material: Cesium.Color.ORANGE,
        depthFailMaterial: Cesium.Color.RED,
        // classificationType: Cesium.ClassificationType.BOTH,
      },
    });
  var polygon = viewer.entities.add({
      polygon: {
        hierarchy: new Cesium.PolygonHierarchy(
          Cesium.Cartesian3.fromRadiansArray([
            -1.3194369277314022,
            0.6988062530900625,
            -1.3193955980204217,
            0.6988091578771254,
            -1.3193931220959367,
            0.698743632490865,
            -1.3194358224045408,
            0.6987471965556998,
          ])
        ),
        // NONE 位置绝对;CLAMP_TO_GROUND 位置固定在地形上;RELATIVE_TO_GROUND 位置高度是指地形上方的高度
        // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        // material: Cesium.Color.RED.withAlpha(0.5),
        material: "./images/Cesium_Logo_Color.jpg",
        // TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH    将同时对Terrain和3D Tiles进行分类。
        classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
      },
    });

    var polyline = viewer.entities.add({
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([
          -75.60217330403601,
          40.04102882709425,
          -75.59968252414251,
          40.04093615560871,
          -75.598020153828,
          40.04079437042357,
          -75.59674934074435,
          40.040816173283304,
          -75.59630042791713,
          40.03986900370842,
          -75.59563636849978,
          40.03930996506271,
          -75.59492397899098,
          40.03873932846581,
          -75.59457991226778,
          40.038392701955786,
          -75.59424838652453,
          40.03775403572295,
          -75.59387104290336,
          40.03677022167725,
          -75.59355000490342,
          40.03588760913535,
        ]),
        width: 8,
        material: new Cesium.PolylineOutlineMaterialProperty({
          color: Cesium.Color.YELLOW,
          outlineWidth: 2,
          outlineColor: Cesium.Color.BLACK,
        }),
        clampToGround: true,
        // TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH    将同时对Terrain和3D Tiles进行分类。
        classificationType: Cesium.ClassificationType.TERRAIN,
      },
    });
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容