def tile_box(self): """ Expands the bounding box to the next even tile box. If the previously calculated box of tiles is smaller than the window size tiles are added until the box is larger than the window size @returns: the geographic coordinates of the bounding box of the displayed tiles @rtype: [min_lon, min_lat, max_lon, max_lat] """ (min_x, max_y), (max_x, min_y) = self.__tiles_zoom_level while self.__d_tiles_x * TILE_SIZE < self.__window_width: self.__d_tiles_x += 1 #: stores the number of displayed tiles in x-direction max_x += 1 while self.__d_tiles_y * TILE_SIZE < self.__window_height: self.__d_tiles_y += 1 #: stores the number of displayed tiles in y-direction min_y += 1 # recalculate the tiles that will be displayed self.__tiles_zoom_level = [(min_x, max_y), (max_x, min_y)] # calculate the geographic coordinates of the edges s1, w1, n1, e1 = tileEdges(min_x, max_y, self.__zoom_level) s2, w2, n2, e2 = tileEdges(max_x, min_y, self.__zoom_level) # calculate the expansion of the displayed tiles in pixels self.__box_pixel = (self.__d_tiles_x * TILE_SIZE, self.__d_tiles_y * TILE_SIZE) #: pixel size of the box spanned by the displayed tiles (width, height) return [w1, s2, e2, n1]
def genInfoFile(tileCollection): infoFileName = tileCollection.getMapName(" ") + ".info" print("Writing info file to", infoFileName) # S lat, W lon, N lat, E lon startCornerCoords = tilenames.tileEdges(tileCollection.tileStartX, tileCollection.tileStartY, tileCollection.zoom) endCornerCoords = tilenames.tileEdges(tileCollection.tileEndX, tileCollection.tileEndY, tileCollection.zoom) latStartCorner, lonStartCorner = startCornerCoords[2], startCornerCoords[1] # Get's north-west tile start lat & lon latEndCorner, lonEndCorner = endCornerCoords[0], endCornerCoords[3] # Get's south-east tile end lat & lon infoFile = open(infoFileName, "w") print("// Generated with Anaxi Tile Downloader", file=infoFile) print("lat_north=", latStartCorner, file=infoFile) print("lat_south=", latEndCorner, file=infoFile) print("lon_east=", lonEndCorner, file=infoFile) print("lon_west=", lonStartCorner, file=infoFile) print("tileStartX=", tileCollection.tileStartX, file=infoFile) print("tileStartY=", tileCollection.tileStartY, file=infoFile) print("tileEndX=", tileCollection.tileEndX, file=infoFile) print("tileEndY=", tileCollection.tileEndY, file=infoFile) print("zoom=", tileCollection.zoom, file=infoFile) print("numTiles=", len(tileCollection.tiles), file=infoFile) print("mapFile=", tileCollection.getMapName(), file=infoFile) print("cmd=", " ".join(sys.argv), file=infoFile)
def GetOsmTileData(z,x,y): """Download OSM data for the region covering a slippy-map tile""" if(x < 0 or y < 0 or z < 0 or z > 25): print("Disallowed (%d,%d) at zoom level %d" % (x, y, z)) return directory = 'cache/%d/%d/%d' % (z,x,y) filename = '%s/data.osm.pkl' % (directory) if(not os.path.exists(directory)): os.makedirs(directory) if(z == DownloadLevel()): # Download the data s,w,n,e = tileEdges(x,y,z) # /api/0.6/map?bbox=left,bottom,right,top URL = 'http://api.openstreetmap.org/api/0.6/map?bbox={},{},{},{}'.format(w,s,e,n) if(not os.path.exists(filename)): # TODO: allow expiry of old data urlretrieve(URL, filename) return(filename) elif(z > DownloadLevel()): # use larger tile while(z > DownloadLevel()): z = z - 1 x = int(x / 2) y = int(y / 2) return(GetOsmTileData(z,x,y)) return(None)
def GetOsmTileData(z, x, y): """Download OSM data for the region covering a slippy-map tile""" if (x < 0 or y < 0 or z < 0 or z > 25): print("Disallowed (%d,%d) at zoom level %d" % (x, y, z)) return directory = 'cache/%d/%d/%d' % (z, x, y) filename = '%s/data.osm.pkl' % (directory) if (not os.path.exists(directory)): os.makedirs(directory) if (z == DownloadLevel()): # Download the data s, w, n, e = tileEdges(x, y, z) # /api/0.6/map?bbox=left,bottom,right,top URL = 'http://api.openstreetmap.org/api/0.6/map?bbox={},{},{},{}'.format( w, s, e, n) if (not os.path.exists(filename)): # TODO: allow expiry of old data urlretrieve(URL, filename) return (filename) elif (z > DownloadLevel()): # use larger tile while (z > DownloadLevel()): z = z - 1 x = int(x / 2) y = int(y / 2) return (GetOsmTileData(z, x, y)) return (None)
def get_tile_coordinates(self, lat, lon): """ Gets for a point given by its geographic coordinates the geographic coordinates of the edges of the tile this point lies in. @param lat: Geographic latitude of a point @param lon: Geographic longitude of a point @returns: Geographic coordinates of the edges of the corresponding tile @rtype: (min_lat, min_lon, max_lat, max_lon) """ x, y = tileXY(lat, lon, self.__zoom_level) return tileEdges(x, y, self.__zoom_level) # S, W, N, E
def draw_tile_box(x, y): """ Draws the slippy map tile x, y on the screen """ key = (self.zoom_level,x,y) # Read tile from disk if not in memory cache if self.tiles.has_key(key): t = self.tiles[key] else: t = Tile(x, y, self.zoom_level) t.load() self.tiles[key] = t edges = tilenames.tileEdges(x, y, self.zoom_level) offsetlat = edges[2]-focus[0] # North edge offset offsetlong = edges[1]-focus[1] # West edge offset self.tileheight_deg = edges[2]-edges[0] self.tilewidth_deg = edges[3]-edges[1] px = int(offsetlong / self.tilewidth_deg * 256) py = int(-offsetlat / self.tileheight_deg * 256) self.window.draw_pixbuf(self.get_style().fg_gc[gtk.STATE_NORMAL], t.pixbuf, 0, 0, w/2 + int(px), h/2 + int(py) ) """ Adding placemark icons from the database and removing them when user is moving the map """ if (self.draw_icons == True): self.dbobjects = self.get_objects_from_db() #if (self.i % 20 == 0): for e in self.dbobjects: (f,g) = self._coord_to_pixel(e.long,e.lat) if e.__class__ == Mission: if (e.status != 3): self.window.draw_pixbuf(self.get_style().fg_gc[gtk.STATE_NORMAL], self.mission_pic, 0, 0, int(f), int(g)-10,19,33) if e.__class__ == Placemark: if (e.type == 1): self.window.draw_pixbuf(self.get_style().fg_gc[gtk.STATE_NORMAL], self.obstacle_pic, 0, 0, int(f), int(g),29,29) if (e.type == 2): self.window.draw_pixbuf(self.get_style().fg_gc[gtk.STATE_NORMAL], self.water_pic, 0, 0, int(f), int(g),29,29) if (e.type == 3): self.window.draw_pixbuf(self.get_style().fg_gc[gtk.STATE_NORMAL], self.power_pic, 0, 0, int(f), int(g),29,29) self.i = self.i-1
def get_coord_by_position_in_tile(self, tile_x, tile_y, x, y): """ Calculates for the pixel coordinates of a point within a tile the corresponding geographic cordinates @type tile_x: C{int} @param tile_x: slippy map tilename in x direction @type tile_y: C{int} @param tile_y: slippy map tilename in y direction @type x: C{int} @param x: x coordinate within the tile @type y: C{int} @param y: y coordinate within the tile @returns: Geographic coordinates of the point as a tuple (lat, lon) @rtype: C{lat, lon)} """ s, w, n, e = tileEdges(tile_x, tile_y, self.__zoom_level) lat = y * (s - n) / TILE_SIZE + n lon = x * (e - w) / TILE_SIZE + w return (lat, lon)
def draw_tile_box(x, y): edges = tilenames.tileEdges(x, y, self.zoom_level) #print edges offsetlat = edges[0]-focus[0] offsetlong = edges[1]-focus[1] self.tileheight_deg = edges[2]-edges[0] self.context.rectangle( offsetlong / self.tilewidth_deg * 256, offsetlat / self.tileheight_deg * 256, 256, 256) self.context.fill() self.context.move_to( offsetlong / self.tilewidth_deg * 256 + 128, offsetlat / self.tileheight_deg * 256 + 128) self.context.set_source_rgb(0, 0, 0) self.context.set_font_size(12) self.context.show_text("%s, %s" % (x, y))
def GetOsmTileData(z, x, y): """Download OSM data for the region covering a slippy-map tile""" if x < 0 or y < 0 or z < 0 or z > 25: print "Disallowed %d,%d at %d" % (x, y, z) return directory = "cache/%d/%d/" % (z, x) filename = "%s/%s.png" % (directory, y) if not os.path.exists(directory): os.makedirs(directory) (S, W, N, E) = tileEdges(x, y, z) # Download the data # URL = 'http://dev.openstreetmap.org/~ojw/api/?/map/%d/%d/%d' % (z,x,y) # URL = 'http://map02.eniro.com/geowebcache/service/tms1.0.0/map/%s/%s/%s.png' % (z,x,y) # URL = 'http://%s/api/0.6/map?bbox=%f,%f,%f,%f' % ('api.openstreetmap.org',W,S,E,N) URL = "http://c.tile.openstreetmap.org/%s/%s/%s.png" % (z, x, y) print URL if not os.path.exists(filename): # TODO: allow expiry of old data print "Downloading %d/%d/%d from network" % (z, x, y) urlretrieve(URL, filename) return filename
def pdfer(data, page_size='letter'): overlays = data.get('overlays') grid = {'zoom': data.get('zoom')} center_lon, center_lat = data['center'] center_tile_x, center_tile_y = tileXY(float(center_lat), float(center_lon), int(data['zoom'])) dim_across, dim_up = data['dimensions'] if dim_across > dim_up: page_height, page_width, tiles_up, tiles_across = PAGE_SIZES[page_size] orientation = 'landscape' else: page_width, page_height, tiles_across, tiles_up = PAGE_SIZES[page_size] orientation = 'portrait' min_tile_x = center_tile_x - (tiles_across / 2) min_tile_y = center_tile_y - (tiles_up / 2) max_tile_x = min_tile_x + tiles_across max_tile_y = min_tile_y + tiles_up links = [] for ty in range(min_tile_y, max_tile_y + 1): for tx in range(min_tile_x, max_tile_x + 1): links.append( 'http://a.tiles.mapbox.com/v3/datamade.hnmob3j3/{0}/{1}/{2}.png' .format(grid['zoom'], tx, ty)) names = dl_write_all(links) now = datetime.now() date_string = datetime.strftime(now, '%Y-%m-%d_%H-%M-%S') outp_name = os.path.join('/tmp', '{0}.png'.format(date_string)) image_names = ['-'.join(l.split('/')[-3:]) for l in names] image_names = sorted([i.split('-') for i in image_names]) arrays = [] for k, g in groupby(image_names, key=itemgetter(4)): images = list(g) fnames = ['/tmp/%s' % ('-'.join(f)) for f in images] array = [] for img in fnames: array.append(cv2.imread(img)) arrays.append(np.vstack(array)) outp = np.hstack(arrays) cv2.imwrite(outp_name, outp) for parts in image_names: parts = parts[3:] parts[-1] = parts[-1].rstrip('.png') key = '-'.join(parts[-3:]) grid[key] = { 'bbox': tileEdges(float(parts[1]), float(parts[2]), int(parts[0])) } d = {} keys = sorted(grid.keys()) if overlays: polys = [] for k, v in grid.items(): try: one, two, three, four = grid[k]['bbox'] polys.append(box(two, one, four, three)) except TypeError: pass mpoly = MultiPolygon(polys) bb_poly = box(*mpoly.bounds) min_key = keys[0] max_key = keys[-2] bminx, bminy = grid[min_key]['bbox'][0], grid[min_key]['bbox'][1] bmaxx, bmaxy = grid[max_key]['bbox'][2], grid[max_key]['bbox'][3] bmin_mx, bmin_my = mercator.LatLonToMeters(bminx, bminy) bmax_mx, bmax_my = mercator.LatLonToMeters(bmaxx, bmaxy) bmin_px, bmin_py = mercator.MetersToPixels(bmin_mx, bmin_my, float(grid['zoom'])) bmax_px, bmax_py = mercator.MetersToPixels(bmax_mx, bmax_my, float(grid['zoom'])) bmin_rx, bmin_ry = mercator.PixelsToRaster(bmin_px, bmin_py, int(grid['zoom'])) im = cairo.ImageSurface.create_from_png(outp_name) ctx = cairo.Context(im) for beat_overlay in overlays.get('beat_overlays'): color = hex_to_rgb('#7B3294') boundary = requests.get( 'http://crimearound.us/data/beats/%s.geojson' % beat_overlay) if boundary.status_code == 200: coords = boundary.json()['coordinates'][0] x, y = get_pixel_coords(coords[0], grid['zoom'], bmin_rx, bmin_ry) ctx.move_to(x, y) ctx.set_line_width(4.0) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red / 255, green / 255, blue / 255, 0.7) ctx.line_to(x, y) ctx.close_path() ctx.stroke() if overlays.get('shape_overlay'): shape_overlay = overlays['shape_overlay'] color = hex_to_rgb('#f06eaa') coords = shape_overlay['coordinates'][0] x, y = get_pixel_coords(coords[0], grid['zoom'], bmin_rx, bmin_ry) ctx.move_to(x, y) ctx.set_line_width(4.0) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red / 255, green / 255, blue / 255, 0.3) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) ctx.line_to(x, y) ctx.close_path() ctx.fill() ctx.set_source_rgba(red / 255, green / 255, blue / 255, 0.5) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) ctx.line_to(x, y) ctx.close_path() ctx.stroke() ctx.set_line_width(2.0) for point_overlay in overlays.get('point_overlays'): color = hex_to_rgb(point_overlay['color']) for p in point_overlay['points']: if p[0] and p[1]: pt = Point((float(p[0]), float(p[1]))) if bb_poly.contains(pt): nx, ny = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red / 255, green / 255, blue / 255, 0.6) ctx.arc(nx, ny, 5.0, 0, 50) # args: center-x, center-y, radius, ?, ? ctx.fill() ctx.arc(nx, ny, 5.0, 0, 50) ctx.stroke() im.write_to_png(outp_name) scale = 1 pdf_name = outp_name.rstrip('.png') + '.pdf' pdf = cairo.PDFSurface(pdf_name, page_width, page_height) ctx = cairo.Context(pdf) image = cairo.ImageSurface.create_from_png(outp_name) ctx.set_source_surface(image, 0, 0) ctx.paint() pdf.finish() return pdf_name
def pdfer(data, page_size=PAGE_SIZES['letter']): overlays = data.get('overlays') grid = {'zoom': data.get('zoom')} center_lon, center_lat = data['center'] center_tile_x, center_tile_y = tileXY(float(center_lat), float(center_lon), int(data['zoom'])) dim_across, dim_up = data['dimensions'] if dim_across > dim_up: page_height, page_width, tiles_up, tiles_across = page_size orientation = 'landscape' else: page_width, page_height, tiles_across, tiles_up = page_size orientation = 'portrait' min_tile_x = center_tile_x - (tiles_across / 2) min_tile_y = center_tile_y - (tiles_up / 2) max_tile_x = min_tile_x + tiles_across max_tile_y = min_tile_y + tiles_up links = [] for ty in range(min_tile_y, max_tile_y + 1): for tx in range(min_tile_x, max_tile_x + 1): links.append('http://a.tiles.mapbox.com/v3/datamade.hnmob3j3/{0}/{1}/{2}.png'.format(grid['zoom'], tx, ty)) names = dl_write_all(links) now = datetime.now() date_string = datetime.strftime(now, '%Y-%m-%d_%H-%M-%S') outp_name = os.path.join('/tmp', '{0}.png'.format(date_string)) image_names = ['-'.join(l.split('/')[-3:]) for l in names] image_names = sorted([i.split('-') for i in image_names]) arrays = [] for k,g in groupby(image_names, key=itemgetter(4)): images = list(g) fnames = ['/tmp/%s' % ('-'.join(f)) for f in images] array = [] for img in fnames: array.append(cv2.imread(img)) arrays.append(np.vstack(array)) outp = np.hstack(arrays) cv2.imwrite(outp_name, outp) for parts in image_names: parts = parts[3:] parts[-1] = parts[-1].rstrip('.png') key = '-'.join(parts[-3:]) grid[key] = {'bbox': tileEdges(float(parts[1]),float(parts[2]),int(parts[0]))} d = {} keys = sorted(grid.keys()) if overlays: polys = [] for k,v in grid.items(): try: one,two,three,four = grid[k]['bbox'] polys.append(box(two, one, four, three)) except TypeError: pass mpoly = MultiPolygon(polys) bb_poly = box(*mpoly.bounds) min_key = keys[0] max_key = keys[-2] bminx, bminy = grid[min_key]['bbox'][0], grid[min_key]['bbox'][1] bmaxx, bmaxy = grid[max_key]['bbox'][2], grid[max_key]['bbox'][3] bmin_mx, bmin_my = mercator.LatLonToMeters(bminx, bminy) bmax_mx, bmax_my = mercator.LatLonToMeters(bmaxx, bmaxy) bmin_px, bmin_py = mercator.MetersToPixels(bmin_mx,bmin_my,float(grid['zoom'])) bmax_px, bmax_py = mercator.MetersToPixels(bmax_mx,bmax_my,float(grid['zoom'])) bmin_rx, bmin_ry = mercator.PixelsToRaster(bmin_px,bmin_py,int(grid['zoom'])) im = cairo.ImageSurface.create_from_png(outp_name) ctx = cairo.Context(im) for beat_overlay in overlays.get('beat_overlays'): color = hex_to_rgb('#7B3294') boundary = requests.get('http://crimearound.us/data/beats/%s.geojson' % beat_overlay) if boundary.status_code == 200: coords = boundary.json()['coordinates'][0] x, y = get_pixel_coords(coords[0], grid['zoom'], bmin_rx, bmin_ry) ctx.move_to(x,y) ctx.set_line_width(4.0) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red/255, green/255, blue/255, 0.7) ctx.line_to(x,y) ctx.close_path() ctx.stroke() if overlays.get('shape_overlay'): shape_overlay = overlays['shape_overlay'] color = hex_to_rgb('#f06eaa') coords = shape_overlay['coordinates'][0] x, y = get_pixel_coords(coords[0], grid['zoom'], bmin_rx, bmin_ry) ctx.move_to(x,y) ctx.set_line_width(4.0) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red/255, green/255, blue/255, 0.3) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) ctx.line_to(x,y) ctx.close_path() ctx.fill() ctx.set_source_rgba(red/255, green/255, blue/255, 0.5) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) ctx.line_to(x,y) ctx.close_path() ctx.stroke() ctx.set_line_width(2.0) for point_overlay in overlays.get('point_overlays'): color = hex_to_rgb(point_overlay['color']) for p in point_overlay['points']: if p[0] and p[1]: pt = Point((float(p[0]), float(p[1]))) if bb_poly.contains(pt): nx, ny = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red/255, green/255, blue/255, 0.6) ctx.arc(nx, ny, 5.0, 0, 50) # args: center-x, center-y, radius, ?, ? ctx.fill() ctx.arc(nx, ny, 5.0, 0, 50) ctx.stroke() im.write_to_png(outp_name) scale = 1 pdf_name = outp_name.rstrip('.png') + '.pdf' pdf = cairo.PDFSurface(pdf_name, page_width, page_height) ctx = cairo.Context(pdf) image = cairo.ImageSurface.create_from_png(outp_name) ctx.set_source_surface(image, 0, 0) ctx.paint() pdf.finish() return pdf_name
def processTileParams(prefs): tileStartX, tileStartY = tilenames.tileXY(prefs.latStart, prefs.lonStart, prefs.zoom, True) tileEndX, tileEndY = tilenames.tileXY(prefs.latEnd, prefs.lonEnd, prefs.zoom, True) # Sort the numbers low to high if tileStartY > tileEndY: tileStartY, tileEndY = tileEndY, tileStartY if tileStartX > tileEndX: tileStartX, tileEndX = tileEndX, tileStartX tileStartX, tileStartY = math.floor(tileStartX), math.floor(tileStartY) tileEndX, tileEndY = math.ceil(tileEndX), math.ceil(tileEndY) # S lat, W lon, N lat, E lon startCornerCoords = tilenames.tileEdges(tileStartX, tileStartY, prefs.zoom) endCornerCoords = tilenames.tileEdges(tileEndX, tileEndY, prefs.zoom) latStartCorner, lonStartCorner = startCornerCoords[2], startCornerCoords[1] # Get's north-west tile start lat & lon latEndCorner, lonEndCorner = endCornerCoords[0], endCornerCoords[3] # Get's south-east tile end lat & lon print("Starting at North-West corner: [" + str(latStartCorner) + ", " + str(lonStartCorner) + "]") print("Ending at South-East corner: [" + str(latEndCorner) + ", " + str(lonEndCorner) + "]") print("Downloading X tiles", tileStartX, "through", tileEndX) print("Downloading Y tiles", tileStartY, "through", tileEndY) print("Downloading a total of", abs(tileEndX - tileStartX + 1) * abs(tileEndY - tileStartY + 1), "tiles") print("Each tile at this zoom will be ~", str(tilenames.horozontalDistance(latStartCorner, prefs.zoom)), "meters wide") if prefs.dryRun: try: checkPilInstalled() except (ImportError, ModuleNotFoundError) as e: print("PIL is not installed, image stitching will not be supported") print("Dry run, exiting now...") return 0 if not os.path.exists(prefs.name): os.mkdir(prefs.name) os.chdir(prefs.name) tileCol = TileCollection(tileStartX, tileStartY, tileEndX, tileEndY, prefs.zoom, prefs.tileServer, prefs.name) if not os.path.exists("raw"): os.mkdir("raw") os.chdir("raw") downloadErr = tileCol.downloadTiles(prefs.forceDownload) if downloadErr == 0: print("Download Complete!") if not prefs.noStitch: print("Stitching images...") stitchResult = tileCol.stitchImages(prefs.stitchFormat) if stitchResult["err"] == 0: os.rename(stitchResult["imageName"], "../" + stitchResult["imageName"]) os.chdir("..") return genInfoFile(tileCol) return downloadErr
def pdfer(data, page_size=PAGE_SIZES['letter'], output='pdf'): shape_overlays = data.get('shape_overlays') point_overlays = data.get('point_overlays') grid = {'zoom': data.get('zoom')} center_lon, center_lat = data['center'] center_tile_x, center_tile_y = tileXY(float(center_lat), float(center_lon), int(data['zoom'])) dim_across, dim_up = data['dimensions'] if dim_across > dim_up: page_height, page_width, tiles_up, tiles_across = page_size else: page_width, page_height, tiles_across, tiles_up = page_size min_tile_x = center_tile_x - (tiles_across / 2) min_tile_y = center_tile_y - (tiles_up / 2) max_tile_x = min_tile_x + tiles_across max_tile_y = min_tile_y + tiles_up # Get base layer tiles base_pattern = 'http://d.tile.stamen.com/toner/{z}/{x}/{y}.png' if data.get('base_tiles'): base_pattern = data['base_tiles'] base_links = generateLinks(base_pattern, grid['zoom'], min_tile_x, min_tile_y, max_tile_x, max_tile_y) base_names = dl_write_all(base_links, 'base') # Get overlay tiles overlay_pattern = None if data.get('overlay_tiles'): overlay_pattern = data['overlay_tiles'] overlay_links = generateLinks(overlay_pattern, grid['zoom'], min_tile_x, min_tile_y, max_tile_x, max_tile_y) overlay_names = dl_write_all(overlay_links, 'overlay') now = datetime.now() date_string = datetime.strftime(now, '%Y-%m-%d_%H-%M-%S') outp_name = os.path.join('/tmp', '{0}.png'.format(date_string)) base_image_names = ['-'.join(l.split('/')[-3:]) for l in base_names] base_image_names = sorted([i.split('-')[-3:] for i in base_image_names], key=itemgetter(1)) for parts in base_image_names: z,x,y = parts y = y.rstrip('.png').rstrip('.jpg') z = z.rsplit('_', 1)[1] key = '-'.join([z,x,y]) grid[key] = {'bbox': tileEdges(float(x),float(y),int(z))} keys = sorted(grid.keys()) mercator = GlobalMercator() bb_poly = None bmin_rx = None bmin_ry = None if shape_overlays or point_overlays: polys = [] for k,v in grid.items(): try: one,two,three,four = grid[k]['bbox'] polys.append(box(two, one, four, three)) except TypeError: pass mpoly = MultiPolygon(polys) bb_poly = box(*mpoly.bounds) min_key = keys[0] max_key = keys[-2] bminx, bminy = grid[min_key]['bbox'][0], grid[min_key]['bbox'][1] bmaxx, bmaxy = grid[max_key]['bbox'][2], grid[max_key]['bbox'][3] bmin_mx, bmin_my = mercator.LatLonToMeters(bminx, bminy) bmax_mx, bmax_my = mercator.LatLonToMeters(bmaxx, bmaxy) bmin_px, bmin_py = mercator.MetersToPixels(bmin_mx,bmin_my,float(grid['zoom'])) bmax_px, bmax_py = mercator.MetersToPixels(bmax_mx,bmax_my,float(grid['zoom'])) bmin_rx, bmin_ry = mercator.PixelsToRaster(bmin_px,bmin_py,int(grid['zoom'])) if shape_overlays: all_polys = [] for shape_overlay in shape_overlays: shape_overlay = json.loads(shape_overlay) if shape_overlay.get('geometry'): shape_overlay = shape_overlay['geometry'] coords = shape_overlay['coordinates'][0] all_polys.append(Polygon(coords)) mpoly = MultiPolygon(all_polys) one, two, three, four, five = list(box(*mpoly.bounds).exterior.coords) left, right = LineString([one, two]), LineString([three, four]) top, bottom = LineString([two, three]), LineString([four, five]) left_to_right = left.distance(right) top_to_bottom = top.distance(bottom) if left_to_right > top_to_bottom: page_height, page_width, _, _ = page_size else: page_width, page_height, _, _ = page_size center_lon, center_lat = list(mpoly.centroid.coords)[0] if point_overlays: all_points = [] for point_overlay in point_overlays: point_overlay = json.loads(point_overlay) for p in point_overlay['points']: if p[0] and p[1]: all_points.append(p) mpoint = MultiPoint(all_points) center_lon, center_lat = list(mpoint.centroid.coords)[0] one, two, three, four, five = list(box(*mpoint.bounds).exterior.coords) left, right = LineString([one, two]), LineString([three, four]) top, bottom = LineString([two, three]), LineString([four, five]) left_to_right = left.distance(right) top_to_bottom = top.distance(bottom) if left_to_right > top_to_bottom: page_height, page_width, _, _ = page_size else: page_width, page_height, _, _ = page_size center_lon, center_lat = list(mpoint.centroid.coords)[0] print(center_lon, center_lat) arrays = [] for k,g in groupby(base_image_names, key=itemgetter(1)): images = list(g) fnames = ['/tmp/%s' % ('-'.join(f)) for f in images] array = [] for img in fnames: i = cv2.imread(img, -1) if isinstance(i, type(None)): i = np.zeros((256,256,4), np.uint8) elif i.shape[2] != 4: i = cv2.cvtColor(cv2.imread(img), cv2.COLOR_BGR2BGRA) array.append(i) arrays.append(np.vstack(array)) outp = np.hstack(arrays) cv2.imwrite(outp_name, outp) if overlay_pattern: overlay_outp_name = os.path.join('/tmp', 'overlay_{0}.png'.format(date_string)) overlay_image_names = ['-'.join(l.split('/')[-3:]) for l in overlay_names] overlay_image_names = sorted([i.split('-')[-3:] for i in overlay_image_names], key=itemgetter(1)) arrays = [] for k,g in groupby(overlay_image_names, key=itemgetter(1)): images = list(g) fnames = ['/tmp/%s' % ('-'.join(f)) for f in images] array = [] for img in fnames: i = cv2.imread(img, -1) if isinstance(i, type(None)): i = np.zeros((256,256,4), np.uint8) elif i.shape[2] != 4: i = cv2.cvtColor(cv2.imread(img), cv2.COLOR_BGR2BGRA) array.append(i) arrays.append(np.vstack(array)) nuked = [os.remove(f) for f in fnames] outp = np.hstack(arrays) cv2.imwrite(overlay_outp_name, outp) base = cv2.imread(outp_name, -1) overlay = cv2.imread(overlay_outp_name, -1) overlay_g = cv2.cvtColor(overlay, cv2.COLOR_BGR2GRAY) ret, mask = cv2.threshold(overlay_g, 10, 255, cv2.THRESH_BINARY) inverted = cv2.bitwise_not(mask) overlay = cv2.bitwise_not(overlay, overlay, mask=inverted) base_alpha = 0.55 overlay_alpha = 1 for channel in range(3): x,y,d = overlay.shape base[:,:,channel] = (base[:,:,channel] * base_alpha + \ overlay[:,:,channel] * overlay_alpha * \ (1 - base_alpha)) / \ (base_alpha + overlay_alpha * (1 - base_alpha)) cv2.imwrite(outp_name, base) ########################################################################### # Code below here is for drawing vector layers within the PDF # # Leaving it in just because it was a pain to come up with the first time # ########################################################################### if shape_overlays or point_overlays: im = cairo.ImageSurface.create_from_png(outp_name) ctx = cairo.Context(im) if shape_overlays: for shape_overlay in shape_overlays: shape_overlay = json.loads(shape_overlay) if shape_overlay.get('geometry'): shape_overlay = shape_overlay['geometry'] color = hex_to_rgb('#f06eaa') coords = shape_overlay['coordinates'][0] x, y = get_pixel_coords(coords[0], grid['zoom'], bmin_rx, bmin_ry) ctx.move_to(x,y) ctx.set_line_width(4.0) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red/255, green/255, blue/255, 0.3) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) ctx.line_to(x,y) ctx.close_path() ctx.fill() ctx.set_source_rgba(red/255, green/255, blue/255, 0.5) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) ctx.line_to(x,y) ctx.close_path() ctx.stroke() ctx.set_line_width(2.0) if point_overlays: for point_overlay in point_overlays: point_overlay = json.loads(point_overlay) color = hex_to_rgb(point_overlay['color']) for p in point_overlay['points']: if p[0] and p[1]: pt = Point((float(p[0]), float(p[1]))) if bb_poly.contains(pt): nx, ny = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red/255, green/255, blue/255, 0.6) ctx.arc(nx, ny, 5.0, 0, 50) # args: center-x, center-y, radius, ?, ? ctx.fill() ctx.arc(nx, ny, 5.0, 0, 50) ctx.stroke() im.write_to_png(outp_name) scale = 1 # Crop image from center center_point_x, center_point_y = latlon2xy(float(center_lat), float(center_lon), float(data['zoom'])) offset_x = (center_point_x - float(center_tile_x)) + 50 offset_y = (center_point_y - float(center_tile_y)) - 50 outp_image = cv2.imread(outp_name, -1) pixels_up, pixels_across, channels = outp_image.shape center_x, center_y = (pixels_across / 2) + offset_x, (pixels_up / 2) + offset_y start_y, end_y = center_y - (page_height / 2), center_y + (page_height / 2) start_x, end_x = center_x - (page_width / 2), center_x + (page_width / 2) cv2.imwrite(outp_name, outp_image[start_y:end_y, start_x:end_x]) if output == 'pdf': outp_file_name = outp_name.rstrip('.png') + '.pdf' pdf = cairo.PDFSurface(outp_file_name, page_width, page_height) ctx = cairo.Context(pdf) image = cairo.ImageSurface.create_from_png(outp_name) ctx.set_source_surface(image) ctx.paint() pdf.finish() elif output == 'jpeg': outp_file_name = outp_name.rstrip('.png') + '.jpg' jpeg = cv2.cvtColor(cv2.imread(outp_name, -1), cv2.COLOR_RGBA2RGB) cv2.imwrite(outp_file_name, jpeg) return outp_file_name
def pdfer(data, page_size=PAGE_SIZES['letter'], output='pdf'): shape_overlays = data.get('shape_overlays') point_overlays = data.get('point_overlays') grid = {'zoom': data.get('zoom')} center_lon, center_lat = data['center'] center_tile_x, center_tile_y = tileXY(float(center_lat), float(center_lon), int(data['zoom'])) dim_across, dim_up = data['dimensions'] if dim_across > dim_up: page_height, page_width, tiles_up, tiles_across = page_size else: page_width, page_height, tiles_across, tiles_up = page_size min_tile_x = center_tile_x - (tiles_across / 2) min_tile_y = center_tile_y - (tiles_up / 2) max_tile_x = min_tile_x + tiles_across max_tile_y = min_tile_y + tiles_up # Get base layer tiles base_pattern = 'http://d.tile.stamen.com/toner/{z}/{x}/{y}.png' if data.get('base_tiles'): base_pattern = data['base_tiles'] base_links = generateLinks(base_pattern, grid['zoom'], min_tile_x, min_tile_y, max_tile_x, max_tile_y) base_names = dl_write_all(base_links, 'base') # Get overlay tiles overlay_pattern = None if data.get('overlay_tiles'): overlay_pattern = data['overlay_tiles'] overlay_links = generateLinks(overlay_pattern, grid['zoom'], min_tile_x, min_tile_y, max_tile_x, max_tile_y) overlay_names = dl_write_all(overlay_links, 'overlay') now = datetime.now() date_string = datetime.strftime(now, '%Y-%m-%d_%H-%M-%S') outp_name = os.path.join('/tmp', '{0}.png'.format(date_string)) base_image_names = ['-'.join(l.split('/')[-3:]) for l in base_names] base_image_names = sorted([i.split('-')[-3:] for i in base_image_names], key=itemgetter(1)) for parts in base_image_names: z, x, y = parts y = y.rstrip('.png').rstrip('.jpg') z = z.rsplit('_', 1)[1] key = '-'.join([z, x, y]) grid[key] = {'bbox': tileEdges(float(x), float(y), int(z))} keys = sorted(grid.keys()) mercator = GlobalMercator() bb_poly = None bmin_rx = None bmin_ry = None if shape_overlays or point_overlays: polys = [] for k, v in grid.items(): try: one, two, three, four = grid[k]['bbox'] polys.append(box(two, one, four, three)) except TypeError: pass mpoly = MultiPolygon(polys) bb_poly = box(*mpoly.bounds) min_key = keys[0] max_key = keys[-2] bminx, bminy = grid[min_key]['bbox'][0], grid[min_key]['bbox'][1] bmaxx, bmaxy = grid[max_key]['bbox'][2], grid[max_key]['bbox'][3] bmin_mx, bmin_my = mercator.LatLonToMeters(bminx, bminy) bmax_mx, bmax_my = mercator.LatLonToMeters(bmaxx, bmaxy) bmin_px, bmin_py = mercator.MetersToPixels(bmin_mx, bmin_my, float(grid['zoom'])) bmax_px, bmax_py = mercator.MetersToPixels(bmax_mx, bmax_my, float(grid['zoom'])) bmin_rx, bmin_ry = mercator.PixelsToRaster(bmin_px, bmin_py, int(grid['zoom'])) if shape_overlays: all_polys = [] for shape_overlay in shape_overlays: shape_overlay = json.loads(shape_overlay) if shape_overlay.get('geometry'): shape_overlay = shape_overlay['geometry'] coords = shape_overlay['coordinates'][0] all_polys.append(Polygon(coords)) mpoly = MultiPolygon(all_polys) one, two, three, four, five = list( box(*mpoly.bounds).exterior.coords) left, right = LineString([one, two]), LineString([three, four]) top, bottom = LineString([two, three]), LineString([four, five]) left_to_right = left.distance(right) top_to_bottom = top.distance(bottom) if left_to_right > top_to_bottom: page_height, page_width, _, _ = page_size else: page_width, page_height, _, _ = page_size center_lon, center_lat = list(mpoly.centroid.coords)[0] if point_overlays: all_points = [] for point_overlay in point_overlays: point_overlay = json.loads(point_overlay) for p in point_overlay['points']: if p[0] and p[1]: all_points.append(p) mpoint = MultiPoint(all_points) center_lon, center_lat = list(mpoint.centroid.coords)[0] one, two, three, four, five = list( box(*mpoint.bounds).exterior.coords) left, right = LineString([one, two]), LineString([three, four]) top, bottom = LineString([two, three]), LineString([four, five]) left_to_right = left.distance(right) top_to_bottom = top.distance(bottom) if left_to_right > top_to_bottom: page_height, page_width, _, _ = page_size else: page_width, page_height, _, _ = page_size center_lon, center_lat = list(mpoint.centroid.coords)[0] print(center_lon, center_lat) arrays = [] for k, g in groupby(base_image_names, key=itemgetter(1)): images = list(g) fnames = ['/tmp/%s' % ('-'.join(f)) for f in images] array = [] for img in fnames: i = cv2.imread(img, -1) if isinstance(i, type(None)): i = np.zeros((256, 256, 4), np.uint8) elif i.shape[2] != 4: i = cv2.cvtColor(cv2.imread(img), cv2.COLOR_BGR2BGRA) array.append(i) arrays.append(np.vstack(array)) outp = np.hstack(arrays) cv2.imwrite(outp_name, outp) if overlay_pattern: overlay_outp_name = os.path.join('/tmp', 'overlay_{0}.png'.format(date_string)) overlay_image_names = [ '-'.join(l.split('/')[-3:]) for l in overlay_names ] overlay_image_names = sorted( [i.split('-')[-3:] for i in overlay_image_names], key=itemgetter(1)) arrays = [] for k, g in groupby(overlay_image_names, key=itemgetter(1)): images = list(g) fnames = ['/tmp/%s' % ('-'.join(f)) for f in images] array = [] for img in fnames: i = cv2.imread(img, -1) if isinstance(i, type(None)): i = np.zeros((256, 256, 4), np.uint8) elif i.shape[2] != 4: i = cv2.cvtColor(cv2.imread(img), cv2.COLOR_BGR2BGRA) array.append(i) arrays.append(np.vstack(array)) nuked = [os.remove(f) for f in fnames] outp = np.hstack(arrays) cv2.imwrite(overlay_outp_name, outp) base = cv2.imread(outp_name, -1) overlay = cv2.imread(overlay_outp_name, -1) overlay_g = cv2.cvtColor(overlay, cv2.COLOR_BGR2GRAY) ret, mask = cv2.threshold(overlay_g, 10, 255, cv2.THRESH_BINARY) inverted = cv2.bitwise_not(mask) overlay = cv2.bitwise_not(overlay, overlay, mask=inverted) base_alpha = 0.55 overlay_alpha = 1 for channel in range(3): x, y, d = overlay.shape base[:,:,channel] = (base[:,:,channel] * base_alpha + \ overlay[:,:,channel] * overlay_alpha * \ (1 - base_alpha)) / \ (base_alpha + overlay_alpha * (1 - base_alpha)) cv2.imwrite(outp_name, base) ########################################################################### # Code below here is for drawing vector layers within the PDF # # Leaving it in just because it was a pain to come up with the first time # ########################################################################### if shape_overlays or point_overlays: im = cairo.ImageSurface.create_from_png(outp_name) ctx = cairo.Context(im) if shape_overlays: for shape_overlay in shape_overlays: shape_overlay = json.loads(shape_overlay) if shape_overlay.get('geometry'): shape_overlay = shape_overlay['geometry'] color = hex_to_rgb('#f06eaa') coords = shape_overlay['coordinates'][0] x, y = get_pixel_coords(coords[0], grid['zoom'], bmin_rx, bmin_ry) ctx.move_to(x, y) ctx.set_line_width(4.0) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red / 255, green / 255, blue / 255, 0.3) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) ctx.line_to(x, y) ctx.close_path() ctx.fill() ctx.set_source_rgba(red / 255, green / 255, blue / 255, 0.5) for p in coords[1:]: x, y = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) ctx.line_to(x, y) ctx.close_path() ctx.stroke() ctx.set_line_width(2.0) if point_overlays: for point_overlay in point_overlays: point_overlay = json.loads(point_overlay) color = hex_to_rgb(point_overlay['color']) for p in point_overlay['points']: if p[0] and p[1]: pt = Point((float(p[0]), float(p[1]))) if bb_poly.contains(pt): nx, ny = get_pixel_coords(p, grid['zoom'], bmin_rx, bmin_ry) red, green, blue = [float(c) for c in color] ctx.set_source_rgba(red / 255, green / 255, blue / 255, 0.6) ctx.arc( nx, ny, 5.0, 0, 50) # args: center-x, center-y, radius, ?, ? ctx.fill() ctx.arc(nx, ny, 5.0, 0, 50) ctx.stroke() im.write_to_png(outp_name) scale = 1 # Crop image from center center_point_x, center_point_y = latlon2xy(float(center_lat), float(center_lon), float(data['zoom'])) offset_x = (center_point_x - float(center_tile_x)) + 50 offset_y = (center_point_y - float(center_tile_y)) - 50 outp_image = cv2.imread(outp_name, -1) pixels_up, pixels_across, channels = outp_image.shape center_x, center_y = (pixels_across / 2) + offset_x, (pixels_up / 2) + offset_y start_y, end_y = center_y - (page_height / 2), center_y + (page_height / 2) start_x, end_x = center_x - (page_width / 2), center_x + (page_width / 2) cv2.imwrite(outp_name, outp_image[start_y:end_y, start_x:end_x]) if output == 'pdf': outp_file_name = outp_name.rstrip('.png') + '.pdf' pdf = cairo.PDFSurface(outp_file_name, page_width, page_height) ctx = cairo.Context(pdf) image = cairo.ImageSurface.create_from_png(outp_name) ctx.set_source_surface(image) ctx.paint() pdf.finish() elif output == 'jpeg': outp_file_name = outp_name.rstrip('.png') + '.jpg' jpeg = cv2.cvtColor(cv2.imread(outp_name, -1), cv2.COLOR_RGBA2RGB) cv2.imwrite(outp_file_name, jpeg) return outp_file_name