CODE HOUSE


Hello, I'm a freelance software engineer.


[WORK] 標高エリアデータのjsonを作成する

ブログの更新があまりにも放置状態なので、日々の作業の前に今日したいことを少しだけ書いていくことにする。

mapアプリ

mapに関するアプリは以前からずっと作成を細々と続けている。まともにリリース、世の中に公表したことはまだ無い。多少の問題はあっても、さっさと何かしらリリースしたい。

標高エリアデータの作成

今日すること。標高エリアデータの作成。手元には、全世界の標高データのあるエリアと無いエリア(主に海)を表したバイナリデータがある。このデータは経度360度、緯度180度を更に3x3のグリットに区切って、そこに標高データがあるかどうかを0/1のビットで表したデータである(約72kb)。バイナリデータはウェブアプリ(javascript)では扱いにくい。なのでこれをjson形式のデータにしてみるのが今日の課題。

jsonデータの仕様

さて目的とするjsonデータの仕様であるが、なかなか悩ましい。緯度は北緯、南緯合わせて180度。これを16進数の文字列にすると、最大で2Byteになる。経度は360度。16進数の文字列にすると最大で3Byteになる。合わせて5Byte、これを標高データのある座標だけを並べたjsonを考えてみると、下記のようになる。

area.json
1{
2  "area": ["0872D", "0872E", ...]
3}

多くのデータで文字列の頭は0になる。それをわかっていて座標を5byteで表すのは、データサイズ的にもったいない気がする。

そこで、データを北緯、南緯、東経、西経の4エリアに分けて考える。すると、座標は4byteのデータで表すことができる。

area.json
1{
2  "area": {
3    "NE": ["872D", "872E", ...],
4    "SE": [...],
5    "NW": [...],
6    "SW": [...]
7  }
8}

最初に書いたが、実際には緯度、経度のデータはさらに3x3のグリットに分かれている(何故3x3なのかは後日書くかも)。そして多くのエリアでは、3x3全てのグリッドにデータが存在すると思われる。なので、データの欠けている場合だけ、更に座標の文字列の後ろにその情報を追加する。

3x3のグリッドの何処が欠けているかを単純に表すと、9bitのデータ(512パターン)になる。16進数で表すと3Byte、Base64で変換しても2Byteになる。

さて、実際のデータでグリッドの欠けるパターンには何パターンあるのかを調べてみることにする。512パターン全てが現れるとは考えにくい。

(ここで、pythonでコードを書いて調べてみた・・・)

意外にも418パターンも存在した。仕方がないのでグリッドのデータが存在しない場合のみ、Base64で変換した2Byteを座標文字列の後ろに追加することにする。

area.json
1{
2  "area": {
3    "NE": ["872DEg", "872E", ...],
4    "SE": [...],
5    "NW": [...],
6    "SW": [...]
7  }
8}

ここで、出来上がったjsonのファイルサイズを見てみると、元の72kByteを大幅に超えている・・。

最終的に・・

いろいろ考えていて、ふと思いついた。緯度のデータが90度で7bit。経度が180度で8bit。3x3のグリッドが9bit。合わせるとちょうど24bitで6の倍数になることに気がついた。するとbase64エンコードの様に6bitづつに分けて文字で表すと、常に4Byteのデータでグリッドを表すことができる。最終的には下記の様な不思議な文字列のjsonデータが出来上がったのである。

area.json
1{
2  "area": {
3    "SW": "?kG[SfG[?ZG[.....",
4    "NE": "[email protected][email protected]=.....",
5    "SE": "GosXWpGX?~SW.....",
6    "NW": "@OJ=cKI=~FI=....."
7  }
8}

変換のコードをgithubに置いておきます。

mm-git/filter_convert