[WORK]標高エリアjsonデータを読み込む
2017-06-19
標高エリアjsonデータを読み込む
先日の記事で作成した、不思議な文字列のjsonデータを読み込むクラスを作成してみる。読み込みの手順は下記の通りになる。
- require()でjsonを読み込む。
- 読み込んだ文字列を4文字ごとに区切る。
- 4文字に区切ったうち、末尾の’=‘を削る。
- 残りの文字列をbase64と似たアルゴリズムでデコードする。すると、24bitのデータが抽出される。
- 上位7bitが緯度、次の8ビット経度、残り9bitが3x3グリッドのデータ有無を表す。
- 緯度経度を16進数変換して4文字の文字列にする。これをkeyとする。グリッドの値はそのままvalueとする。
- 結果として下記の様なObjectになる。
area Object
1area = {
2 "NE": {
3 "000a": 511, // 北緯0度、東経10度の3x3グリッドには全てのグリッドにデータがあることを示す。
4 "0100": 511,
5 :
6 },
7 "NW": {
8 "0a0a": 511,
9 "0a0b": 511,
10 :
11 },
12 "SE": {
13 "0a01": 511,
14 "0a02": 511
15 :
16 },
17 "SW": {
18 "0a29": 8, // 南緯10度、西経41度の3x3グリッドには、y=1, x=0のグリッドにのみデータがあることを示す。
19 "0d26": 384
20 }
21};
上記処理のコード部分を抜粋して下記に置いておきます。
AltitudeService.js(一部抜粋)
1class AltitudeService {
2 _prepareArea() {
3 let areaJson = require('./altfilter.json');
4 let area = {
5 "NE": {},
6 "NW": {},
7 "SE": {},
8 "SW": {}
9 };
10
11 Object.keys(areaJson).map((areaName) => {
12 let coordinateList = areaJson[areaName].match(/.{1,4}/g);
13 coordinateList.forEach((coordinateBase64) => {
14 let coordinateKeyValue = this._decodeBase64(coordinateBase64);
15 area[areaName][coordinateKeyValue.key] = coordinateKeyValue.value;
16 })
17 });
18
19 return area;
20 }
21
22 _decodeBase64(base64) {
23 base64 = base64.replace("=", "");
24
25 let shift = 0;
26 let decodeValue = 0;
27 while(base64 !== ""){
28 let c = base64.substr(0, 1);
29 let code = c.charCodeAt(0) - 0x3f;
30 decodeValue += code<<shift;
31 shift += 6;
32 base64 = base64.substr(1);
33 }
34
35 let lat = (decodeValue >> 17) & 0x7f;
36 let lng = (decodeValue >> 9) & 0xff;
37 let grid = decodeValue & 0x1ff;
38
39 return {
40 key: this._lngLatToHex(lng, lat),
41 value: grid
42 };
43 }
44}