Help us understand the problem. What is going on with this article?

地理院地図の標高タイル(CSV)を描画してみた

More than 3 years have passed since last update.

国土地理院が提供している API の一つに「標高タイル」というものがあります。

タイルというと、Googleマップや OpenStreetMap などの Web地図では通常、画像を指しますが、標高タイルAPIでは 「画素毎の高度(m)」 が取得できます。

これは面白い、ということで使ってみました。

サンプル

Google Map

img1

標高タイルAPI で取得した標高値を描画

img1

何をしているか?

下は、このサンプルのコードの抜粋ですが、ポイントは2つ

  • getTile で通常 img 要素を生成して返すが、代わりに canvas 要素に返す
  • 標高API をコールして得られた CSV をパースし、 高さに応じた色を計算して、canvas に矩形を描画する

さすがに1ピクセル毎に描画すると重すぎるので、初期値では 16ピクセルずつに間引きしています(画面の DotSize で変更できます)。

クライアント側でレンダリングしているので、色などが動的に変更できます。

    map.mapTypes.set("GsiMaps", {
      name:"標高タイル",
      tileSize:new google.maps.Size(256,256),
      minZoom:14, // 標高タイルは Lv:14 しか用意されてないので
      maxZoom:14, 
      getTile:function(tileCoord, zoom, ownerDocument) {

        // 普通は img だけど、標高タイルは CSV で画素毎の標高値が取得できるので、
        // クライアント側で描画するために Canvas を使う
        var canvas = ownerDocument.createElement("canvas");
        canvas.width = 256;
        canvas.height = 256;

        var x = (tileCoord.x % Math.pow(2, zoom)).toString();
        var y = tileCoord.y.toString();

        // 各画素の標高値を取得する
        canvas.tileUrl = "http://cyberjapandata.gsi.go.jp/xyz/dem/" + zoom +  "/" + x + "/" + y + ".txt";
        // 標高を描画する
        renderDem(canvas);
        renderedTiles[canvas.tileUrl] = canvas; // タイル再描画の為にとっておく
        return canvas;
      }
    });

    // 標高タイルを描画する
    function renderDem(canvas) {
      var ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, 256, 256);

      $.get(canvas.tileUrl, function(data) {
        // CSV が得られるのでパース
        var lines = data.split(/\r\n|\r|\n/);
        for (var i = 0; i < lines.length; i+=dotSize) {
          var cols = lines[i].split(',');
          for (var j = 0; j < cols.length; j+=dotSize) {
            if (cols[j] == 'e') { // エラーの画素には 'e' が入ってる
              continue;
            }

            // 標高0m を startColor、標高1000mを endColor としたグラデーション色を設定する。
            ctx.fillStyle = $.xcolor
            .gradientlevel(startColor, endColor, cols[j] / 1000.0 * 100.0, 100)
            .getCSS();
            ctx.fillRect(j, i, dotSize, dotSize);
          }
        }
      });
    }

まとめ

ただの標高値を地図に表すなら画像でいいじゃん!とか言われそうですが、よいアイデアが浮かばなかったのでまずは素直に使ってみました。

たとえば、移動手段による移動コストの違い(車だと坂道余裕だけど自転車だとキツい)みたいなのを視覚化するのに使えるような気がします。

今回は、Canvas を使ったのでこの程度ですが、WebGL とかを使えば、Google Map の地形図に負けない、美しい3D地図が描画できるはずです。

他に例を見ない、野心的な試みだと思うので、何か面白い使い方ができるといいなと思います。

amay077
ランチの時は呼ぶといい!
https://blog.amay0777.net/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away