Mapbox GL JSで膨大なポイントデータを美しく視覚化できるヒートマップを作成する方法をご紹介します。ヒートマップは、特定のエリアにおけるポイントの密度をさまざまな色で表現したデータビジュアライゼーションです。ヒートマップは、データの「形」を見るのに役立ち、多くのポイントが密接に集まるエリアを強調します。
Mapbox GL JSのヒートマップレイヤーは、地図の移動やズームをしながら60fpsでスムーズにレンダリングします。特にクラスタリングと組み合わせた場合、高速に大量のデータを処理することができます。
以下の動画で、OpenStreetMapにマッピングされた40万本の樹木を、Mapbox GL JSのインタラクティブ・マップ上に表示した例をご覧ください。
ヒートマップを使ってみましょう
ヒートマップをすぐにでも使いたい方は、公式のサンプルや詳しいチュートリアルをご覧ください。この記事では概要をご紹介します。
まず、スタイルに「ヒートマップ」タイプのレイヤーを追加します。
ヒートマップは用途に応じて様々なカスタマイズが必要です。Mapbox GL JSでは、レイヤーの外観をリアルタイムに制御するための、描画スタイルプロパティを提供しています。各項目を見ていきましょう。
heatmap-radius
このプロパティは、各ポイントの「影響半径」をピクセル単位で設定することで、ヒートマップの詳細を設定できます。
値を高くすると、より滑らかで一般的な外観になります。このプロパティでは、ズームインしたときの見た目を調整することができます。
heatmap-color
このスタイルプロパティは、ヒートマップデザインの重要な側面である、マップ上の各ピクセルの「密度」値をどの色に変換するかを制御します。
このプロパティの値は、0.0〜1.0の密度値を色にマッピングする関数です。この例では、最も疎らな場所を青にし、混雑している場所では黄色から赤へと徐々に移行するように設定しています。
heatmap-intensity
このプロパティは、ヒートマップの外観を調整することができます。値が高いほど、各ポイントが見た目に与える "重み"が大きくなります。例えば、heatmap-intensityを10.0に設定すると、データセットを10回複製し、デフォルトの1.0の値でレンダリングすることと同じになります。
heatmap-intensityは、異なるズームレベルに対してヒートマップの見た目を調整するのに便利です。これを一定のままにすると、低いズームレベルのヒートマップは、ポイントが視覚的に近くなるため、より重く見えます。
heatmap-weight
このスタイルプロパティは、データ駆動型であること以外は、heatmap-intensityと同じ働きをし、個々のポイントの特徴的な特性に応じた強度を調整することができます。
この例では、point_countの値が100のポイントは、point_countが1の100ポイントと同じに見えます。クラスタリングと組み合わせることで、描画するポイントの数を大幅に減らし、ヒートマップの性能を向上させることができます。
heatmap-opacity
このプロパティは、ヒートマップレイヤーの不透明度を制御します。
heatmap-opacityの便利な応用として、ズームインしたときにヒートマップをフェードアウトしてより詳細に見えるようにすることができます。
ヒートマップの仕組み
数学用語で言うと、Mapbox GLヒートマップはガウシアンカーネルを用いた二変量(2D)カーネル密度推定法です。つまり、各データポイントは、その周りに「影響力」のある領域(カーネルと呼びます)を持ち、ポイントから離れるにつれて影響力の数値(これを密度と呼びます)が減少していきます。画面の各ピクセルにあるすべてのポイントの密度値を合計すると、合成された密度値が得られ、それをヒートマップの色にマッピングします。
OpenGLでこれを実装するには、各データポイントについて、カーネル(ぼやけた円のように見える)をオフスクリーンのハーフフロートテクスチャに加法混色(カーネルが重なったときに値が合計されるように)で描き、別のステップでこのグレースケールテクスチャに色を付けます。
理想的には、対応するポイントから遠く離れていても、この値が完全にゼロになることはないため、データポイントごとに、ピクセルごとに密度を個別に計算する必要があります。しかし、描画するポイントの数がわずかでも、数十億回の演算が必要になり、コストがかかりすぎます。
高速化するために、各カーネルを、外側のすべての値が非常に小さくなるのに十分な大きさ(ある閾値以下、ここでは任意に1 / 255 / 16を選択)の正方形にクロップします。このサイズは各ポイントの重さと強さに依存し、重いポイントにはより大きな描画領域が必要です。
さらに、密度の描画には、マップの解像度よりも4倍小さな辺を持つダウンスケールされたテクスチャを使用し(その結果、各ポイントに描画するピクセル数が16倍になります)、カラー化ステップで線形補間によりテクスチャをアップスケールし直しています。ヒートマップの場合、これは視覚的にはフル解像度レンダリングとほとんど区別がつきませんが、かなり高速化されます。
ヒートマップへの異なるアプローチ
他のプラットフォームでは、ヒートマップはサーバー上の静的なイメージタイルとしてレンダリングされます。
Mapboxのアプローチは、Mapbox GLを中核に活用し、60fpsでスムーズなトランジションをレンダリングし、正しいカラーランプの選択から各ズームレベルでのポイント半径の調整まで、ヒートマップレイヤーのあらゆる側面をスケールで制御する機能を提供します。
ヒートマップを、データ駆動型スタイル、式、クラスタリングなどの他のGL JS機能と組み合わせることで、データをよりユニークに構成することができます。
より詳細はGL JSのヒートマップの例とチュートリアルをご覧ください。
*本記事は、Mapbox Inc. Blogの翻訳記事です。