やはり少し頭を使って、元になる国土地理院の海岸線データの特徴を調べてみます。
1.海岸線データの固まり方
先にも言いましたが、元データは県別のxmlデータになっていて、行政界、島毎にタグが分かれています。それを緯度経度だけ抽出してくると以下ののようになります。
- 35.04924833 136.83906528
- 35.05145167 136.83815250
- 35.05175111 136.83802834
- 35.05899417 136.87838278
- 35.05921944 136.87846166
- 35.05952000 136.87857805
- 35.05949694 136.87866195
- 35.05947139 136.87874555
- 35.05914306 136.87861805
- 35.05894917 136.87855139
- 35.05899417 136.87838278
- 35.05730000 136.87774750
- 35.05771861 136.87788778
途中、2行の空白行がありますが、そこが行政界の区切り、あるいは島のデータの始まりを表します。上記サンプルを見ると、2つ目のデータの固まりのデータの始まりと終わり(6行目と13行目です)が同じ緯度経度になっています。つまりこれは島だということです。
前回のプログラムでは、以下に注意しました。
- 行政界、島の区切りを示す空白行は残す。
- 空白行を出力したところで間引きカウンタを0クリアして、空白行に続く先頭データは積極的に出力する。
しかし、特に島のデータに顕著にでましたが、あまり間引く数が大きいときはデータの固まりの最後(空白行の直前のデータ)も残してやらないと島が閉曲線になりません。
2,改良版プログラム
ということで、島の最後のデータも残してやるように改修しました。
- #!/usr/bin/python
- # coding: utf-8
- import sys
- if __name__ == "__main__":
- argv = sys.argv # コマンドライン引数を格納したリストの取得
- argc = len(argv) # 引数の個数
- # print argv
- # print argc
- fi = open(argv[1], 'r')
- fo = open(argv[2], 'w')
- # n行に1回出力するようにする
- ct = 0
- preLine = ""
- for line in fi:
- if line.strip() == "": # 島等のデータとの境界である空白行は残すようにする
- if (preLine.strip() != ""): # 空白行の直前のデータは残す(島の閉曲線を守るため)
- fo.write(preLine)
- fo.write(line)
- ct = 0 # 島のデータは少ないので1行でも残す
- preLine = line
- continue
- if ct == 0:
- fo.write(line)
- ct = ct + 1
- preLine = line
- if ct == 100: # 100行に1回出力する
- ct = 0
- fi.close()
- fo.close()
さてこれで1/100に間引いてみましたが、どうもデータのサイズが思うように小さくなりません。
3.改良版の処理結果を見る
再度、処理結果を調べてみました。
- 35.08614861 136.89070723
- 35.08342250 136.86787278
- 35.05776194 136.84691778
- 35.06403806 136.84048584
- 35.05175111 136.83802834
- 35.05175111 136.83802834
- 35.05899417 136.87838278
- 35.05899417 136.87838278
確かに島のデータは残されるようになっていますが、思いの外国土地理院のデータには小島がしっかりはいっているようで、同じ緯度経度が2回連続する固まりが大量にありました。こいつらは改良版のプログラムではどんなに間引率を大きくしても残されるようにしてあるため、思ったようにデータのサイズが小さくならなかったようです。
でも実際日本地図を使うようなときはこんな小島、表示もされないのでデータの無駄です。
4.小島のデータを削除する
手作業で削除するかとも思ったんですが、すぐに諦めました。さすがにデータのサイズが小さくならない原因だけあって大量に存在しています。あきらめて、2行同じ緯度経度のデータが続く箇所はフィルタするようなプログラムを作りました。(行政界の他のところで偶然そういう場所がないか、という恐れはありますがまあ少しくらい抜けてもそれに気づくほど拡大して使うことはないでしょう。もし使う必要があるなら、それはもう手作業でなんとかしてやるしかありません)
- #!/usr/bin/python
- # coding: utf-8
- import sys
- if __name__ == "__main__":
- argv = sys.argv # コマンドライン引数を格納したリストの取得
- argc = len(argv) # 引数の個数
- # print argv
- # print argc
- fi = open(argv[1], 'r')
- fo = open(argv[2], 'w')
- # n行に1回出力するようにする
- ct = 0
- preLine = ""
- for line in fi:
- if line.strip() == "": # 島等のデータとの境界である空白行は残すようにする
- if (preLine.strip() != ""): # 空白行の直前のデータは残す(島の閉曲線を守るため)
- fo.write(preLine)
- fo.write(line)
- ct = 0 # 島のデータは少ないので1行でも残す
- preLine = line
- continue
- if preLine != line:
- fo.write(preLine)
- else:
- preLine = ""
- line = ""
- continue
- preLine = line
- fi.close()
- fo.close()
かなり手抜きプログラムですが、これでサイズを1/100にし、かつ2行しかないような小島のデータを削除して、データサイズが1.4MBまで縮小できました。結果を以下に示します。
先日の海岸線とほとんど見た目は変わりません。よく見れば、小さな小島は消えているんですがね。