[cesium] entity 和primitive 繪製對象

 Entity 和primitive 對比

  1. entity偏向數據,primitive偏向圖形.primitive更底層
  2. entity用法簡單,primitive用法複雜。我們會有這樣的疑問:entity已經封裝的如此完美,調用如此便捷,爲何還要primitive接口呢?區別就是加載效率。primitive更接近webgl底層,沒有entity各種各樣的附加屬性,因此在加載時效率會更高。爲了直觀感受兩者區別,我們分別用entity和primitive方式繪製3150個圓。
一entity方式
for (var lon = -180.0; lon < 180.0; lon += 4.0) {
            for (var lat = -70.0; lat < 70.0; lat += 4.0) {
                viewer.entities.add({
                    position: Cesium.Cartesian3.fromDegrees(lon, lat),
                    ellipse: {
                        semiMinorAxis: 10000.0,
                        semiMajorAxis: 10000.0,
                        //height: 200000.0,
                        material: Cesium.Color.GREEN
                    }
                });
            }
        }
 //primitive方式
        var instances = [];
        for (var lon = -180.0; lon < 180.0; lon += 4.0) {
            for (var lat = -70.0; lat < 70.0; lat += 4.0) {
                var ellipse = new Cesium.EllipseGeometry({
                    center: Cesium.Cartesian3.fromDegrees(lon, lat),
                    semiMajorAxis: 10000.0,
                    semiMinorAxis: 10000.0,
                    vertexFormat: Cesium.VertexFormat.POSITION_ONLY
                });
                var geometry = Cesium.EllipseGeometry.createGeometry(ellipse);
                var ellipseInstance = new Cesium.GeometryInstance({
                    geometry: geometry,
                    attributes: {
                        color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
                    }
                });

                instances.push(ellipseInstance);
            }
        }
        viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: instances,
            appearance: new Cesium.PerInstanceColorAppearance()

        }));

查看瀏覽器內存消耗情況:

Cesium學習筆記18--繪製對象-效率比較

Entity

1材質
空間對象可視化,不僅需要知道對象的空間位置,還需要知道對象的顯示樣式。顯示樣式就是通過材質來控制,比如說顏色、透明度、紋理貼圖、更高級的光照等等。我們常用到就是顏色和透明度。
以下代碼爲繪製一個半透明的紅色橢圓,設置material爲Cesium.Color.RED.withAlpha(0.5)透明度爲0.5的紅色:
    viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(103.0, 40.0),
        name: 'Red ellipse on surface with outline',
        ellipse: {
            semiMinorAxis: 250000.0,
            semiMajorAxis: 400000.0,
            material: Cesium.Color.RED.withAlpha(0.5),
        }
    });
2填充和邊框
填充和邊框共同組成了面狀對象的樣式,通過制定屬性fill(默認爲true)和outline(默認爲false)來確定是否顯示填充和邊框,material對應填充樣式,outlineColor和outlineWidth對應邊框的顏色和寬度。如一下內容繪製一個填充半透明紅色邊框爲藍色的橢圓:
 viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(103.0, 40.0),
        name: 'Red ellipse on surface with outline',
        ellipse: {
            semiMinorAxis: 300000.0,
            semiMajorAxis: 300000.0,
            height: 200000.0,
            fill:true,
            material: Cesium.Color.RED.withAlpha(0.5),
            outline: true, //必須設置height,否則ouline無法顯示
            outlineColor: Cesium.Color.BLUE.withAlpha(0.5),
            outlineWidth:10.0//不能設置,固定爲1
        }
    });
效果:
Cesium學習筆記14--繪製對象-Entity管理

3貼圖
通過設置material爲圖片url,可以將圖片填充到對象中:
 viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(103.0, 40.0),
            name: 'Red ellipse on surface with outline',
            ellipse: {
                semiMinorAxis: 250000.0,
                semiMajorAxis: 400000.0,
                height: 200000.0,
                fill:true,
                material: "./sampledata/images/globe.jpg",
                outline: true, //必須設置height,否則ouline無法顯示
                outlineColor: Cesium.Color.BLUE.withAlpha(0.5),
                outlineWidth: 10.0//windows系統下不能設置固定爲1
            }
        });
4垂直拉伸
有時候我們需要將面在垂直方向進行拉伸形成體,通過extrudedHeight即可實現這種效果,形成的體積任然符合它拉伸面的地球曲率。
viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(103.0, 40.0),
            name: 'Red ellipse on surface with outline',
            ellipse: {
                semiMinorAxis: 250000.0,
                semiMajorAxis: 400000.0,
                height: 200000.0,
                extrudedHeight: 400000.0,
                fill:true,
                material: Cesium.Color.RED.withAlpha(0.5),
                outline: true, //必須設置height,否則ouline無法顯示
                outlineColor: Cesium.Color.BLUE.withAlpha(0.5),
                outlineWidth:10.0//windows系統下不能設置固定爲1
            }
        });
5場景中entity管理
viewer.entities屬性實際上是一個EntityCollecton對象,是entity的一個集合,提供了add、remove、removeAll等等接口來管理場景中的entity。
查看幫助文檔,提供一下接口:
Cesium.EntityCollection.collectionChangedEventCallback(collection, added, removed, changed)
add(entity) → Entity
computeAvailability() → TimeInterval
contains(entity) → Boolean
getById(id) → Entity
getOrCreateEntity(id) → Entity
remove(entity) → Boolean
removeAll()
removeById(id) → Boolean
resumeEvents()
suspendEvents()
6選擇
在多數應用場景中,我們不僅需要繪製出空間對象還需要用鼠標拾取對象,cesium爲我們提供了scene.pick接口,如下代碼實現座標左鍵單擊實現對象的拾取:
 viewer.entities.add({
            id:'obj_id_110',
            position: Cesium.Cartesian3.fromDegrees(103.0, 40.0),
            name: 'Red ellipse on surface with outline',
            ellipse: {
                semiMinorAxis: 250000.0,
                semiMajorAxis: 400000.0,
                height: 200000.0,
                extrudedHeight: 400000.0,
                fill: true,
                material: Cesium.Color.RED.withAlpha(0.5),
                outline: true, //必須設置height,否則ouline無法顯示
                outlineColor: Cesium.Color.BLUE.withAlpha(0.5),
                outlineWidth: 10.0//windows系統下不能設置固定爲1
            }
        });

        var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
        handler.setInputAction(function (movement) {
            var pick = viewer.scene.pick(movement.position);
            if (Cesium.defined(pick) && (pick.id.id === 'obj_id_110')) {
                ;
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

以上代碼,在添加的entity中加入id唯一標識,然後利用ScreenSpaceEventHandler接口監聽鼠標事件,在左鍵單擊事件中,通過viewer.scene.pick獲取點擊出的對象,如果對象不爲空且id匹配則說明選中。

Primitive

1合併幾何圖形(Combing Geometries)
cesium給出primitive最大用意應該是提高渲染效率問題,當我們使用一個圖元繪製多個靜態對象時,這種優勢就顯現出來了。下面代碼時繪製兩個對象:
var instance = new Cesium.GeometryInstance({
            geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(105.20, 30.55, 106.20, 31.55),
                vertexFormat:Cesium.EllipsoidSurfaceAppearance.VERTEXT_FORMAT
            })
        });
        var instance1 = new Cesium.GeometryInstance({
            geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(107.20, 30.55, 108.20, 31.55),
                vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEXT_FORMAT
            })
        });
        viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: [instance, instance1],
            appearance: new Cesium.EllipsoidSurfaceAppearance({
                material:Cesium.Material.fromType('Stripe')
            })
        }));
我們可以使用PerInstanceColorAppearance爲每個實例賦不同顏色:
var instance = new Cesium.GeometryInstance({
            geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(105.20, 30.55, 106.20, 31.55),
                vertexFormat: Cesium.PerInstanceColorAppearance.VERTEXT_FORMAT
            }),
            attributes: {
                color:new Cesium.ColorGeometryInstanceAttribute(0.0,0.0,1.0,0.8)
            }
        });
        var instance1 = new Cesium.GeometryInstance({
            geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(107.20, 30.55, 108.20, 31.55),
                vertexFormat: Cesium.PerInstanceColorAppearance.VERTEXT_FORMAT
            }),
            attributes: {
                color: new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.8)
            }
        });
        viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: [instance, instance1],
            appearance: new Cesium.PerInstanceColorAppearance()
        }));
合併多個GeometryInstances 爲一個Primitive可以極大的提高性能,下面的例子創建了2592一顏色各異的矩形,覆蓋整個地球 :
var instances = [];
        for (var lon = -180.0; lon < 180.0; lon += 5.0) {
            for (var lat = -90.0; lat < 90.0; lat += 5.0) {
                instances.push(new Cesium.GeometryInstance({
                geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(lon, lat, lon + 5.0, lat +5.0)
                    }),
                    attributes: {
                        color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromRandom({
                            alpha: 0.5
                        }))
                    }
                }));
            }
        }
        viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: instances, //合併
            //某些外觀允許每個幾何圖形實例分別指定某個屬性,例如:
            appearance: new Cesium.PerInstanceColorAppearance()
        }));
2選取幾何圖形(Picking)
即使多個 GeometryInstance被合併爲單個Primitive,讓然可以獨立的被訪問。我們可以爲每一個GeometryInstance指定一個id,並且可以通過Scene.pick來判斷該實例是否被選取:
 var instance = new Cesium.GeometryInstance({
            geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(107.20, 30.55, 108.20, 31.55)
            }),
            id: 'rectangle-1',
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
            }
        });
        viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: instance,
            appearance: new Cesium.PerInstanceColorAppearance()
        }));
        var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
        //設置單擊事件的處理句柄
        handler.setInputAction(function (movement) {
            var pick = viewer.scene.pick(movement.position);
            if (Cesium.defined(pick) && (pick.id === 'rectangle-1')) {
                ;
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
3幾何圖形實例(Geometry Instances)
上面的例子中,我們已經用到了GeometryInstances,注意GeometryInstance與Geometry的關係:前者是後者的容器,多個Instance可以共用一個Geometry,並且可以通過GeometryInstances.modelMatrix屬性提供不同position、scale、rotate等位置、縮放、旋轉信息。例如,下面的例子使用同一個Geometry繪製了兩個Instance,一個位於另一個的上方:
var ellipsoidGeometry = new Cesium.EllipsoidGeometry({
            vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
            radii: new Cesium.Cartesian3(300000.0, 200000.0, 150000.0)//三軸半徑
        });
        //下方的實例
        var cyanEllipsoidInstance = new Cesium.GeometryInstance({
            geometry: ellipsoidGeometry,
            modelMatrix: Cesium.Matrix4.multiplyByTranslation(
               Cesium.Transforms.eastNorthUpToFixedFrame(
                Cesium.Cartesian3.fromDegrees(107.20, 30.55)),
                new Cesium.Cartesian3(0.0, 0.0, 150000.0),
                new Cesium.Matrix4()
            ),
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
            }
        });
        //上方的實例
        var orangeEllipsoidInstance = new Cesium.GeometryInstance({
            geometry: ellipsoidGeometry,
            modelMatrix: Cesium.Matrix4.multiplyByTranslation(
                Cesium.Transforms.eastNorthUpToFixedFrame(
                Cesium.Cartesian3.fromDegrees(107.20, 30.55)),
                new Cesium.Cartesian3(0.0, 0.0, 450000.0),
                new Cesium.Matrix4()
            ),
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE)
            }
        });
        viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: [
                cyanEllipsoidInstance, orangeEllipsoidInstance
            ],
            appearance: new Cesium.PerInstanceColorAppearance({
                translucent: false,
                closed: true
            })
        }));
4更新單個GeometryInstance的屬性
  var circleInstance = new Cesium.GeometryInstance({
            geometry: new Cesium.CircleGeometry({
                center: Cesium.Cartesian3.fromDegrees(107.20, 30.55),
                radius: 250000.0,
                vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
            }),
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                new Cesium.Color(1.0, 0.0, 0.0, 0.5)),
                show: new Cesium.ShowGeometryInstanceAttribute(true) //顯示或者隱藏
            },
            id: 'circle'
        });
        var primitive = new Cesium.Primitive({
            geometryInstances: circleInstance,
            appearance: new Cesium.PerInstanceColorAppearance({
                translucent: false,
                closed: true
            })
        });
        viewer.scene.primitives.add(primitive);
        //定期修改顏色
        setInterval(function () {
            //獲取某個實例的屬性集
            var attributes = primitive.getGeometryInstanceAttributes('circle');
            attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(
            Cesium.Color.fromRandom({
                alpha: 1.0
            }));
5場景中primitive管理
場景通過viewer.scene.primitives屬性來管理添加的primitive對象,primitives是PrimitiveCollection類型,查看幫助文檔:
Cesium學習筆記16--繪製對象-Primitive管理
提供一下接口來管理場景中primitive對象:
add(primitive) → Object
contains(primitive) → Boolean
destroy() → undefined
get(index) → Object
isDestroyed() → Boolean
lower(primitive)
lowerToBottom(primitive)
raise(primitive)
raiseToTop(primitive)
remove(primitive) → Boolean
removeAll()

演示 

這裏對entity幾個圖形做了一下簡單封裝供使用

/**
 * entity 添加實體
 * 
 * @type 類型
 * @param entity參數
 * 調用方法
 * var entity = new _cesiumTool({viewer:this.viewer}).createEntity({handleType:"cylinder",p:{length: Math.max.apply(null,height),slices:4}});
 */
_cesiumTool.prototype.createEntity =  function(param){
    try {
     var t = this,viewer = t.viewer,p = param.p,entity = null;
     if(param === null) return;
     
     switch(param.handleType){
         case "cylinder":{ 
             var cylinderEntity = viewer.entities.add({
                 cylinder: {
                     HeightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //表示相對於地形的位置。
                     length: p.length == null?600000:p.length,     //長度
                     topRadius: p.topRadius == null?0:p.topRadius,    //頂點半徑
                     bottomRadius: p.bottomRadius == null?600000 / 4 :p.bottomRadius,  //底部半徑
                     material: p.material == null?Cesium.Color.RED.withAlpha(.4) :p.material,  //填充材料
                     outline: p.outline == null? !0:p.outline,            //輪廓
                     numberOfVerticalLines: p.numberOfVerticalLines == null?0:p.numberOfVerticalLines, //垂直線數
                     slices:p.slices == null?128:p.slices,         //周邊數
                     outlineColor: p.outlineColor == null?Cesium.Color.RED.withAlpha(.8):p.outlineColor  //顏色輪廓
                 }
             });
             entity = cylinderEntity;
             break; 
         }
         case "box":{
             var boxEntity = viewer.entities.add({
                 name: 'Blue box',
                 position: Cesium.Cartesian3.fromDegrees(homePOsition[0], homePOsition[1], 0),
                 box: {
                     dimensions: new Cesium.Cartesian3(400000.0, 300000.0, 500000.0),
                     material: Cesium.Color.BLUE
                 }
             });
             entity = boxEntity;
             break; 
         }
         case "circle":{
             var circleEntity = viewer.entities.add({
                 position: Cesium.Cartesian3.fromDegrees(111.0, 40.0, 150000.0),
                 name: 'Green circle at height',
                 ellipse: {
                     semiMinorAxis: 300000.0,
                     semiMajorAxis: 300000.0,
                     height: 200000.0,
                     material: Cesium.Color.GREEN
                 }
             });
             entity = circleEntity;
             break; 
         }
         case "ellipse":{
             var ellipseEntity = viewer.entities.add({
                 position: Cesium.Cartesian3.fromDegrees(103.0, 40.0),
                 name: 'Red ellipse on surface with outline',
                 ellipse: {
                     semiMinorAxis: 250000.0,
                     semiMajorAxis: 400000.0,
                     material: Cesium.Color.RED.withAlpha(0.5),
                     outline: true,
                     outlineColor: Cesium.Color.RED
                 }
             });
             entity = ellipseEntity;
             break; 
         }
         case "corridor":{
             var corridorEntity = viewer.entities.add({
                 name: 'Red corridor on surface with rounded corners and outline',
                 corridor: {
                     positions: Cesium.Cartesian3.fromDegreesArray([
                     100.0, 40.0,
                     105.0, 40.0,
                     105.0, 35.0
                     ]),
                     width: 200000.0,
                     material: Cesium.Color.RED.withAlpha(0.5),
                     outline: true,
                     outlineColor: Cesium.Color.RED
                 }
             });
             entity = corridorEntity;
             break; 
         }
         case "polygon":{
             var polygonEntity = viewer.entities.add({
                 name: 'Red polygon on surface',
                 polygon: {
                     hierarchy: Cesium.Cartesian3.fromDegreesArray([115.0, 37.0,
                     115.0, 32.0,
                     107.0, 33.0,
                     102.0, 31.0,
                     102.0, 35.0]),
                     material: Cesium.Color.RED
                 }
             });
             entity = polygonEntity;
             break; 
         }
         case "polyline":{
             var polylineEntity = viewer.entities.add({
                 name: 'Red line on the surface',
                 polyline: {
                     positions: Cesium.Cartesian3.fromDegreesArray([75, 35,
                     125, 35]),
                     width: 5,
                     material: Cesium.Color.RED
                 }
             });
             entity = polylineEntity;
             break; 
         }
         default :{}   
     }
    } catch (error) {
        console.log("error mannager:" + error)
    }
    
    return entity;
 }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章