2017年4月9日日曜日

Pythonで地図を描く:Basemap

anaconda関係で色々調べていたら、Basemapというパッケージのことを知りました。これは地図を描画してくれるライブラリとのこと。昔から、地図のGUIには苦労していたので、早速試してみました。(ちなみにコードはpython3でかいてます。遂に2.7から3系に移行する決心をつけました)

とりあえず実行例を示します。
環境はmac OSXです。(最近は、Linuxよりmacの方が楽になってきました(^_^;))
これは、matplotlibというグラフ描画パッケージが元にあり、その上で動くようです。しかもGUIまで自分で持ってます。以下にコードを示します。

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

# 緯度経度で範囲を指定する
north = 46.
south = 30.
east = 147.
#west = 128.
west = 128.

# 地図の表示('merc"は純粋に緯度経度を直行座標系にplotしている)
m = Basemap( projection='merc', llcrnrlat=south, urcrnrlat=north, llcrnrlon=west, urcrnrlon=east, resolution='l' )

# 陸地を茶色に, 湖を水色に
#m.fillcontinents(color='#8B4513', lake_color='#90FEFF')
m.fillcontinents(color='coral', lake_color='aqua')

# 海を濃い青に
#m.drawlsmask(ocean_color='#00008b')
#m.drawlsmask(ocean_color='blue')
m.drawmapboundary(fill_color='blue')

# NASA 'Blue marble' image
#m.bluemarble()

# 海岸線を引く
m.drawcoastlines(linewidth=0.5, color='black')

# 5度ごとに緯度線を描く
m.drawparallels(np.arange(25, 50, 5), labels = [1, 0, 0, 0], fontsize=10)

# 5度ごとに経度線を描く
m.drawmeridians(np.arange(125, 150, 5), labels = [0, 0, 0, 1], fontsize=10)

# 画面に表示
plt.show()
ちょっと色々試行錯誤したあとがコメントに残ってます。面白いのはNASA 'Blue marble'で、衛星写真ぽいテクスチャを貼り付けてくれます。

さて、実際に使うときは任意の緯度経度にマークをつけたくなります。定番の日本標準時の明石の位置に赤丸を表示してみました。
コードは以下を追加することになります。

# 地図に色をつけると見えなくなる! zorderが配置の意味をつけるらしい
x = 135.
y = 35.
m.scatter(x, y, s=200, c='red', latlon=True, zorder=10)
これはかなり苦労しました。scatterというメソッドを最初は例題を見ていると、matplotlibのpltのメソッドをcallする例が多数でしたが、どうもうまくいきません。大体、なんで表示領域の座標系をpltが理解できるんだ?ということに気づき、継承しているBasemapからcallしてみたらやっとうまくいきました。(latlon=Trueという引数があり、これを呼ばないと全然位置があいません)また更に罠なのが、zorderという引数です。よく考えれば当たり前なんですが、どう見てもこれ大元にOpenGL使ってるよねという感じです。(引数の中にはalphaまでありました)だったら、描画位置の指定をしないと隠れてしまいます。ですから、マークは少しZ軸で手前に置いて描きます。

座標のXYはリストで与えてもいいようなので、簡単にGISデータの描画ができます。

PS
ただ気になったのは、これの海岸前の元データはどこからきたんだろう?ということです。自分が知っている限り、(日本のは)国土地理院しかありません。あそこは基本、利用はプライベートの利用は許可していますが、著作権はどこかに表示してね、というスタンスだったはずです。同様なデータがNatural Earthというサイトにありますが、この海岸線(及び国境線)のデータに関するライセンスの記述がありません。自分が見つけられないだけ?ならいいんですが、少しグレーな気がします。