Creating tiles from a QGIS map

This recipe creates a set of Internet web map tiles from your QGIS map. What's interesting about this recipe is that once the static map tiles are generated, you can serve them up locally or from any web-accessible directory using the client-side browser's JavaScript without the need of a map server, or you can serve them (for example, distribute them on a portable USB drive).

Getting ready

You will need to download the zipped shapefile from https://geospatialpython.googlecode.com/svn/countries.zip.

Unzip the shapefile to a directory named shapes in your qgis_data directory. Next, create a directory called tilecache in your qgis_data directory. You will also need to install the QTiles plugin using the QGIS Plugin Manager. This plugin is experimental, so make sure that the Show also experimental plugins checkbox is checked in the QGIS Plugin Manager's Settings tab.

How to do it...

We will load the shapefile and randomly color each country. We'll then manipulate the QTiles plugin using Python to generate map tiles for 5 zoom levels' worth of tiles. To do this, we need to perform the following steps:

  1. First, we need to import all the necessary Python libraries, including the QTiles plugin:
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    import qtiles
    import random
    
  2. Now, we create a color function that can produce random colors. This function accepts a mixed color, which defaults to white, to change the overall tone of the color palette:
    def randomColor(mix=(255,255,255)):
      red = random.randrange(0,256)
      green = random.randrange(0,256)
      blue = random.randrange(0,256)
      r,g,b = mix
      red = (red + r) / 2
      green = (green + g) / 2
      blue = (blue + b) / 2
      return (red, green, blue)
    
  3. Next, we'll create a simple callback function for notification of when the tile generation is done. This function will normally be used to create a message bar or other notification, but we'll keep things simple here:
    def done():
      print "FINISHED!!"
    
  4. Now, we set the path to the shapefile and the tile's output direction:
    shp = "/qgis_data/shapes/countries.shp"
    dir = "/qgis_data/tilecache"
    
  5. Then, we load the shapefile:
    layer = QgsVectorLayer(shp, "Countries", "ogr")
    
  6. After that, we define the field that is used to color the countries:
    field = 'CNTRY_NAME'
    
  7. Now, we need to get all the features so that we can loop through them:
    features = layer.getFeatures()
    
  8. We'll build our color renderer:
    categories = []
    for feature in features:
        country = feature[field]
        sym = QgsSymbolV2.defaultSymbol(layer.geometryType())
        r,g,b = randomColor()
        sym.setColor(QColor(r,g,b,255))
        category = QgsRendererCategoryV2(country, sym, country)
        categories.append(category)    
    
  9. Then, we'll set the layer renderer and add it to the map:
    renderer = QgsCategorizedSymbolRendererV2(field, categories)
    layer.setRendererV2(renderer)
    QgsMapLayerRegistry.instance().addMapLayer(layer)
    
  10. Now, we'll set all the properties we need for the image tiles, including the map elements and image properties:
    canvas = iface.mapCanvas()
    layers = canvas.mapSettings().layers()
    extent = canvas.extent()
    minZoom = 0
    maxZoom = 5
    width = 256
    height = 256
    transp = 255
    quality = 70
    format = "PNG"
    outputPath = QFileInfo(dir)
    rootDir = "countries"
    antialiasing = False
    tmsConvention = True
    mapUrl = False
    viewer = True
    
  11. We are ready to generate the tiles using the efficient threading system of the QTiles plugin. We'll create a thread object and pass it all of the tile settings previously mentioned:
    tt = qtiles.tilingthread.TilingThread(layers, extent, minZoom, maxZoom, width, height, transp,
    quality, format, outputPath, rootDir, antialiasing, tmsConvention,
    mapUrl, viewer)
    
  12. Then, we can connect the finish signal to our simple callback function:
    tt.processFinished.connect(done)
    
  13. Finally, we start the tiling process:
    tt.start()
    
  14. Once you receive the completion message, check the output directory and verify that there is an HTML file named countries.html and a directory named countries.
  15. Double-click on the countries.html page to open it in a browser.
  16. Once the map loads, click on the plus symbol (+) in the upper-left corner twice to zoom the map.
  17. Next, pan around to see the tiled version of your map load.

How it works...

You can generate up to 16 zoom levels with this plugin. After eight zoom levels, the tile generation process takes a long time and the tile set becomes quite large on the filesystem, totaling hundreds of megabytes. One way to avoid creating a lot of files is to use the mbtiles format, which stores all the data in a single file. However, you need a web application using GDAL to access it.

Note

You can see a working example of the output recipe stored in a github.io web directory at http://geospatialpython.github.io/qgis/tiles/countries.html.

The following image shows the output in a browser:

How it works...
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset