Creating a mapbook

A mapbook is an automatically-generated document, which can also be called an atlas. A mapbook takes a dataset and breaks it down into smaller, detailed maps based on a coverage layer that zooms the larger map to each feature in the coverage in order to make a page of the mapbook. The coverage layer may or may not be the same as the map layer featured on each page of the mapbook. In this recipe, we'll create a mapbook that features all the countries in the world.

Getting ready

For this recipe, you need to download the world countries dataset from https://geospatialpython.googlecode.com/svn/countries.zip and put it in a directory named shapes within your qgis_data directory.

Next, you'll need to install the PyPDF2 library. On Linux or OS X, just open a console and run the following command:

sudo easy_install PyPDF2

On Windows, open the OSGEO4W console from your start menu and run this:

easy_install PyPDF2

Finally, in your qgis_data directory, create a folder called atlas to store the mapbook's output.

How to do it...

We will build a QGIS composition and set it to atlas mode. Then, we'll add a composer map, where each country will be featured, and an overview map. Next, we'll run the atlas process to produce each page of the mapbook as separate PDF files. Finally, we'll combine the individual PDFs into a single PDF file. To do this, we need to perform the following steps:

  1. First, import all the libraries that are needed:
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    from qgis.core import *
    import PyPDF2
    import os
    
  2. Next, create variables related to the output files, including the mapbook's name, the coverage layer, and the naming pattern for the individual PDF files:
    filenames = []
    mapbook = "/Users/joellawhead/qgis_data/atlas/mapbook.pdf"
    coverage = "/Users/joellawhead/qgis_data/shapes/countries.shp"
    atlasPattern = "/Users/joellawhead/qgis_data/atlas/output_"
    
  3. Now, add the coverage layer to the map using the following code:
    vlyr = QgsVectorLayer(coverage, "Countries", "ogr")
    QgsMapLayerRegistry.instance().addMapLayer(vlyr)
    
  4. Next, establish the map renderer:
    mr = QgsMapRenderer()
    mr.setLayerSet([vlyr.id()])
    mr.setProjectionsEnabled(True)
    mr.setMapUnits(QGis.DecimalDegrees)
    crs = QgsCoordinateReferenceSystem()
    crs.createFromSrid(4326)
    mr.setDestinationCrs(crs)
    
  5. Then, set up the composition:
    c = QgsComposition(mr)
    c.setPaperSize(297, 210)
    
  6. Create a symbol for the coverage layer:
    gray = {"color": "155,155,155"}
    mapSym = QgsFillSymbolV2.createSimple(gray)
    renderer = QgsSingleSymbolRendererV2(mapSym)
    vlyr.setRendererV2(renderer)
    
  7. Now, add the first composer map to the composition, as shown here:
    atlasMap = QgsComposerMap(c, 20, 20, 130, 130)
    atlasMap.setFrameEnabled(True)
    c.addComposerMap(atlasMap)
    
  8. Then, create the atlas framework:
    atlas = c.atlasComposition()
    atlas.setCoverageLayer(vlyr)
    atlas.setHideCoverage(False)
    atlas.setEnabled(True)
    c.setAtlasMode(QgsComposition.ExportAtlas)
    
  9. Next, establish the overview map:
    ov = QgsComposerMap(c, 180, 20, 50, 50)
    ov.setFrameEnabled(True)
    ov.setOverviewFrameMap(atlasMap.id())
    c.addComposerMap(ov)
    rect = QgsRectangle(vlyr.extent())
    ov.setNewExtent(rect)
    
  10. Then, create the overview map symbol:
    yellow = {"color": "255,255,0,255"}
    ovSym = QgsFillSymbolV2.createSimple(yellow)
    ov.setOverviewFrameMapSymbol(ovSym)
    
  11. Next, you need to label each page with the name of the country, which is stored in the CNTRY_NAME field of the shapefile:
    lbl = QgsComposerLabel(c)
    c.addComposerLabel(lbl)
    lbl.setText('[% "CNTRY_NAME" %]')
    lbl.setFont(QgsFontUtils.getStandardTestFont())
    lbl.adjustSizeToText()
    lbl.setSceneRect(QRectF(150, 5, 60, 15))
    
  12. Now, we'll tell the atlas to use automatic scaling for each country in order to best fit each map in the window:
    atlasMap.setAtlasDriven(True)
    atlasMap.setAtlasScalingMode(QgsComposerMap.Auto)
    atlasMap.setAtlasMargin(0.10)
    
  13. Now we tell the atlas to loop through all the features and create PDF maps, as follows:
    atlas.setFilenamePattern("'%s' || $feature" % atlasPattern)
    atlas.beginRender()
    for i in range(0, atlas.numFeatures()):
        atlas.prepareForFeature(i)
        filename = atlas.currentFilename() + ".pdf"
        print "Writing file %s" % filename
        filenames.append(filename)
        c.exportAsPDF(filename)
    atlas.endRender()
    
  14. Finally, we will use the PyPDF2 library to combine the individual PDF files into a single PDF file, as shown here:
    output = PyPDF2.PdfFileWriter()
    for f in filenames:
        pdf = open(f, "rb")
        page = PyPDF2.PdfFileReader(pdf)
        output.addPage(page.getPage(0))
        os.remove(f)
    print "Writing final mapbook..."
    book = open(mapbook, "wb")
    output.write(book)
    with open(mapbook, 'wb') as book:
        output.write(book)
    

How it works...

You can customize the template that creates the individual pages as much as you want. The GUI atlas tool can export the atlas to a single file, but this functionality is not available in PyQIS, so we use the pure Python PyPDF2 library. You can also create a template in the GUI, save it, and load it with Python, but it is often easier to make changes if you have the layout available in the code. You should also know that the PDF pages are just images. The maps are exported as rasters, so the mapbook will not be searchable and the file size can be large.

..................Content has been hidden....................

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