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.
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.
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:
from PyQt4.QtCore import * from PyQt4.QtGui import * from qgis.core import * import PyPDF2 import os
filenames = [] mapbook = "/Users/joellawhead/qgis_data/atlas/mapbook.pdf" coverage = "/Users/joellawhead/qgis_data/shapes/countries.shp" atlasPattern = "/Users/joellawhead/qgis_data/atlas/output_"
vlyr = QgsVectorLayer(coverage, "Countries", "ogr") QgsMapLayerRegistry.instance().addMapLayer(vlyr)
mr = QgsMapRenderer() mr.setLayerSet([vlyr.id()]) mr.setProjectionsEnabled(True) mr.setMapUnits(QGis.DecimalDegrees) crs = QgsCoordinateReferenceSystem() crs.createFromSrid(4326) mr.setDestinationCrs(crs)
c = QgsComposition(mr) c.setPaperSize(297, 210)
gray = {"color": "155,155,155"} mapSym = QgsFillSymbolV2.createSimple(gray) renderer = QgsSingleSymbolRendererV2(mapSym) vlyr.setRendererV2(renderer)
atlasMap = QgsComposerMap(c, 20, 20, 130, 130) atlasMap.setFrameEnabled(True) c.addComposerMap(atlasMap)
atlas = c.atlasComposition() atlas.setCoverageLayer(vlyr) atlas.setHideCoverage(False) atlas.setEnabled(True) c.setAtlasMode(QgsComposition.ExportAtlas)
ov = QgsComposerMap(c, 180, 20, 50, 50) ov.setFrameEnabled(True) ov.setOverviewFrameMap(atlasMap.id()) c.addComposerMap(ov) rect = QgsRectangle(vlyr.extent()) ov.setNewExtent(rect)
yellow = {"color": "255,255,0,255"} ovSym = QgsFillSymbolV2.createSimple(yellow) ov.setOverviewFrameMapSymbol(ovSym)
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))
atlasMap.setAtlasDriven(True) atlasMap.setAtlasScalingMode(QgsComposerMap.Auto) atlasMap.setAtlasMargin(0.10)
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()
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)
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.