Kaart renderen en afdrukken

Er zijn over het algemeen twee benaderingen wanneer ingevoerde gegevens zouden moeten worden gerenderd als een kaart: ofwel doe het op de snelle manier met behulp van QgsMapRenderer of produceer een meer fijn afgestemde uitvoer door de kaart samen te stellen met behulp van de klasse QgsComposition en diens vrienden.

Eenvoudig renderen

Render enkele lagen met behulp van QgsMapRenderer — maak een doel-kleurapparaat (QImage, QPainter etc.), stel de set van kaartlagen in, bereik, grootte van de uitvoer en voer het renderen uit

# create image
img = QImage(QSize(800, 600), QImage.Format_ARGB32_Premultiplied)

# set image's background color
color = QColor(255, 255, 255)
img.fill(color.rgb())

# create painter
p = QPainter()
p.begin(img)
p.setRenderHint(QPainter.Antialiasing)

render = QgsMapRenderer()

# set layer set
lst = [layer.getLayerID()]  # add ID of every layer
render.setLayerSet(lst)

# set extent
rect = QgsRect(render.fullExtent())
rect.scale(1.1)
render.setExtent(rect)

# set output size
render.setOutputSize(img.size(), img.logicalDpiX())

# do the rendering
render.render(p)

p.end()

# save image
img.save("render.png","png")

Lagen met een verschillend CRS renderen

Als u meer dan één laag hebt en zij hebben een verschillend CRS, zal het eenvoudige voorbeeld hierboven niet werken: om de juiste waarden uit de berekeningen van het bereik te krijgen dient u expliciet het doel-CRS in te stellen en opnieuw projecteren van gelijktijdige transformatie in te schakelen zoals in het voorbeeld hieronder (alleen het gedeelte van de configuratie van de renderer wordt vermeld)

...
# set layer set
layers = QgsMapLayerRegistry.instance().mapLayers()
lst = layers.keys()
render.setLayerSet(lst)

# Set destination CRS to match the CRS of the first layer
render.setDestinationCrs(layers.values()[0].crs())
# Enable OTF reprojection
render.setProjectionsEnabled(True)
...

Uitvoer met behulp van Printvormgeving

Printvormgeving is een zeer handig gereedschap als u een uitgebreidere uitvoer wilt dan de eenvoudige rendering van die welke hierboven is weergegeven. Met behulp van printvormgeving is het mogelijk complexe lay-outs voor kaarten te maken, bestaande uit weergaven van kaarten, labels, legenda, tabellen en andere elementen die gewoonlijk aanwezig zij op papieren kaarten. De lay-outs kunnen dan worden geëxporteerd naar PDF, rasterafbeeldingen of direct worden afgedrukt op een printer.

De Printvormgeving bestaat uit een aantal klassen. Zij behoren allemaal tot de bron-bibliotheek. De toepassing QGIS heeft een handige GUI voor het plaatsen van de elementen, hoewel die niet beschikbaar is in de bibliotheek van de GUI. Als u niet bekend bent met het framework Qt Graphics View, dan wordt u aangeraden nu de documentatie te raadplegen, omdat Printvormgeving daarop is gebaseerd.

De centrale klasse van de printvormgeving is QgsComposition die is afgeleid van QGraphicsScene. Laten we er een maken

mapRenderer = iface.mapCanvas().mapRenderer()
c = QgsComposition(mapRenderer)
c.setPlotStyle(QgsComposition.Print)

Onthoud dat de Printvormgeving een instance heeft van QgsMapRenderer. In de code gaan we er van uit dat het binnen de toepassing QGIS wordt uitgevoerd en dus de renderer voor de kaart gebruiken van het kaartvenster. De compositie gebruikt verscheidene parameters van de renderer van de kaart, meest belangrijke daarvan zijn de standaard set kaartlagen en het huidige bereik. Bij het gebruiken van printvormgeving in een zelfstandige toepassing kunt u uw eigen instance van de renderer voor de kaart maken op dezelfde manier zoals die welke in het gedeelte hierboven wordt weergegeven en die doorgeven aan de compositie.

Het is mogelijk om verscheidene elementen (map, label, ...) toe te voegen aan de compositie — deze elementen moeten afstammen van de klasse QgsComposerItem. De huidige ondersteunde items zijn:

  • kaart — dit item vertelt de bibliotheken waar de kaart zelf moet worden geplaatst. Hier maken we ene kaart en spreiden die over de gehele grootte van het papier

    x, y = 0, 0
    w, h = c.paperWidth(), c.paperHeight()
    composerMap = QgsComposerMap(c, x ,y, w, h)
    c.addItem(composerMap)
    
  • label — maakt het weergeven van labels mogelijk. Het is mogelijk het lettertype, de kleur, de uitlijning en marge aan te passen

    composerLabel = QgsComposerLabel(c)
    composerLabel.setText("Hello world")
    composerLabel.adjustSizeToText()
    c.addItem(composerLabel)
    
  • legenda

    legend = QgsComposerLegend(c)
    legend.model().setLayerSet(mapRenderer.layerSet())
    c.addItem(legend)
    
  • schaalbalk

    item = QgsComposerScaleBar(c)
    item.setStyle('Numeric') # optionally modify the style
    item.setComposerMap(composerMap)
    item.applyDefaultSize()
    c.addItem(item)
    
  • pijl

  • afbeelding

  • vorm

  • tabel

Standaard hebben de nieuw gemaakte items voor Printvormgeving de positie nul (linkerbovenhoek van de pagina) en de grootte nul. De positie en grootte worden altijd in millimeters gemeten

# set label 1cm from the top and 2cm from the left of the page
composerLabel.setItemPosition(20, 10)
# set both label's position and size (width 10cm, height 3cm)
composerLabel.setItemPosition(20, 10, 100, 30)

Een kader wordt standaard rondom elk item getekend. Hoe dat kader te verwijderen

composerLabel.setFrame(False)

Naast het handmatig maken van items voor Printvormgeving, heeft QGIS ondersteuning voor sjablonen van Printvormgeving wat in essentie composities zijn met al hun items, opgeslagen als een bestand .qpt (met syntaxis XML). Helaas is deze functionaliteit nog niet beschikbaar in de API.

Als de compositie eenmaal gereed is (de items van Printvormgeving zijn gemaakt en toegevoegd aan de compositie), kunnen we doorgaan en een raster- en/of vector-uitvoer produceren.

De standaard instellingen voor uitvoer van de compositie zijn paginagrootte A4 en resolutie 300 DPI. U kunt ze wijzigen, indien nodig. De grootte van het papier wordt gespecificeerd in millimeters

c.setPaperSize(width, height)
c.setPrintResolution(dpi)

Naar een rasterafbeelding uitvoeren

Het volgende fragment code geeft weer hoe een compositie te renderen naar een rasterafbeelding

dpi = c.printResolution()
dpmm = dpi / 25.4
width = int(dpmm * c.paperWidth())
height = int(dpmm * c.paperHeight())

# create output image and initialize it
image = QImage(QSize(width, height), QImage.Format_ARGB32)
image.setDotsPerMeterX(dpmm * 1000)
image.setDotsPerMeterY(dpmm * 1000)
image.fill(0)

# render the composition
imagePainter = QPainter(image)
sourceArea = QRectF(0, 0, c.paperWidth(), c.paperHeight())
targetArea = QRectF(0, 0, width, height)
c.render(imagePainter, targetArea, sourceArea)
imagePainter.end()

image.save("out.png", "png")

Naar PDF uitvoeren

Het volgende fragment code rendert een compositie naar een PDF-bestand

printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName("out.pdf")
printer.setPaperSize(QSizeF(c.paperWidth(), c.paperHeight()), QPrinter.Millimeter)
printer.setFullPage(True)
printer.setColorMode(QPrinter.Color)
printer.setResolution(c.printResolution())

pdfPainter = QPainter(printer)
paperRectMM = printer.pageRect(QPrinter.Millimeter)
paperRectPixel = printer.pageRect(QPrinter.DevicePixel)
c.render(pdfPainter, paperRectPixel, paperRectMM)
pdfPainter.end()