naohiro701 commited on
Commit
6bae1b6
·
verified ·
1 Parent(s): 1ee5d4a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -115
app.py CHANGED
@@ -8,128 +8,117 @@ from PIL import Image
8
  import numpy as np
9
 
10
  def meters_to_degrees(meters, lat):
11
- """
12
- Convert meters to degrees for latitude and longitude.
13
-
14
- Parameters:
15
- - meters (float): Distance in meters
16
- - lat (float): Latitude at which the conversion is done (as the conversion depends on latitude)
17
-
18
- Returns:
19
- - lat_deg (float): Change in degrees of latitude
20
- - lon_deg (float): Change in degrees of longitude
21
- """
22
  # 緯度1度あたりの距離は常に約111.32km
23
  lat_deg = meters / 111320
24
 
25
- # 経度1度あたりの距離は緯度によって変わる(赤道では約111.32kmだが、極に近づくと小さくなる)
26
  lon_deg = meters / (111320 * np.cos(np.radians(lat)))
27
 
28
  return lat_deg, lon_deg
29
 
30
- def create_artistic_map(lat, lon, distance, dpi, width, height, bg_color, greenery_color, water_color, building_colors, major_road_color, medium_road_color, minor_road_color):
31
- """
32
- Create an artistic map image with customizable settings based on the given latitude, longitude, distance, and visual parameters.
33
-
34
- Parameters:
35
- - lat (float): Latitude of the center point
36
- - lon (float): Longitude of the center point
37
- - distance (float): Radius of the map in meters
38
- - dpi (int): Resolution of the output image in DPI
39
- - width (int): Width of the output image in inches
40
- - height (int): Height of the output image in inches
41
- - bg_color (str): Background color in hex code
42
- - greenery_color (str): Color for greenery in hex code
43
- - water_color (str): Color for water bodies in hex code
44
- - building_colors (list): List of colors for buildings in hex codes
45
- - major_road_color (str): Color for major roads in hex code
46
- - medium_road_color (str): Color for medium roads in hex code
47
- - minor_road_color (str): Color for minor roads in hex code
48
-
49
- Returns:
50
- - PIL.Image.Image: Generated map image
51
- """
52
  # 中心点の設定
53
  point = (lat, lon)
54
-
55
  # 距離をもとに緯度経度の幅と高さを計算
56
  lat_deg, lon_deg = meters_to_degrees(distance, lat)
57
-
58
- # OSMデータ取得
59
- G = ox.graph_from_point(point, dist=distance, network_type='all')
60
- nodes, edges = ox.graph_to_gdfs(G)
61
-
62
- # 建物データ取得
63
- buildings = ox.features_from_point(point, tags={'building': True}, dist=distance)
64
-
65
- # 水域データ取得
66
- water = ox.features_from_point(point, tags={'natural': 'water'}, dist=distance)
67
-
68
- # 緑地データ取得(公園、草地、森林など)
69
- greenery_list = []
70
- greenery_tags = [
71
- {'leisure': 'park'},
72
- {'landuse': 'grass'},
73
- {'landuse': 'forest'},
74
- {'natural': 'wood'}
75
- ]
76
- for tags in greenery_tags:
77
- greenery_part = ox.features_from_point(point, tags=tags, dist=distance)
78
- if not greenery_part.empty:
79
- greenery_list.append(greenery_part)
80
-
81
- if greenery_list:
82
- greenery = pd.concat(greenery_list)
83
- else:
84
- greenery = gpd.GeoDataFrame()
85
-
86
  # 描画設定
87
  fig, ax = plt.subplots(figsize=(width, height))
88
-
89
  # 背景色を設定
90
  fig.patch.set_facecolor(bg_color)
91
  ax.set_facecolor(bg_color)
92
-
93
  # 緑地の描画
94
- if not greenery.empty:
95
- greenery.plot(ax=ax, facecolor=greenery_color, edgecolor='none')
96
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  # 水域の描画
98
- if not water.empty:
99
- water.plot(ax=ax, facecolor=water_color, edgecolor='none')
100
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  # 建物の描画
102
- if not buildings.empty:
103
- building_types = buildings['building'].unique()
104
- for i, building_type in enumerate(building_types):
105
- building_subset = buildings[buildings['building'] == building_type]
106
- building_color = building_colors[i % len(building_colors)]
107
- building_subset.plot(ax=ax, facecolor=building_color, edgecolor='none')
108
-
 
 
 
109
  # 道路の描画
110
- if not edges.empty and 'highway' in edges.columns:
111
- # 主要道路の描画
112
- major_roads = edges[edges['highway'].isin(['motorway', 'trunk', 'primary'])]
113
- if not major_roads.empty:
114
- major_roads.plot(ax=ax, linewidth=2, edgecolor=major_road_color)
115
-
116
- # 中程度の道路の描画
117
- medium_roads = edges[edges['highway'].isin(['secondary', 'tertiary'])]
118
- if not medium_roads.empty:
119
- medium_roads.plot(ax=ax, linewidth=1.5, edgecolor=medium_road_color)
120
-
121
- # 小規模な道路の描画
122
- minor_roads = edges[~edges['highway'].isin(['motorway', 'trunk', 'primary', 'secondary', 'tertiary'])]
123
- if not minor_roads.empty:
124
- minor_roads.plot(ax=ax, linewidth=1, edgecolor=minor_road_color)
125
-
 
 
 
 
 
 
 
126
  # 軸をオフに設定
127
  ax.axis('off')
128
-
129
- # 入力された距離をもとに表示範囲を正方形に設定
130
  ax.set_xlim([lon - lon_deg, lon + lon_deg])
131
  ax.set_ylim([lat - lat_deg, lat + lat_deg])
132
-
133
  # バッファに保存して、PIL画像として返す
134
  buf = io.BytesIO()
135
  plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0, dpi=dpi)
@@ -143,7 +132,7 @@ st.title("カラフルな地図が作成できます")
143
  # デフォルト値を設定
144
  default_lat = 35.533283
145
  default_lon = 139.642000
146
- default_distance = 1000
147
 
148
  # ユーザー入力
149
  lat = st.number_input("緯度を入力してください", value=default_lat, format="%.6f")
@@ -151,25 +140,66 @@ lon = st.number_input("経度を入力してください", value=default_lon, fo
151
  distance = st.number_input("距離を選択(km)", value=default_distance, format="%.2f")
152
 
153
  # 画像設定
154
- dpi = st.number_input(
155
- label="画像のDPI(解像度)を選択", # Input label
156
- value=72, # Default value
157
- format="%d" # Format for integers
158
- )
159
  width = st.slider("画像の幅(インチ)を選択", 5, 30, 20)
160
  height = st.slider("画像の高さ(インチ)を選択", 5, 30, 20)
161
 
162
- # 色設定
 
 
 
163
  bg_color = st.color_picker("背景色を選択", "#FAF3E0")
164
- greenery_color = st.color_picker("緑地の色を選択", "#80C341")
165
- water_color = st.color_picker("水域の色を選択", "#45A6FF")
166
- building_colors = [
167
- st.color_picker(f"建物の色 {i+1}", default_color)
168
- for i, default_color in enumerate(['#FF6F61', '#FFAB73', '#FFA07A', '#FFD700', '#F08080'])
169
- ]
170
- major_road_color = st.color_picker("主要道路の色を選択", "#FF6347")
171
- medium_road_color = st.color_picker("中程度の道路の色を選択", "#FF4500")
172
- minor_road_color = st.color_picker("小規模な道路の色を選択", "#D2691E")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
  # マップ生成ボタン
175
  if st.button("マップを生成"):
@@ -177,6 +207,8 @@ if st.button("マップを生成"):
177
  map_image = create_artistic_map(
178
  lat, lon, distance*1000, dpi, width, height,
179
  bg_color, greenery_color, water_color, building_colors,
180
- major_road_color, medium_road_color, minor_road_color
 
 
181
  )
182
  st.image(map_image, caption="生成されたアートマップ", use_column_width=True)
 
8
  import numpy as np
9
 
10
  def meters_to_degrees(meters, lat):
 
 
 
 
 
 
 
 
 
 
 
11
  # 緯度1度あたりの距離は常に約111.32km
12
  lat_deg = meters / 111320
13
 
14
+ # 経度1度あたりの距離は緯度によって変わる
15
  lon_deg = meters / (111320 * np.cos(np.radians(lat)))
16
 
17
  return lat_deg, lon_deg
18
 
19
+ def create_artistic_map(
20
+ lat, lon, distance, dpi, width, height, bg_color, greenery_color, water_color,
21
+ building_colors, major_road_color, medium_road_color, minor_road_color,
22
+ display_greenery, display_water, display_buildings,
23
+ display_major_roads, display_medium_roads, display_minor_roads
24
+ ):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  # 中心点の設定
26
  point = (lat, lon)
27
+
28
  # 距離をもとに緯度経度の幅と高さを計算
29
  lat_deg, lon_deg = meters_to_degrees(distance, lat)
30
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  # 描画設定
32
  fig, ax = plt.subplots(figsize=(width, height))
33
+
34
  # 背景色を設定
35
  fig.patch.set_facecolor(bg_color)
36
  ax.set_facecolor(bg_color)
37
+
38
  # 緑地の描画
39
+ if display_greenery:
40
+ # 緑地データ取得
41
+ greenery_list = []
42
+ greenery_tags = [
43
+ {'leisure': 'park'},
44
+ {'leisure': 'garden'},
45
+ {'landuse': 'grass'},
46
+ {'landuse': 'forest'},
47
+ {'landuse': 'meadow'},
48
+ {'natural': 'wood'},
49
+ {'natural': 'scrub'},
50
+ {'natural': 'grassland'},
51
+ {'natural': 'heath'}
52
+ ]
53
+ for tags in greenery_tags:
54
+ greenery_part = ox.features_from_point(point, tags=tags, dist=distance)
55
+ if not greenery_part.empty:
56
+ greenery_list.append(greenery_part)
57
+ if greenery_list:
58
+ greenery = pd.concat(greenery_list)
59
+ greenery.plot(ax=ax, facecolor=greenery_color, edgecolor='none')
60
+
61
  # 水域の描画
62
+ if display_water:
63
+ # 水域データ取得
64
+ water_list = []
65
+ water_tags = [
66
+ {'natural': 'water'},
67
+ {'waterway': 'riverbank'},
68
+ {'landuse': 'reservoir'},
69
+ {'landuse': 'basin'},
70
+ {'natural': 'wetland'}
71
+ ]
72
+ for tags in water_tags:
73
+ water_part = ox.features_from_point(point, tags=tags, dist=distance)
74
+ if not water_part.empty:
75
+ water_list.append(water_part)
76
+ if water_list:
77
+ water = pd.concat(water_list)
78
+ water.plot(ax=ax, facecolor=water_color, edgecolor='none')
79
+
80
  # 建物の描画
81
+ if display_buildings:
82
+ # 建物データ取得
83
+ buildings = ox.features_from_point(point, tags={'building': True}, dist=distance)
84
+ if not buildings.empty:
85
+ building_types = buildings['building'].unique()
86
+ for i, building_type in enumerate(building_types):
87
+ building_subset = buildings[buildings['building'] == building_type]
88
+ building_color = building_colors[i % len(building_colors)]
89
+ building_subset.plot(ax=ax, facecolor=building_color, edgecolor='none')
90
+
91
  # 道路の描画
92
+ if display_major_roads or display_medium_roads or display_minor_roads:
93
+ # OSMデータ取得
94
+ G = ox.graph_from_point(point, dist=distance, network_type='all')
95
+ nodes, edges = ox.graph_to_gdfs(G)
96
+ if not edges.empty and 'highway' in edges.columns:
97
+ # 主要道路の描画
98
+ if display_major_roads:
99
+ major_roads = edges[edges['highway'].isin(['motorway', 'trunk', 'primary'])]
100
+ if not major_roads.empty:
101
+ major_roads.plot(ax=ax, linewidth=2, edgecolor=major_road_color)
102
+
103
+ # 中程度の道路の描画
104
+ if display_medium_roads:
105
+ medium_roads = edges[edges['highway'].isin(['secondary', 'tertiary'])]
106
+ if not medium_roads.empty:
107
+ medium_roads.plot(ax=ax, linewidth=1.5, edgecolor=medium_road_color)
108
+
109
+ # 小規模な道路の描画
110
+ if display_minor_roads:
111
+ minor_roads = edges[~edges['highway'].isin(['motorway', 'trunk', 'primary', 'secondary', 'tertiary'])]
112
+ if not minor_roads.empty:
113
+ minor_roads.plot(ax=ax, linewidth=1, edgecolor=minor_road_color)
114
+
115
  # 軸をオフに設定
116
  ax.axis('off')
117
+
118
+ # 表示範囲を設定
119
  ax.set_xlim([lon - lon_deg, lon + lon_deg])
120
  ax.set_ylim([lat - lat_deg, lat + lat_deg])
121
+
122
  # バッファに保存して、PIL画像として返す
123
  buf = io.BytesIO()
124
  plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0, dpi=dpi)
 
132
  # デフォルト値を設定
133
  default_lat = 35.533283
134
  default_lon = 139.642000
135
+ default_distance = 1.0 # キロメートル
136
 
137
  # ユーザー入力
138
  lat = st.number_input("緯度を入力してください", value=default_lat, format="%.6f")
 
140
  distance = st.number_input("距離を選択(km)", value=default_distance, format="%.2f")
141
 
142
  # 画像設定
143
+ dpi = st.number_input("画像のDPI(解像度)を選択", value=72, format="%d")
 
 
 
 
144
  width = st.slider("画像の幅(インチ)を選択", 5, 30, 20)
145
  height = st.slider("画像の高さ(インチ)を選択", 5, 30, 20)
146
 
147
+ # 表示設定
148
+ st.header("表示設定")
149
+
150
+ # 背景色
151
  bg_color = st.color_picker("背景色を選択", "#FAF3E0")
152
+
153
+ # 緑地の設定
154
+ st.subheader("緑地の設定")
155
+ display_greenery = st.checkbox("緑地を表示", value=True)
156
+ if display_greenery:
157
+ greenery_color = st.color_picker("緑地の色を選択", "#80C341")
158
+ else:
159
+ greenery_color = None
160
+
161
+ # 水域の設定
162
+ st.subheader("水域の設定")
163
+ display_water = st.checkbox("水域を表示", value=True)
164
+ if display_water:
165
+ water_color = st.color_picker("水域の色を選択", "#45A6FF")
166
+ else:
167
+ water_color = None
168
+
169
+ # 建物の設定
170
+ st.subheader("建物の設定")
171
+ display_buildings = st.checkbox("建物を表示", value=True)
172
+ if display_buildings:
173
+ default_building_colors = ['#FF6F61', '#FFAB73', '#FFA07A', '#FFD700', '#F08080']
174
+ building_colors = [
175
+ st.color_picker(f"建物の色 {i+1}", default_color)
176
+ for i, default_color in enumerate(default_building_colors)
177
+ ]
178
+ else:
179
+ building_colors = []
180
+
181
+ # 道路の設定
182
+ st.subheader("道路の設定")
183
+ # 主要道路
184
+ display_major_roads = st.checkbox("主要道路を表示", value=True)
185
+ if display_major_roads:
186
+ major_road_color = st.color_picker("主要道路の色を選択", "#FF6347")
187
+ else:
188
+ major_road_color = None
189
+
190
+ # 中程度の道路
191
+ display_medium_roads = st.checkbox("中程度の道路を表示", value=True)
192
+ if display_medium_roads:
193
+ medium_road_color = st.color_picker("中程度の道路の色を選択", "#FF4500")
194
+ else:
195
+ medium_road_color = None
196
+
197
+ # 小規模な道路
198
+ display_minor_roads = st.checkbox("小規模な道路を表示", value=True)
199
+ if display_minor_roads:
200
+ minor_road_color = st.color_picker("小規模な道路の色を選択", "#D2691E")
201
+ else:
202
+ minor_road_color = None
203
 
204
  # マップ生成ボタン
205
  if st.button("マップを生成"):
 
207
  map_image = create_artistic_map(
208
  lat, lon, distance*1000, dpi, width, height,
209
  bg_color, greenery_color, water_color, building_colors,
210
+ major_road_color, medium_road_color, minor_road_color,
211
+ display_greenery, display_water, display_buildings,
212
+ display_major_roads, display_medium_roads, display_minor_roads
213
  )
214
  st.image(map_image, caption="生成されたアートマップ", use_column_width=True)