반응형
github.com/pavel-perina/gpx_to_png
저 분 깃헙 코드 쓰는데, opencyclemap 쓰면 배경사진에 api key 입력하라는 워터마크가 떠서 조금 바꿨다
썬더포레스트쓰면 없앨 수 있다고 했다. (api key 공짜로 사용가능)
www.frogsparks.com/opencyclemap-api-key-required/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
# -*- coding: utf-8 -*-
import sys as mod_sys
import math as mod_math
import logging as mod_logging
import urllib as mod_urllib
import os as mod_os
import gpxpy as mod_gpxpy
from PIL import Image as mod_pil_image
from PIL import ImageDraw as mod_pil_draw
import glob as mod_glob
osm_cache_base = r"c:\devel-python\.cache\opencyclemap"
osm_tile_res = 256
def format_time(time_s):
if not time_s:
return 'n/a'
minutes = mod_math.floor(time_s / 60.)
hours = mod_math.floor(minutes / 60.)
return '%s:%s:%s' % (str(int(hours)).zfill(2), str(int(minutes % 60)).zfill(2), str(int(time_s % 60)).zfill(2))
def get_tile_url (x, y, z):
return "http://a.tile.thunderforest.com/{타일종류}/%d/%d/%d.png?apikey={썬더포레스트 api 키}" % (z, x, y)
def get_tile_filename (x, y, z):
return r"c:\devel-python\.cache\opencyclemap\%d\%d\%d.png" % (z, x, y)
def get_map_suffix ():
return "osm-cycle"
def osm_lat_lon_to_x_y_tile (lat_deg, lon_deg, zoom):
""" Gets tile containing given coordinate at given zoom level """
# taken from http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames, works for OSM maps and mapy.cz
lat_rad = mod_math.radians(lat_deg)
n = 2.0 ** zoom
xtile = int((lon_deg + 180.0) / 360.0 * n)
ytile = int((1.0 - mod_math.log(mod_math.tan(lat_rad) + (1 / mod_math.cos(lat_rad))) / mod_math.pi) / 2.0 * n)
return (xtile, ytile)
def osm_get_auto_zoom_level ( min_lat, max_lat, min_lon, max_lon, max_n_tiles):
""" Gets zoom level which contains at maximum `max_n_tiles` """
for z in range (0,17):
x1, y1 = osm_lat_lon_to_x_y_tile (min_lat, min_lon, z)
x2, y2 = osm_lat_lon_to_x_y_tile (max_lat, max_lon, z)
max_tiles = max (abs(x2 - x1), abs(y2 - y1))
if (max_tiles > max_n_tiles):
print ("Max tiles: %d" % max_tiles)
return z
return 17
def osm_cache_tile (x,y,z):
""" Downloads tile x,y,x into cache. Directories are automatically created, existing files are not retrieved. """
src_url = get_tile_url(x,y,z)
dst_filename = get_tile_filename(x,y,z)
dst_dir = mod_os.path.dirname(dst_filename)
if not mod_os.path.exists(dst_dir):
mod_os.makedirs(dst_dir)
if mod_os.path.isfile (dst_filename):
return
print ("Downloading %s ..." % src_url)
request = mod_urllib.request.Request (src_url)
response = mod_urllib.request.urlopen (request)
data = response.read()
f = open(dst_filename, "wb")
f.write(data)
f.close()
class MapCreator:
""" Class for map drawing """
def __init__(self, min_lat, max_lat, min_lon, max_lon, z):
""" constructor """
x1, y1 = osm_lat_lon_to_x_y_tile (min_lat, min_lon, z)
x2, y2 = osm_lat_lon_to_x_y_tile (max_lat, max_lon, z)
self.x1 = min (x1, x2)
self.x2 = max (x1, x2)
self.y1 = min (y1, y2)
self.y2 = max (y1, y2)
self.w = (self.x2 - self.x1 + 1) * osm_tile_res
self.h = (self.y2 - self.y1 + 1) * osm_tile_res
self.z = z
print (self.w, self.h)
self.dst_img = mod_pil_image.new ("RGB", (self.w, self.h))
def cache_area(self):
""" Downloads necessary tiles to cache """
print ("Caching tiles x1=%d y1=%d x2=%d y2=%d" % (self.x1, self.y1, self.x2, self.y2))
for y in range (self.y1, self.y2 + 1):
for x in range (self.x1, self.x2 + 1):
osm_cache_tile (x, y, self.z)
def create_area_background(self):
""" Creates background map from cached tiles """
for y in range (self.y1, self.y2+1):
for x in range (self.x1, self.x2+1):
try:
src_img = mod_pil_image.open (get_tile_filename (x, y, z))
dst_x = (x-self.x1)*osm_tile_res
dst_y = (y-self.y1)*osm_tile_res
self.dst_img.paste (src_img, (dst_x, dst_y))
except Exception as e:
print("Error processing file " + get_tile_filename (x, y, z))
def lat_lon_to_image_xy (self, lat_deg, lon_deg):
""" Internal. Converts lat, lon into dst_img coordinates in pixels """
lat_rad = mod_math.radians(lat_deg)
n = 2.0 ** self.z
xtile_frac = (lon_deg + 180.0) / 360.0 * n
ytile_frac = (1.0 - mod_math.log(mod_math.tan(lat_rad) + (1 / mod_math.cos(lat_rad))) / mod_math.pi) / 2.0 * n
img_x = int( (xtile_frac-self.x1)*osm_tile_res )
img_y = int( (ytile_frac-self.y1)*osm_tile_res )
return (img_x, img_y)
def draw_track (self, gpx):
""" Draw GPX track onto map """
draw = mod_pil_draw.Draw (self.dst_img)
trk = 0 # Just changes color of segment a little
for track in gpx.tracks:
for segment in track.segments:
idx = 0
x_from = 0
y_from = 0
for point in segment.points:
if (idx == 0):
x_from, y_from = self.lat_lon_to_image_xy (point.latitude, point.longitude)
else:
x_to, y_to = self.lat_lon_to_image_xy (point.latitude, point.longitude)
# draw.line ((x_from,y_from,x_to,y_to), (255,0,trk), 2)
draw.line((x_from,y_from,x_to,y_to), (1, 1, 1), 10)
x_from = x_to
y_from = y_to
idx += 1
trk += 32
if (trk > 160):
trk = 0
def save_image(self, filename):
print("Saving " + filename)
self.dst_img.save (filename)
if (__name__ == '__main__'):
gpx_files = mod_glob.glob (r"{gpx 저장 경로}\*.gpx")
for gpx_file in gpx_files:
try:
gpx = mod_gpxpy.parse(open(gpx_file, encoding='UTF8'))
# Print some track stats
print ('--------------------------------------------------------------------------------')
print (' GPX file : %s' % gpx_file)
start_time, end_time = gpx.get_time_bounds()
print(' Started : %s' % start_time)
print(' Ended : %s' % end_time)
print(' Length : %2.2fkm' % (gpx.length_3d() / 1000.))
moving_time, stopped_time, moving_distance, stopped_distance, max_speed = gpx.get_moving_data()
print(' Moving time : %s' % format_time(moving_time))
print(' Stopped time : %s' % format_time(stopped_time))
# print(' Max speed : %2.2fm/s = %2.2fkm/h' % (max_speed, max_speed * 60. ** 2 / 1000.))
uphill, downhill = gpx.get_uphill_downhill()
print(' Total uphill : %4.0fm' % uphill)
print(' Total downhill: %4.0fm' % downhill)
min_lat, max_lat, min_lon, max_lon = gpx.get_bounds()
print(" Bounds : [%1.4f,%1.4f,%1.4f,%1.4f]" % (min_lat, max_lat, min_lon, max_lon))
z = osm_get_auto_zoom_level (min_lat, max_lat, min_lon, max_lon, 6)
print(" Zoom Level : %d" % z)
# Create the map
map_creator = MapCreator (min_lat, max_lat, min_lon, max_lon, z)
map_creator.cache_area()
map_creator.create_area_background()
map_creator.draw_track(gpx)
map_creator.save_image (gpx_file[:-4] + '.png')
except Exception as e:
mod_logging.exception(e)
print('Error processing %s' % gpx_file)
mod_sys.exit(1)
|
cs |
타일 종류는 다음과 같다
transport
transport-dark
atlas
cycle
landscape
mobile-atlas
neighbourhood
outdoors
pioneer
spinal-map
반응형
'개발' 카테고리의 다른 글
@RequestBody (0) | 2021.08.24 |
---|---|
특정 GPX 파일 실행 시 앱 종료되는 현상 (jenetics/jpx) (0) | 2021.06.14 |
UserProfileDto NPE (0) | 2021.05.04 |
[연습] querydsl 정렬 포함한 쿼리 실행 시 NPE 발생 (0) | 2021.04.29 |
[연습] travis-ci (0) | 2021.04.27 |