Пример #1
0
 def get_box_tiles(self, box):
     """ Calculates for a given bounding box the
     U{slippy map tilenames<http://wiki.openstreetmap.org/index.php/Slippy_map_tilenames>}
     of the tiles that are intersected by the bounding box.
     
     The calculated tiles are given by the U{slippy map tilenames<http://wiki.openstreetmap.org/index.php/Slippy_map_tilenames>}
     of the top/left edge tile and the bottom/right edge tile.
     
     @type box: C{[min_lat, min_lon, max_lat, max_lon]}
     @param box: OSM bounding box
     @returns: slippy map tile names of the top/left tile and right/bottom tile of a rectangular box in the format C{[(topleft_x, topleft_y), (bottomright_x, bottomright_y)]}
     @rtype: C{[(int, int), (int, int)]}
     """
     return [tileXY(box[3], box[0], self.__zoom_level),
             tileXY(box[1], box[2], self.__zoom_level)]
Пример #2
0
  def packWay(self, id, nodes, style, tags):
    """Compress a way for storage"""
    data = ''
    
    data += struct.pack("I", id)
    
    # Nodes
    data += struct.pack("I", len(nodes))
    for n in nodes:
      (id,lat,lon) = n
      (x,y) = tilenames.tileXY(lat,lon,31)
      data += struct.pack("III", x, y, id)

    # Styles
    data += struct.pack("I", self.enumIDs[style['name']])

    # Layer
    try:
      layer = int(tags.get('layer',0))
    except ValueError:  # yeah thanks for whoever entered "=1" as a layer number...
      layer = 0
    data += struct.pack("b", layer)

    # Important tags
    packedTags = ''
    packedTags += self.packTag("N", tags, 'name')
    packedTags += self.packTag("r", tags, 'ref')
    packedTags += self.packTag("r", tags, 'ncn_ref')
    data += struct.pack("H", len(packedTags)) + packedTags

    return(data)
Пример #3
0
 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
Пример #4
0
 def storeNode(self,id,lat,lon):
   """Store a node"""
   if(not self.nodesExist):
     (x,y) = tilenames.tileXY(lat,lon,z)
     self.db[str(id)] = "%f,%f,%d_%d"%(lat,lon,x,y)
     
     self.countNodes += 1
     self.prompt -= 1
     if(not self.prompt):
       self.prompt = self.promptFreq
       print "%1.3fM nodes" % (float(self.countNodes) / 1000000.0)
Пример #5
0
  def getArea(self, lat, lon):
    """Download data in the vicinity of a lat/long"""
    
    z = tiledata.DownloadLevel()
    (x,y) = tilenames.tileXY(lat, lon, z)

    tileID = '%d,%d'%(x,y)
    if(self.tiles.get(tileID,False)):
      #print "Already got %s" % tileID
      return
    self.tiles[tileID] = True
    
    filename = tiledata.GetOsmTileData(z,x,y)
    #print "Loading %d,%d at z%d from %s" % (x,y,z,filename)
    return(self.loadOsm(filename))
Пример #6
0
    def getArea(self, lat, lon):
        """Download data in the vicinity of a lat/long"""

        z = tiledata.DownloadLevel()
        (x, y) = tilenames.tileXY(lat, lon, z)

        tileID = '%d,%d' % (x, y)
        if self.tiles.get(tileID, False):
            #print("Already got %s" % tileID)
            return
        self.tiles[tileID] = True

        filename = tiledata.GetOsmTileData(z, x, y)
        #print("Loading %d,%d at z%d from %s" % (x,y,z,filename))
        return self.loadOsm(filename)
Пример #7
0
 def viewport_coordinates(self):
     """ Calculates the geographic coordinates of the edges of the MoSP-GeoTool viewport
     
     @returns: the geographic coordinates of the viewport
     @rtype: C{[min_lon, min_lat, max_lon, max_lat]}         
     """
     position_nw = self.get_position_in_tile(self.__selection_box[3], self.__selection_box[0])
     (tile_w, tile_n) = tileXY(self.__selection_box[3], self.__selection_box[0], self.__zoom_level)
     tiles_x = (position_nw[0] + self.__window_width) / TILE_SIZE
     tiles_y = (position_nw[1] + self.__window_height) / TILE_SIZE
     x = TILE_SIZE - ((tiles_x + 1) * TILE_SIZE - (position_nw[0] + self.__window_width))
     y = TILE_SIZE - ((tiles_y + 1) * TILE_SIZE - (position_nw[1] + self.__window_width))
     tile_e = tile_w + tiles_x
     tile_s = tile_n + tiles_y
     coord_se = self.get_coord_by_position_in_tile(tile_e, tile_s, x, y)
     return [self.__selection_box[0], coord_se[0], coord_se[1], self.__selection_box[3]]
Пример #8
0
    def getArea(self, lat, lon):
        """Download data in the vicinity of a lat/long.
    Return filename to existing or newly downloaded .osm file."""

        z = tiledata.DownloadLevel()
        (x, y) = tilenames.tileXY(lat, lon, z)

        tileID = '%d,%d' % (x, y)
        if (self.tiles.get(tileID, False)):
            #print "Already got %s" % tileID
            return
        self.tiles[tileID] = True

        filename = tiledata.GetOsmTileData(z, x, y)
        #print "Loading %d,%d at z%d from %s" % (x,y,z,filename)
        return (self.loadOsm(filename))
Пример #9
0
    def draw(self):
        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))

        (x, y, w, h) = self.get_allocation()
        focus = self.focus
        self.context.translate(w/2, h/2)
        x, y = tilenames.tileXY(focus[0], focus[1], self.zoom_level)
        self.tilewidth_deg = 360.0/tilenames.numTiles(self.zoom_level)
        #tileheight_deg = 180.0/tilenames.numTiles(self.zoom_level)
        #print self.focus
        #print x, y

        self.context.set_source_rgb(0, 0, 1)
        draw_tile_box(x, y)
        self.context.set_source_rgb(1, 0, 1)
        draw_tile_box(x-1, y)
        self.context.set_source_rgb(1, 0, 0)
        draw_tile_box(x+1, y)
        self.context.set_source_rgb(0, 0, 0)
        draw_tile_box(x, y+1)
        self.context.set_source_rgb(0, 1, 0)
        draw_tile_box(x, y-1)

        """
Пример #10
0
    def loadTileSet(self, lat, lon):
        size = self.tileSize + 2 * self.tileSize * self.surround

        img = Image.new("RGB", (size, size))

        tx, ty = tilenames.tileXY(lat, lon, self.zoom)
        i = 0
        for x in range(tx - self.surround, tx + self.surround + 1):
            j = 0
            for y in range(ty - self.surround, ty + self.surround + 1):
                tile = self.loadTile(self.zoom, x, y)
                img.paste(tile, (i * self.tileSize, j * self.tileSize))
                j += 1
            i += 1

            # tmp, lry = tilenames.latEdges(ty + self.surround + 1, self.zoom);
            # uly, tmp = tilenames.latEdges(ty - self.surround, self.zoom);
            # ulx, tmp = tilenames.lonEdges(tx - self.surround, self.zoom);
            # tmp, lrx= tilenames.lonEdges(tx + self.surround + 1, self.zoom);
            # self.bounds = ulx, uly, lrx, lry
            # print self.bounds
        return img
Пример #11
0
    # POIs
    if(1):
      for poi in self.osm.poi:
        n = poi['id']
        (lat,lon) = self.osm.nodes[n]
        (x,y) = self.proj.project(lat,lon)
        s = 1
        ctx = self.getCtx(100000000000)
	ctx.set_source_rgb(0., 0., 1.)
        ctx.rectangle(x-s,y-s,x+s,y+s)



#-----------------------------------------------------------------
# Test suite - call this file from the command-line to generate a
# sample image
if(__name__ == '__main__'):
  from tilenames import tileXY
  a = RenderClass()
  filename = "sample_"+__file__+".png"
  #a.RenderTile(15, 16372, 10895, 'default', filename) # london
  #a.RenderTile(14, 8166, 5447, 'default', filename) # Z14
  (x,y) = tileXY(58.409, 15.572, 9)
  a.RenderTile(9, x, y, 'default', filename) # i linkan
  #a.RenderTile(17, 65385, 43659, 'default', filename) # fran render_PIL

  
  print "------------------------------------"
  print "(x,y):",x,y
  print "Saved image to " + filename
Пример #12
0
    def draw(self):
        (x3, y3, w, h) = self.get_allocation()
        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  
            
            
        # Find x, y of tile in focus
        focus = self.focus
        x, y = tilenames.tileXY(focus[0], focus[1], self.zoom_level)

        # Cover screen with tiles by adding "safety margin" to all sides
        num_h = w/256+3
        off_x = num_h/2
        num_v = h/256+3
        off_y = num_v/2
        xtiles = range(x-off_x, x-off_x+num_h)
        ytiles = range(y-off_y, y-off_y+num_v)

        # Draw visible tiles
        for tx in xtiles:
            for ty in ytiles:
                draw_tile_box(tx,ty)

        # unload tiles not visible on screen from memory
        for key in self.tiles.keys():
            if not (key[1] in xtiles and key[2] in ytiles):
                del self.tiles[key]
Пример #13
0
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
Пример #14
0
# by teh jonerer and the elofferer.
# just grabs some images (like... linkoping) to populate the cache.

from tiledata import GetOsmTileData
from tilenames import tileXY

bbox = (58.258000000000003, 15.282, 58.539000000000001, 15.976000000000001)

z = 15
scalr = 1000.0
for lat in range(bbox[0]*scalr, bbox[2]*scalr):
  lat /= scalr
  for long in range(bbox[1]*scalr, bbox[3]*scalr):
    long /= scalr
    (x, y) = tileXY(lat, long, z)
    GetOsmTileData(z, x, y)
Пример #15
0
    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


if __name__ == "__main__":
    bbox = (58.258000000000003, 15.282, 58.539000000000001, 15.976000000000001)

    zoom_level = 10
    scalr = 100.0
    for lat in range(bbox[0] * scalr, bbox[2] * scalr):
        lat /= scalr
        for long in range(bbox[1] * scalr, bbox[3] * scalr):
            long /= scalr
            (x, y) = tileXY(lat, long, zoom_level)
            GetOsmTileData(zoom_level, x, y)
Пример #16
0
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

    # Get base layer tiles
    base_pattern = 'http://{s}.tile.openstreetmap.org/{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))
    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.cvtColor(cv2.imread(img), cv2.COLOR_RGB2RGBA)
            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.cvtColor(cv2.imread(img, -1), cv2.COLOR_RGB2RGBA)
                array.append(i)
            arrays.append(np.vstack(array))
        outp = np.hstack(arrays)
        cv2.imwrite(overlay_outp_name, outp)
        base = cv2.imread(outp_name, -1)
        overlay = cv2.imread(overlay_outp_name, -1)
        for c in range(0, 3):
            zero = overlay.shape[0]
            one = overlay.shape[1]
            base[0:0+zero, 0:0+one, c] = overlay[:,:,c] * \
                (overlay[:,:,3]/255.0) + base[0:0+zero, 0:0+one, c] * \
                (1.0 - overlay[:,:,3]/255.0)
        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 #
    ###########################################################################

    # 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)
    #     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()
    print pdf_name
    return pdf_name
Пример #17
0
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
Пример #18
0
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
Пример #19
0
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
Пример #20
0
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