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閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容