Created
September 30, 2014 01:26
-
-
Save TheMapSmith/622e884832f5fc5d562d to your computer and use it in GitHub Desktop.
fetch tiles and stitch together
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import csv | |
import math | |
import os.path | |
import urllib | |
### Function to Read in trace from csv ### | |
def traceImportCSV(fname): | |
import csv | |
trace = [] | |
for lat,lon in csv.reader(open(fname,'r')): | |
trace.append([float(lat),float(lon)]) | |
return trace | |
### Function to Read in trace from GPX ### | |
### Function to get trace boundries ### | |
def traceBoundaries(trace): | |
lat = zip(*trace)[0] | |
lon = zip(*trace)[1] | |
return {"north":max(lat),"south":min(lat),"east":max(lon),"west":min(lon)} | |
### Function to convert lat,lon degrees to tile x/y number ### | |
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.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n) | |
return (xtile, ytile) | |
### Function to convert xy tile to NW corner of tile ### | |
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) | |
### Determine tile range given boundaries and zoom ### | |
def determineTileRange(boundaries,zoom): | |
Xmax,Ymin = deg2num(boundaries["north"],boundaries["east"],zoom) | |
Xmin,Ymax = deg2num(boundaries["south"],boundaries["west"],zoom) | |
return {"xMin":Xmin,"xMax":Xmax,"yMin":Ymin,"yMax":Ymax} | |
### Take a tile range and download them (if not locally present) ### | |
def getTiles(xyRange,zoom): | |
#set acive directory to that of the script | |
currentdir = os.curdir | |
tileDir = os.path.join(currentdir,"/Users/spoon/Documents/tiles/golf/peter/") | |
tileServerUrl = "http://localhost:3000/style/" | |
#create a list of all the x and y coordinates to download | |
xRange = range(xyRange["xMin"],xyRange["xMax"]+1) | |
yRange = range(xyRange["yMin"],xyRange["yMax"]+1) | |
for x in xRange: | |
for y in yRange: | |
#define the file name | |
tileFileName = str(y)+".png" | |
#define the local path as well as the complete path to the local and remote files | |
localPath = os.path.join(tileDir,str(zoom),str(x)) | |
localFile = os.path.join(localPath,tileFileName) | |
preFile = tileServerUrl+str(zoom)+"/"+str(x)+"/"+str(y)+"@4x.png" | |
remoteFile = preFile + "?id=tmstyle:///Users/spoon/Dropbox/GolfMap/_style/peter.tm2&hzrt9lj6" | |
#check if the file exists locally | |
if not os.path.isfile(localFile): | |
print "retrieving "+remoteFile | |
#if local directory doesn't yet exist, make it | |
if not os.path.isdir(localPath): | |
os.makedirs(localPath) | |
#retrieve the file from the server and save it | |
urllib.urlretrieve(remoteFile,localFile) | |
### Merge tiles into one image ### | |
def mergeTiles(xyRange,zoom,filename): | |
from PIL import Image | |
tileSize = 1024 | |
tileDir = os.path.join(os.getcwd(),"/Users/spoon/Documents/tiles/golf/peter/",str(zoom)) | |
out = Image.new( 'RGBA', ((xyRange["xMax"]-xyRange["xMin"]+1) * tileSize, (xyRange["yMax"]-xyRange["yMin"]+1) * tileSize) ) | |
imx = 0; | |
for x in range(xyRange["xMin"], xyRange["xMax"]+1): | |
imy = 0 | |
for y in range(xyRange["yMin"], xyRange["yMax"]+1): | |
tileFile = os.path.join(tileDir,str(x),str(y)+".png") | |
tile = Image.open(tileFile) | |
out.paste( tile, (imx, imy) ) | |
imy += tileSize | |
imx += tileSize | |
out.save(os.path.join(os.curdir,filename)) | |
# define parameters | |
zoom = 21 | |
trace = traceImportCSV(r"peter.csv") | |
# determine the boundaries of the trace | |
boundaries_trace = traceBoundaries(trace) | |
# determine xy numbers of boundary tiles | |
tileRange = determineTileRange(boundaries_trace,zoom) | |
# count number of tiles in x and y direction | |
xTiles = tileRange["xMax"]-tileRange["xMin"] | |
yTiles = tileRange["yMax"]-tileRange["yMin"] | |
numTiles = xTiles*yTiles | |
print "fetching " + str(numTiles) + " tiles" | |
# download tiles if needed | |
getTiles(tileRange,zoom) | |
print "Got all the tiles. Merging" | |
# merge tiles into oneimage | |
mergeTiles(tileRange,zoom,r"peter-21-4x.png") | |
print "boundaries: ",boundaries_trace | |
print "tile X,Y range: ",tileRange | |
print "x tiles: ",xTiles | |
print "y tiles: ",yTiles | |
print "num tiles: ",numTiles | |
#Current record: AVAST Pete WP sized | |
#x tiles: 433 | |
#y tiles: 258 | |
#num tiles: 111714 | |
#[Finished in 18099.2s] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment