Cesiumの表示オブジェクトの動的なスタイル変更

# 地図上のオブジェクトの色を変更する

マップ上に表示したポリゴンやラインなどのオブジェクトの、スタイルを変更する手法について記載します。

成果物デモ公開先: http://jsdo.it/tkama/Ov1W
<img width="421" alt="スクリーンショット 2017-12-09 18.52.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/53918/52647a2c-2d23-5eb6-b1ed-4edcf642bac6.png">


## オブジェクトの表示
2017年 Cesium アドベントカレンダー 5日目のソースコードを改造してみます。

・Qiita記事
https://qiita.com/takahi/items/238c604f71ca0c1302d4
・ソースコード設置先
http://jsdo.it/tkama/kQnc

## 変更対象のオブジェクト(Entity)の取得

Cesiumのチュートリアルのサイト [Visualizing Spatial Data](https://cesiumjs.org/tutorials/Visualizing-Spatial-Data/)の[Managing Entities](https://cesiumjs.org/tutorials/Visualizing-Spatial-Data/#managing-entities)の章を参考にします。

手法： idを指定してオブジェクト(CesiumではEntity)を取得する

```js:getEntityById.js
var et =  viewer.entities.getById("Entity作成時に指定した文字か数字");
```
　予め、後で制御することを考えて、Entity作成時の戻り値を変数や配列で保持しておく手法を試しましたが、複数のEntityを生成した場合などでは上手く動作しませんでした。

## Entityへのスタイル変更

entities.getByIdで取得したentityに対して、表示仕様を変更します。
表示は`material`のパラメータを指定する事で実現します。
entityは階層構造をもっており、`entity.[オブイェクト（polygon,box,等）].material`と3階層目に当たります。

materialは色や透明度の他に、テクスチャなども貼ることが出来ます。

#### 色の設定
色と透明度はColorを定義することで指定がかのうです。
色の指定方法は、非常にたくさんあります.
https://cesiumjs.org/Cesium/Build/Documentation/Color.html

- RGBA指定 `Cesium.Color.fromBytes(red, green, blue, alpha, result)` 

- CSS表記  `Cesium.Color.fromCssColorString(color, result)`

- ランダムカラー `Cesium.Color.fromRandom({alpha:1.0});`

#### テクスチャ画像の指定

画像が公開されているURLを指定すればOKのようです。
その際に`http:`や`https:`など通信方式を表記する「URLスキーム」の記述は不要のようです。

例） 私のQiitaのアイコンのURI
https://qiita-image-store.s3.amazonaws.com/0/53918/profile-images/1473693208
↓
Cesiumのテクスチャとして指定する場合

' "//qiita-image-store.s3.amazonaws.com/0/53918/profile-images/1473693208" `

# 実装

元々水色で表示されているものを、ランダムカラーで置き換えるプログラムを記載しました。
ソースコード全体は、[こちら](http://jsdo.it/tkama/Ov1W)を参照して下さい。

```js:
//Cesium地図ビューワの作成
var viewer = new Cesium.Viewer('cesiumContainer');
var entities = viewer.entities;
var ids = 0;

//100個の3次メッシュを追加
for( var i = 0 ; i< 100 ; i++ ){
  viewer.entities.add(getJapan3rdmeshRectangle( 53394500 + i , 100*i , 0xccff6666 , String(53394500 + i) ));
}

//Rectangle Dynamic Color Control.
setInterval( 
    function(  ){
                 if (ids == 100 ){ 
                     ids = 0 ; //処理を循環させるための処置
                  }else{
                      //更新対象のentityのidを生成
                      var id = 53394500 + ids++;
                      //idを指定してentityを取得し、そのままmaterialにランダムカラーを指定
                      viewer.entities.getById( id ).rectangle.material  = Cesium.Color.fromRandom({alpha: 0.9});
                  };
    }, 1000);　//1000ミリ秒のスリープ

viewer.zoomTo(viewer.entities);

/**
 * 3次メッシュ３D棒グラフオブジェクト作成関数
 * @param  <Number>  meshcode3rd (required) 3次メッシュコード
 * @param  <Number>  h (required) 高さ（単位メートル）
 * @param  <string>　　　　color_abgr (required) 　色
 * @param  <string> description_text (required) オブジェクトの説明文
 * @retrun <object> ans_entities rectangleオブジェクト
 **/
function getJapan3rdmeshRectangle( meshcode3rd , h, color_abgr , description_text　){
    
    var strMeshcoe = String(meshcode3rd);
    var p = parseInt(strMeshcoe.slice(0,2));
    var u = parseInt(strMeshcoe.slice(2,4));
    var q = parseInt(strMeshcoe.slice(4,5));
    var v = parseInt(strMeshcoe.slice(5,6));
    var r = parseInt(strMeshcoe.slice(6,7));
    var w = parseInt(strMeshcoe.slice(7,8));
    var lat = p / 1.5 + q * 1 / 12 + r * 1 / 120;
    var lon = u + 100 + v * 0.125 + w * 0.0125;
    var ans_entities = {
            id:meshcode3rd ,
            description : "<p>"+description_text+"</p>",
            rectangle : {
                coordinates : Cesium.Rectangle.fromDegrees( lon , lat , lon+0.0125 , lat+0.008333333 ),
                height : h,
                extrudedHeight : 0,
                material : Cesium.Color.fromRgba( color_abgr )
            }
        };
    return ans_entities ;
}
```
# まとめ
　一度登録したオブジェクトを再度制御するためには、ライブラリであるCesiumの管理している仕様に合わせる必要があるため、結構躓くことがありました。