#!/usr/bin/env python3 """ 구마모토 지역 타일 생성 스크립트 """ import os import math import mapnik import psycopg2 from PIL import Image # 구마모토 지역 경계 KUMAMOTO_BOUNDS = { 'north': 33.2, 'south': 32.4, 'east': 131.2, 'west': 130.2 } # 타일 크기 TILE_SIZE = 256 def deg2num(lat_deg, lon_deg, zoom): """위경도를 타일 번호로 변환""" lat_rad = math.radians(lat_deg) n = 2.0 ** zoom xtile = int((lon_deg + 180.0) / 360.0 * n) ytile = int((1.0 - math.asinh(math.tan(lat_rad)) / math.pi) / 2.0 * n) return (xtile, ytile) def num2deg(xtile, ytile, zoom): """타일 번호를 위경도로 변환""" n = 2.0 ** zoom lon_deg = xtile / n * 360.0 - 180.0 lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n))) lat_deg = math.degrees(lat_rad) return (lat_deg, lon_deg) def create_mapnik_map(): """Mapnik 지도 객체 생성""" m = mapnik.Map(TILE_SIZE, TILE_SIZE) # 한국어/일본어 폰트 설정 mapnik.FontEngine.register_fonts('/usr/share/fonts/truetype/noto/') # 스타일 로드 mapnik.load_map(m, '/opt/map-server/mapnik-style.xml') return m def generate_tile(m, z, x, y): """개별 타일 생성""" # 타일 경계 계산 lat_north, lon_west = num2deg(x, y, z) lat_south, lon_east = num2deg(x + 1, y + 1, z) # 지도 범위 설정 bbox = mapnik.Box2d(lon_west, lat_south, lon_east, lat_north) m.zoom_to_box(bbox) # 타일 렌더링 im = mapnik.Image(TILE_SIZE, TILE_SIZE) mapnik.render(m, im) return im.tostring('png') def generate_kumamoto_tiles(): """구마모토 지역 타일 생성""" print("구마모토 지역 타일 생성 시작...") # Mapnik 지도 생성 m = create_mapnik_map() # 줌 레벨별 타일 생성 (8-16레벨) for zoom in range(8, 17): print(f"줌 레벨 {zoom} 타일 생성 중...") # 구마모토 지역의 타일 범위 계산 x_min, y_max = deg2num(KUMAMOTO_BOUNDS['north'], KUMAMOTO_BOUNDS['west'], zoom) x_max, y_min = deg2num(KUMAMOTO_BOUNDS['south'], KUMAMOTO_BOUNDS['east'], zoom) tile_count = 0 for x in range(x_min, x_max + 1): for y in range(y_min, y_max + 1): # 타일 디렉토리 생성 tile_dir = f"/var/www/html/tiles/{zoom}/{x}" os.makedirs(tile_dir, exist_ok=True) # 타일 파일 경로 tile_path = f"{tile_dir}/{y}.png" # 이미 존재하는 타일은 건너뛰기 if os.path.exists(tile_path): continue try: # 타일 생성 tile_data = generate_tile(m, zoom, x, y) # 타일 저장 with open(tile_path, 'wb') as f: f.write(tile_data) tile_count += 1 except Exception as e: print(f"타일 생성 실패 ({zoom}/{x}/{y}): {e}") print(f"줌 레벨 {zoom}: {tile_count}개 타일 생성 완료") print("구마모토 지역 타일 생성 완료!") if __name__ == "__main__": generate_kumamoto_tiles()