deck.glを使って、D3.jsで計算したネットワークグラフをWebGLで描画する

概要

deck.glは、Uber社が巨大なデータセットを地図上に可視化するために作ったフレームワークですがバージョンアップのごとに進化を遂げ、現在では地理空間データに関わらず、様々な座標系に対応したビジュアライゼーションフレームワークになっています。

ここでは、D3を使って計算したネットワークグラフをDeck.glを用いてWebGLに描画します。

ネットワークグラフをWebGLを使って描画する

DENO

サンプルコード

解説

deck.glのビューシステム

deck.glでは、デフォルトで地理空間データを描画するためのビュー(Mapview)が設定されています。
deck.glにはMapviewの他にも、さまざまな座標データに対応したviewが用意されおり、開発者が地理空間データ以外のデータでもwebGLを用いて描画することができます。
(各viewには、データの座標をスクリーン上の座標に変換する投影法と、カメラのコンントローラー設定がワンセットとなってパッケージ化されています)
ここでは、3D(x,y,z)座標の投影法と、指定した座標を中心として回転するカメラコントローラーが定義された(OrbitView)を使って、D3で生成したネットワークグラフをwebGL上に描画します。

d3.forceSimulationの計算結果をdeck.glに反映させる

ネットワークグラフの座標計算について詳しい仕組みは d3-force のドキュメントを参照してください。
ここでのポイントは、forceSimulationの内部タイマーによって送出されるtickイベントを捕まえて、シュミレーターによって計算されたノードとリンクの座標をdeck.glのScatterplotLayerLineLayerに反映している部分になります。
基本的には、ノードとリンク用のステートを生成し、tickイベント内で、計算された座標をレイヤーに反映するわけですが、この時重要なポイントとして計算結果が収められたデータオブジェクトを別オブジェクトとして複製する必要があります。
D3.jsはシミュレーターに渡されたデータオブジェクトを破壊的に更新しますが、これをそのままステートに渡してもアップデートが検知されずレンダーが走らないためです。
そのため、JSON.stringifyJSON.parseを使ったあまりスマートでないディープコピーを行なっています。これはもうちょっと改善の余地があるかも。

ネットワークグラフ自体も3Dにする

せっかくなので、z軸も含めてネットワークグラフの座標計算を行うd3-force-3dプラグインを使って3Dのネットワークグラフも作ってみました。
基本的な内容は変わっていません、d3-forceライブラリを使っていたところを、d3-force-3dライブラリに変え、ノードを描画するのにScatterplotLayerではなくPointCloudLayerを使うように変更しただけです。(ScatterplotLayeにはz軸を描画する機能がなかったので、PointCloudLayerに変更しました)

サンプルコード

deck.glには、エレメントにテクスチャーを貼ったりマテリアルを細かく設定する機能備わっているので、より細かくカスタマイズしたネットワークグラフを描画することもできます。