国土数値情報 行政区域データの GeoJSON を作る

# 国土数値情報 行政区域データのダウンロード

http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03.html
利用規約などはご自身でご確認ください。

# shapefile から GeoJSON に変換

`ogr2ogr` コマンドを使う。 該当コマンドは GDAL に含まれている。

```bash:gdalのインストール
$ brew install gdal
```

```bash:変換
$ ogr2ogr -lco "ENCODING=UTF-8" -f geoJSON N03-15_150101.geojson N03-15_150101.shp
```

# GeoJSON ファイルを分割

Node モジュールの `geojsplit` が使えそうだ。
https://www.npmjs.com/package/geojsplit

```bash:geojsplitのインストール
$ npm install geojsplit
```

`--key` オプションで指定すれば市区町村コード毎に分割できそう。

```bash:geojsplitのコマンド引数
Options:
  -a, --suffix-length     number of characters in the suffix length for split file names  [default: 4]
  -l, --geometry-count    number of geometries per split file                             [default: 10]
  --help, -h              display this message                                            [boolean]  [default: false]
  -v, --verbose           verbose output                                                  [boolean]  [default: false]
  -o, --output-directory  output directory                                                [string]
  -k, --key               split by key [property name properties]                         [string]
```

が、

```bash:実行！
$ ./node_modules/.bin/geojsplit -k N03_007 -o splited_geojson N03-15_150101.geojson 

<--- Last few GCs --->

[5065:0x102004c00]    61374 ms: Mark-sweep 1405.1 (1465.1) -> 1405.1 (1465.1) MB, 1093.7 / 0.0 ms  allocation failure GC in old space requested
[5065:0x102004c00]    62455 ms: Mark-sweep 1405.1 (1465.1) -> 1405.1 (1434.1) MB, 1081.3 / 0.0 ms  last resort gc 
[5065:0x102004c00]    63495 ms: Mark-sweep 1405.1 (1434.1) -> 1405.1 (1434.1) MB, 1040.1 / 0.0 ms  last resort gc 


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x7bba2ec0d31 <JS Object>
    1: _onToken [/Users/k-nakamura/tmp/N03-20150101_GML/node_modules/jsonparse/jsonparse.js:~331] [pc=0x3bac160a6a35](this=0x29e591481d61 <a Parser with map 0xb00d3c2d2e9>,token=3,value=0x7bba2e9c821 <String[1]: [>)
    2: write [/Users/k-nakamura/tmp/N03-20150101_GML/node_modules/jsonparse/jsonparse.js:~87] [pc=0x3bac16061929](this=0x29e591481d61 <a Parser with map 0xb00d3c2d2e9>,buffer=0x1ef4b...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: node::Abort() [/usr/local/bin/node]
 2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/usr/local/bin/node]
 3: v8::Utils::ReportOOMFailure(char const*, bool) [/usr/local/bin/node]
 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/local/bin/node]
 5: v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/usr/local/bin/node]
 6: v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
 7: 0x3bac15f08506
 8: 0x3bac160a6a35
 9: 0x3bac16061929
Abort trap: 6
```

heap out of memory で死亡 :innocent: 
全国を一気に処理は難しいみたいだ。

# 自前スクリプトで GeoJSON ファイルを分割

どちらにせよ巨大な JSON 文字列は一気に処理できないので、 geojsplit で分割したものを処理する。

```bash:Feature_100件毎に分割
$ mkdir split_by_num
$ ./node_modules/.bin/geojsplit -l 100 -o split_by_num N03-15_150101.geojson
```

```js:split.js
const fs = require('fs');
const files = fs.readdirSync('split_by_num');

let lastFeature;
files.forEach((file) => {
  let current = JSON.parse(fs.readFileSync(`split_by_num/${file}`, {encoding: 'utf8'}));
  current.features.forEach((feature) => {
    if (!lastFeature) {
      lastFeature = feature;
    } else {
      let city = feature.properties.N03_007;
      let lastCity = lastFeature.properties.N03_007;
      if (lastCity == city) {
        lastFeature.geometry.coordinates.push(feature.geometry.coordinates[0]);
      } else {
        if (lastCity) {
          let filePath = `split_by_city/${lastCity}.geojson`;
          if (fs.existsSync(filePath)) {
            console.log(`>>> ${filePath} already exists !!! <<<`);
            let already = JSON.parse(fs.readFileSync(filePath, {encoding: 'utf8'}));
            lastFeature.geometry.coordinates = lastFeature.geometry.coordinates.concat(already.features[0].geometry.coordinates);
          }
          fs.writeFileSync(filePath, JSON.stringify({
            type: "FeatureCollection",
            features: [lastFeature]
          }, null, "  "));
          console.log(`${filePath} has ${lastFeature.geometry.coordinates.length} polygons`);
        }
        lastFeature = feature;
      }
    }
  });
});
```

```bash:実行！
$ mkdir split_by_city
$ node split.js
```

# GitHub で確認

```bash:うp
$ cd split_by_city
$ git init
$ git add -A && git commit -m init
$ git remote add origin https://github.com/kozy4324/gyosei-kuiki-geojson.git
$ git push -u origin master
```

https://github.com/kozy4324/gyosei-kuiki-geojson

マルチポリゴンもよい感じである :v: :sun_with_face: :v:
https://github.com/kozy4324/gyosei-kuiki-geojson/blob/master/data/01517.geojson