presimplify example

D3.jsとTopoJsonライブラリを使って地理情報を動的に簡素化する。

クライアントサイドのtopojsonには読み込んだ地理データを簡素化するpresimplifyという機能があります。
今回はこの機能を使った地形データの動的な簡素化のサンプルをつくりました。

presimplify example

example

スライダーを右に動かすと地形が簡素化されます。

解説

全く持って上手く説明できる自信がないのですが、ただコードを置いておくのもなんなので一応解説っぽいものをかいてみました。

ジオストリーム

D3を用いて地理情報を描画する際、projection関数とpath関数を作成して描画処理を行います。

D3では地理情報がもつ緯度経度をpixcelの座標へと変換するデータの流れを「ジオストリーム」と呼びます。
そしてそのジオストリームに対して変換処理を行う関数をストリームリスナーと呼びます。
d3.geoMercatorは、メルカトル図法を基準にして緯度経度をpixcel座標へと変換するストリームリスナーを生成しています。
今回はこのメルカトル図法のストリームリスナーをラップしてgeometoryを簡素化するストリームリスナーを作りました。

topojson.presimplify

topojson.presimplifyメソッドは、引数で渡されたtopojsonに簡素化に執拗なジオメトリ情報を追加したコピーを返します。

presimplifyメソッドを実行するとgeometoryの各点ごとに隣接した三点を結んだ三角形の面積が付加されます。この面積の値に閾値を設定してそぎ落とすことでgeometoryの簡素化を行うことができます。
詳しいアルゴリズムについては以下を参照してください。

Line Simplification

簡単に説明すると「隣接する三点を結んで作成した三角形の面積が小さい座標点は、隣接する座標点との変化が少ない点なので、無くしちゃっても問題ないよね!」みたいな感じです。

カスタムストリームリスナー

d3.geo.transformを利用するとジオストリーム(緯度経度をpixcel座標に変換するプロセス)を途中でフックし、独自のストリームリスナーを生成することができます。
topojson.presimplifyメソッドで付加した面積の値はストリームリスナーに引数として渡されるので、閾値を設定しgeometoryをフィルタリングしています。

カスタムストリームリスナーの中で、隣接する三点を結んだ三角形の面積が閾値を超える座標点のみを変換対象とし、それ以外の座標は切り捨ててしまうことで、座標点を減らし簡素化した図形を描画しています。