立体地形図を手作りしてみようかな、っと(8.5) 兼 六芒星

(8)とかで、範囲内の地形説明しにくいなぁ、と思っていて、(8)で「そういえばワタシ、Acrobat 持ってた」と気付いたあとで、良く考えたら matplotlib で文字入れれるじゃんか、と。

こんな:

  1 # -*- coding: utf-8 -*-
  2 import numpy as np
  3 import converted_loader
  4 
  5 X, Y, elevs = converted_loader.load_range(
  6     38.235130, 140.840529,
  7     38.336993, 140.954586)
  8 elevs[np.isnan(elevs)] = np.nanmin(elevs)
  9 
 10 #
 11 import matplotlib
 12 import matplotlib.cm as cm
 13 import matplotlib.pyplot as plt
 14 from mpl_toolkits.axes_grid1 import make_axes_locatable
 15 import matplotlib.font_manager
 16 import matplotlib.patheffects as PathEffects
 17 fontprop = matplotlib.font_manager.FontProperties(
 18     fname="c:/Windows/Fonts/msyh.ttf")
 19 
 20 elevs = np.flipud(elevs)
 21 
 22 # ----------------
 23 fig, ax = plt.subplots()
 24 fig.set_size_inches(16.53 * 2, 11.69 * 2)
 25 
 26 from matplotlib.colors import LightSource
 27 ls = LightSource(azdeg=180, altdeg=15)
 28 rgb = ls.shade(elevs, cm.rainbow)
 29 cs = ax.imshow(elevs)
 30 ax.imshow(rgb)
 31 
 32 # create an axes on the right side of ax. The width of cax will be 2%
 33 # of ax and the padding between cax and ax will be fixed at 0.05 inch.
 34 divider = make_axes_locatable(ax)
 35 cax = divider.append_axes("right", size="2%", pad=0.05)
 36 fig.colorbar(cs, cax=cax)
 37 
 38 ax.set_xticks([])
 39 ax.set_yticks([])
 40 # ----------------
 41 
 42 def _latlon2xy(lat, lon):
 43     return (
 44         int((lon - X[0]) / (X[1] - X[0])),
 45         len(Y) - int((lat - Y[0]) / (Y[1] - Y[0])))
 46 
 47 font = {
 48     "fontproperties": fontprop,
 49     'color'  : 'white',
 50     'weight' : 'normal',
 51     'size'   : 24,
 52     }
 53 anns0 = [
 54     ((38.272531, 140.845012), u'大崎八幡宮', (0, 100)),
 55     ((38.280230, 140.885101), u'東照宮', (40, 0)),
 56     ((38.246114, 140.874633), u'愛宕神社', (-100, 100)),
 57     ]
 58 anns1 = [
 59     ((38.253056, 140.855713), u'仙台城址(青葉城址)', (-50, 100)),
 60     ((38.260434, 140.896472), u'榴岡公園', (1, 1)),
 61     ((38.282542, 140.862576), u'青葉神社', (0, 100)),
 62     ]
 63 anns2 = [
 64     ((38.335387, 140.951077), u'宮城スタジアム', (100, -100)),
 65     ((38.313907, 140.939907), u'高森山', (120, -120)),
 66     ((38.306607, 140.943150), u'東光寺', (1, 1)),
 67     ((38.335253, 140.934978), u'青麻神社', (1, 1)),
 68     ((38.317914, 140.919684), u'鶴ヶ城', (60, 60)),
 69     ((38.303409, 140.947723), u'七北田川', (200, 0)),
 70     ((38.272065, 140.931265), u'梅田川', (200, 0)),
 71     ((38.266733, 140.861104), u'広瀬川', (-50, 0)),
 72     ((38.251194, 140.865862), u'瑞宝寺', (-100, 200)),
 73     ((38.257201, 140.903413), u'宮城野原公園', (1, 1)),
 74     ((38.260078, 140.882583), u'仙台駅', (0, 20)),
 75     ((38.236794, 140.902024), u'若林城址\n(現・宮城刑務所)', (-100, 100)),
 76     ((38.266949, 140.871780), u'勾当台公園', (1, 1)),
 77     ((38.265973, 140.874735), u'錦町公園', (1, 1)),
 78     ((38.262210, 140.861936), u'西公園', (1, 1)),
 79     ((38.259659, 140.861912), u'桜岡大神宮', (0, 100)),
 80     ((38.261568, 140.843080), u'亀岡八幡宮', (0, 100)),
 81     ((38.250309, 140.852302), u'八木山橋', (1, 1)),
 82     ((38.246278, 140.848280), u'八木山ベニーランド', (1, 1)),
 83     ((38.326137, 140.881258), u'イズミティ21', (0, 150)),
 84     ((38.323259, 140.881258), u'泉中央駅\n(仙台市営地下鉄)', (0, 150)),
 85     ((38.312770, 140.884236), u'八乙女駅\n(仙台市営地下鉄)', (-100, 150)),
 86     ((38.318739, 140.880808), u'七北田公園', (1, 1)),
 87     ((38.317729, 140.883082), u'かむり大橋\n(県道22号線)', (-100, -100)),
 88     ((38.290907 ,140.872687), u'県道22号線', (0, 200)),
 89     ((38.286209, 140.871126), u'県道22号線', (0, 200)),
 90     ((38.282347, 140.872346), u'県道22号線', (0, 200)),
 91     ]
 92 
 93 for (lat, lon), ann, (off_y, off_x) in anns0 + anns1 + anns2:
 94     tx, ty = _latlon2xy(lat, lon)
 95     p = ax.annotate(
 96         ann,
 97         (tx, ty),
 98         (tx + off_x, ty + off_y),
 99         arrowprops=dict(
100             arrowstyle="->",
101             connectionstyle="angle",
102             lw=1
103             ),
104         size=10,
105         ha="center",
106         path_effects=[
107             PathEffects.withStroke(linewidth=2, foreground="w")
108             ],
109         fontproperties=fontprop)
110     p.arrow_patch.set_path_effects([
111             PathEffects.Stroke(linewidth=2, foreground="w"),
112             PathEffects.Normal()])
113 
114 #
115 p0 = _latlon2xy(anns0[0][0][0], anns0[0][0][1])
116 p1 = _latlon2xy(anns0[1][0][0], anns0[1][0][1])
117 p2 = _latlon2xy(anns0[2][0][0], anns0[2][0][1])
118 li = ax.plot([p0[0], p1[0]], [p0[1], p1[1]])
119 plt.setp(li, color='w', linewidth=2.0)
120 li = ax.plot([p1[0], p2[0]], [p1[1], p2[1]])
121 plt.setp(li, color='w', linewidth=2.0)
122 li = ax.plot([p2[0], p0[0]], [p2[1], p0[1]])
123 plt.setp(li, color='w', linewidth=2.0)
124 p0 = _latlon2xy(anns1[0][0][0], anns1[0][0][1])
125 p1 = _latlon2xy(anns1[1][0][0], anns1[1][0][1])
126 p2 = _latlon2xy(anns1[2][0][0], anns1[2][0][1])
127 li = ax.plot([p0[0], p1[0]], [p0[1], p1[1]])
128 plt.setp(li, color='w', linewidth=2.0)
129 li = ax.plot([p1[0], p2[0]], [p1[1], p2[1]])
130 plt.setp(li, color='w', linewidth=2.0)
131 li = ax.plot([p2[0], p0[0]], [p2[1], p0[1]])
132 plt.setp(li, color='w', linewidth=2.0)
133 
134 
135 plt.savefig(
136     "sendaishigai-izumihigashi-with-annotation.pdf",
137     bbox_inches="tight")

これを突き詰め過ぎれば Google Map とか OpenStreet Map とか地理院地図とか Google Earth を素直に使えやゴルァ、な世界に突入してしまうんだけれど、「自分だけの、自分が興味あることだけが書き込まれた地図」のためには、かえってこのチマチマ感がいいんでは。

フォントの扱いは matplotlib のは決してモダーンなものではないので、愉快ではない。日本語なんかなくなってしまえばいいのに、と思う。違うか。

「ここに注目!」のための API が直接提供されてる(annotate)のが、「科学技術計算向け」に設計された matplotlib ならでは、かもなぁ。

領域は(8)より少し広げてる。亀岡八幡宮をどうしても収めたかったので。

Unable to display PDF
Click here to download

亀岡八幡宮はね、高校時代の部活でランニングコースにしてた神社でさ。ここ、芭蕉の句に詠まれた場所なんだけれど、走ってた当時、「観光地感ゼロ」なうえに廃れてゆくままの年季の入った階段がとても好きで、トレーニングで走っているにも関わらず、とても好きな場所だった。今どうなってんだろう、と、Google で写真検索してみたら、高校時代のまんまみたい。ちょっと観光で周るにはややアクセスよくないかもしれないけれど、もしも宮城県立美術館とか仙台城とか、あるいは東北大学なんぞを訪れることがあったらちょっと思い出してみて。(というか成田山仙台分院のお隣りです。)

さて。「政宗の六芒星」なんだけれど。ひしゃげてるのはワタシがアスペクト比調整をさぼってることもあるんで、これは気にしないで。

こんなの偶然だよ、みたいに疑う気持ちは別にない。政宗のことだからなにか想いがあっても不思議はないし、昔の土木技術って実際はすげーもんであるからね、事実、これが狙いだったのだとしても別に不思議には思わない。驚きはするけれど。陰陽道やら風水やらの宗教観に基づく都市設計なんかは、昔は普通にあったわけだし。というかそれらこそが当時の「最先端科学」に近しいものだったわけだしね。

そうなんだけど、こうやって地形と一緒にプロットしてみるとさ、「特徴的な地形の場所」なのね、どの頂点も。つまり「寺社が建つような場所」に寺社を建ててるわけなのね。無理矢理感が全くない、と言ってもいい。これが全部の頂点が平地にあるような、「そこにそれがあることが腑に落ちない」ならばこそ、「六芒星でしかありえない」と言えるのかも。

なお、国分寺も参加させて、仙台城、瑞鳳殿、大崎八幡宮、東照宮、国分寺の五芒星、てのもあるようなんで、自分で試してみれば?

一年半遅れの浦島太郎ネタ、でした。