Pythonで世界地図-11(日本地図に都府県境界線を追加するライブラリ)

このライブラリだとjapanmapがver upした時にプログラムを変更しなければいけないので、japanmapの作者の了解を得まして、ライブラリ専用のデータを作成しました。
https://qiita.com/ty21ky/items/a5023ed4e07128d81c7b

#####注意
2018/06/28 14:00頃にjapanmapのデータが更新されましたので、それ以前にjapanmapをインストールした方は「pip install -U japanmap」を実行してください。
下記のjapan_border.pyも変更しました。


一度異常が無いことを確認したらjapanmapの更新をしないことをオススメします。データが変更になっている可能性があります。変更になったらjapan_border.pyも変更する必要があります。

Pythonで世界地図-10(日本地図に都府県境界線を追加する)
https://qiita.com/ty21ky/items/f4af8009be4e0407b6fd
を簡単なライブラリにしました。
詳細は上記を参照ください。
#####使い方
japan_border.pyを世界地図を実行するプログラムと同じフォルダに保存するか、pythonパスが通っているフォルダに保存します。

pythonパスは、
LibreOfficeバンドルのPythonにUbuntu - Pythonのパッケージのパスを追加する
https://qiita.com/ty21ky/items/3b944a7abe23e3bcaf8f
を参考にしてください。

私のUbuntuStdioの環境では、/home/ty/.local/lib/python3.6/site-packagesに保存しました。

```python:japan_border.py
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from japanmap import *

qpqo = get_data()
pnts = pref_points(qpqo)

color1 = 'gray' #色・線幅・線種のデフォルト値
linewidth1 = 0.5
linestyle1 = '--'

def opt(color, linewidth, linestyle): #色・線幅・線種の指定
    global color1
    global linewidth1
    global linestyle1

    color1 = color
    linewidth1 = linewidth
    linestyle1 = linestyle

def prefectural_bound(color = color1, linewidth = linewidth1, linestyle = linestyle1): #県境
    opt(color, linewidth, linestyle)

    shikoku_bound()
    kyushu_bound()
    chugoku_bound()
    kansai_bound()
    chubu_bound()
    kanto_bound()
    tohoku_bound()

def print_bound(no, start, end, start_p): #県境の描画
    ii = 0
    for n in no:
        a = pnts[n]

        x = []
        y = []

        for i in range(start[ii], len(a) - 1 - end[ii]):
            x.append(a[i][0])
            y.append(a[i][1])

        if start_p[ii]:
            x.append(a[0][0])
            y.append(a[0][1])

        plt.plot(x, y, linewidth = linewidth1, color = color1, linestyle = linestyle1)
        ii += 1

def shikoku_bound(color = color1, linewidth = linewidth1, linestyle = linestyle1): #四国県境
    opt(color, linewidth, linestyle)

    no = [35,36,38]             #徳島県,香川県,高知県
    start = [59,0,113]          #0は最初から、それ以外はその番号から
    end = [0,71,0]              #0は最後まで、それ以外は最後の番号から数値分を引く
    start_p = [True,False,True] #Trueの場合、最初のポイントが必要

    print_bound(no, start, end, start_p)

def kyushu_bound(color = color1, linewidth = linewidth1, linestyle = linestyle1): #九州県境
    opt(color, linewidth, linestyle)

    no = [39,40,41,43,44,45] #福岡県,佐賀県,長崎県,大分県,宮崎県,鹿児島県
    start = [18,49,0,0,20,0]
    end = [121,17,167,104,61,113] 
    start_p = [False,False,False,False,False,False] 

    print_bound(no, start, end, start_p)

def chugoku_bound(color = color1, linewidth = linewidth1, linestyle = linestyle1): #中国県境
    opt(color, linewidth, linestyle)

    no = [30,31,32,33,34] #鳥取県,島根県,岡山県,広島県,山口県
    start = [23,0,39,0,0]
    end = [14,50,70,113,157]
    start_p = [False,False,False,False,False]

    print_bound(no, start, end, start_p)

def kansai_bound(color = color1, linewidth = linewidth1, linestyle = linestyle1): #関西県境
    opt(color, linewidth, linestyle)

    no = [23,24,25,26,27,27,27,28,29] #三重県,滋賀県,京都府,大阪府,兵庫県,兵庫県,兵庫県,奈良県,和歌山県
    start = [138,17,93,0,0,120,25,0,83]
    end = [0,15,0,48,126,0,74,65,0] 
    start_p = [True,False,True,False,False,True,False,False,True] 

    print_bound(no, start, end, start_p)

def chubu_bound(color = color1, linewidth = linewidth1, linestyle = linestyle1):
    opt(color, linewidth, linestyle)

    no = [14,15,16,17,18,19,20,20,21,22] #新潟県,富山県,石川県,福井県,山梨県,長野県,岐阜県,岐阜県,静岡県,愛知県
    start = [22,32,68,68,0,0,52,106,0,0]
    end = [34,0,0,0,36,65,40,0,76,78]
    start_p = [False,True,True,True,False,False,False,True,False,False] 

    print_bound(no, start, end, start_p)

def kanto_bound(color = color1, linewidth = linewidth1, linestyle = linestyle1):
    opt(color, linewidth, linestyle)

    no = [7,8,9,10,10,11,12,13] #茨城県,栃木県,群馬県,埼玉県,埼玉県,千葉県,東京都,神奈川県
    start = [0,0,0,0,42,99,0,81]
    end = [69,0,31,26,0,0,19,0]
    start_p = [False,False,False,False,True,True,False,True] 

    print_bound(no, start, end, start_p)

def tohoku_bound(color = color1, linewidth = linewidth1, linestyle = linestyle1): #東北県境
    opt(color, linewidth, linestyle)

    no = [1,2,3,4,5,6] #青森県,岩手県,宮城県,秋田県,山形県,福島県
    start = [74,0,109,27,6,42]
    end = [35,136,24,12,0,0]
    start_p = [False,False,False,False,True,True] 

    print_bound(no, start, end, start_p)
```

使用例
地図を表示するコードに2行追加します。
地図の種類は　projection='cyl'　だけです。
他の地図は座標をx,y=map(x,y)で変換しなければいけないのですが、スコープ外のようで、エラーがでます。
「ortho」の地図にも県境を表示することができました。
importすると、import先のコードが現在のコードにすべて読み込まれるので同じようにすればよいだけでした。
ただし、変数でも関数でも前に「japan_border.」付けなくてはいけません。
import japan_borderas as jb
とすると楽ですね。

```python:
#!/usr/bin/python3
# coding: UTF-8

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

import japan_border #都府県境界線

lon1 = 137.0
lat1 = 37.0
lon2 = 10.0
lat2 = 10.0

map = Basemap(llcrnrlon = lon1 - lon2, llcrnrlat = lat1 - lat2, urcrnrlon = lon1 + lon2, urcrnrlat = lat1 + lat2, resolution = 'i', projection='cyl')

map.drawcoastlines() #海岸線

#都府県境界線を表示
japan_border.prefectural_bound(color = 'b', linewidth = 1, linestyle = '-') #色（青）、線幅、線種を指定
#japan_border.prefectural_bound() #デフォルト表示　color = 'gray', linewidth = 0.5, linestyle = '--'破線

#各地方ごとに表示する例
#japan_border.shikoku_bound() #四国地方
#japan_border.shikoku_bound(color = 'b', linewidth = 1, linestyle = '-')

plt.show()
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/238800/ab1d6e92-9b30-aac4-66fa-a73dd31ad279.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/238800/9af2383c-ffce-b183-3f40-25d4f5a5a515.png)

色、線幅、線種を指定する引数の所をもっとスッキリしたいのですが、スキルが不足しているためかうまくいきません。

グローバル変数にデフォルトの値を入れて、関数内で引数の値を代入しても失敗？か代入出来ません。
同じ名前のグローバル変数とローカル変数が出来ているみたいです。（解決：globalキーワード）
#####問題点
2018/06/28 14:00頃にjapanmapの作者にデータの修正をお願いしたところ、すぐに対応していただきましたが、お願いした所以外も沢山修正されていて、下記のように余計な線が入っていました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/238800/7b229416-3ec7-ef33-9aaa-9eb5abccb380.png)

他の人が作成したデータを加工しているので、元のデータが変更になれば変わってしまいます。

やっぱり専用のデータが必要かな。

とりあえず見つけた所は修正していますが、漏れている可能性もありますので修正方法を書きます。

japanmapのデータは１つの県の外周データがエンドレスで記載されています。

１．plt.plot()ではエンドレスではないので、始点と終点の間は線が抜けてしまうので、必要な場合は終点の後ろに始点の座標を追加しています。(変数start_pがTrueの場合)
２．海岸線はjapanmapとmpl_toolkits.basemapでは座標のとり方が全然違うので線が２重になり見苦しいのでjapanmapの海岸線の部分は削除しています。
３．隣の県との境も必ず線が２重になります。この場合同じデータなので線は２重に見えないのですが、県境の線種を破線に指定した場合に実線に見えてしまうので、どちらかの県を削除しています。
地方毎の一番端の境界線は重複しているので、破線に見えずに実線に見えます。
４．県境に必要な部分を除き、始点側を変数startの値分、終点側を変数endの値分を削除しています。
始点側に１本はみ出していたらstartの値を1増やします。
終点側に１本はみ出していたらendの値を1増やします。

修正方法を書いては見たものの、始点・終点がわからないと修正は難しいですね。

一度確認して異常がなければ、japanmapの更新をしないことをオススメします。
データが変更になっている可能性があります。

古いjapan_border.py

```python:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from japanmap import *

qpqo = get_data()
pnts = pref_points(qpqo)

def prefectural_bound(color = 'gray', linewidth = 0.5, linestyle = '--'): #県境
    shikoku_bound(color, linewidth, linestyle)
    kyushu_bound(color, linewidth, linestyle)
    chugoku_region(color, linewidth, linestyle)
    kansai_region(color, linewidth, linestyle)
    chubu_region(color, linewidth, linestyle)
    kanto_region(color, linewidth, linestyle)
    tohoku_region(color, linewidth, linestyle)

def print_bound(no, start, end, start_p, color, linewidth, linestyle): #県境の描画
    ii = 0
    for n in no:
        a = pnts[n]

        x = []
        y = []

        for i in range(start[ii], len(a) - 1 - end[ii]):
            x.append(a[i][0])
            y.append(a[i][1])

        if start_p[ii]:
            x.append(a[0][0])
            y.append(a[0][1])

        plt.plot(x, y, linewidth = linewidth, color = color, linestyle = linestyle)
        ii += 1

def shikoku_bound(color = 'gray', linewidth = 0.5, linestyle = '--'): #四国県境
    no = [35,36,38]             #徳島県,香川県,高知県
    start = [59,0,113]          #0は最初から、それ以外はその番号から
    end = [0,71,0]              #0は最後まで、それ以外は最後の番号から数値分を引く
    start_p = [True,False,True] #Trueの場合、最初のポイントが必要

    print_bound(no, start, end, start_p, color, linewidth, linestyle)

def kyushu_bound(color = 'gray', linewidth = 0.5, linestyle = '--'): #九州県境
    no = [39,40,41,43,44,45] #福岡県,佐賀県,長崎県,大分県,宮崎県,鹿児島県
    start = [18,49,0,0,20,0]
    end = [121,17,167,104,61,113] 
    start_p = [False,False,False,False,False,False] 

    print_bound(no, start, end, start_p, color, linewidth, linestyle)

def chugoku_region(color = 'gray', linewidth = 0.5, linestyle = '--'): #中国県境
    no = [30,31,32,33,34] #鳥取県,島根県,岡山県,広島県,山口県
    start = [23,0,39,0,0]
    end = [14,50,70,113,157]
    start_p = [False,False,False,False,False]

    print_bound(no, start, end, start_p, color, linewidth, linestyle)

def kansai_region(color = 'gray', linewidth = 0.5, linestyle = '--'): #関西県境
    no = [23,24,25,26,27,27,27,28,29] #三重県,滋賀県,京都府,大阪府,兵庫県,兵庫県,兵庫県,奈良県,和歌山県
    start = [138,17,93,0,0,120,25,0,83]
    end = [0,15,0,48,126,0,74,65,0] 
    start_p = [True,False,True,False,False,True,False,False,True] 

    print_bound(no, start, end, start_p, color, linewidth, linestyle)

def chubu_region(color = 'gray', linewidth = 0.5, linestyle = '--'):
    no = [14,15,16,17,18,19,20,20,21,22] #新潟県,富山県,石川県,福井県,山梨県,長野県,岐阜県,岐阜県,静岡県,愛知県
    start = [22,32,68,68,0,0,52,106,0,0]
    end = [34,0,0,0,36,65,40,0,76,78]
    start_p = [False,True,True,True,False,False,False,True,False,False] 

    print_bound(no, start, end, start_p, color, linewidth, linestyle)

def kanto_region(color = 'gray', linewidth = 0.5, linestyle = '--'):
    no = [7,8,9,10,10,11,12,13] #茨城県,栃木県,群馬県,埼玉県,埼玉県,千葉県,東京都,神奈川県
    start = [0,0,0,0,42,99,0,81]
    end = [69,0,31,26,0,0,19,0]
    start_p = [False,False,False,False,True,True,False,True] 

    print_bound(no, start, end, start_p, color, linewidth, linestyle)

def tohoku_region(color = 'gray', linewidth = 0.5, linestyle = '--'): #東北県境
    no = [1,2,3,4,5,6] #青森県,岩手県,宮城県,秋田県,山形県,福島県
    start = [74,0,109,27,6,42]
    end = [35,136,24,12,0,0]
    start_p = [False,False,False,False,True,True] 

    print_bound(no, start, end, start_p, color, linewidth, linestyle)
```