Rendu cartographique et Impression

Il existe deux approches pour effectuer un rendu de données en entrée dans une carte: soit on utilise une méthode rapide avec la classe QgsMapRenderer, soit on produit une sortie plus élaborée en utilisant la classe QgsComposition et ses dérivés.

Rendu simple

Rendu de quelques couches en utilisant QgsMapRenderer: créer le périphérique d’affichage (QImage, QPainter etc.), paramétrer un jeu de couches, l’étendue, la taille de la sortie et faire le rendu:

# 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")

Rendu des couches ayant différents SCR

S’il y a plusieurs couches et qu’elles ont des SCR différents, l’exemple simple ci-dessus ne fonctionnera probablement pas : pour obtenir les bonnes valeurs des calculs de l’emprise vous devez définir explicitement le SCR de la destination et activer la reprojection à la volée comme montré dans l’exemple ci-dessous (seule la configuration du rendu est décrite)

...
# 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)
...

Sortie utilisant un composeur de carte

Le composeur de carte est un outil très pratique lorsqu’on veut réaliser une sortie plus complexe que le rendu présenté ci-dessus. En utilisant le composeur, il est possible de créer des mises en page de cartes complexes en utilisant des vues de cartes, des étiquettes, des légendes, des tables ainsi que d’autres éléments qui sont généralement présents dans les cartes papier. Les mises en page peuvent ensuite être exportées en PDF, dans des images raster ou directement imprimées.

The composer consists of a bunch of classes. They all belong to the core library. QGIS application has a convenient GUI for placement of the elements, though it is not available in the GUI library. If you are not familiar with Qt Graphics View framework, then you are encouraged to check the documentation now, because the composer is based on it.

La classe principale du composeur est QgsComposition qui est dérivée de la classe QGraphicsScene. Créons-en une:

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

Veuillez noter que la composition prend une instance de QgsMapRenderer en argument. Ce code est utilisable au sein de l’application QGIS et il utilisera le moteur de rendu de la carte depuis le canevas de carte. La composition utilise plusieurs paramètres du moteur de rendu de carte, principalement le jeu par défaut des couches et l’emprise actuelle. Lorsqu’on utilise le composeur dans une application autonome, vous pouvez créer votre instance de moteur de rendu de carte de la même manière que précedemment et la passer à la composition.

Il est possible d’ajouter plusieurs éléments (carte, étiquette, etc.) à la composition. Ces éléments doivent hériter de la classe QgsComposerItem. Les éléments actuellement gérés sont les suivants:

  • carte — cet élément indique aux bibliothèques l’emplacement de la carte. Nous créons ici une carte et l’étirons sur toute la taille de la page

    x, y = 0, 0
    w, h = c.paperWidth(), c.paperHeight()
    composerMap = QgsComposerMap(c, x ,y, w, h)
    c.addItem(composerMap)
    
  • étiquette — permet d’afficher des étiquettes. Il est possible d’en modifier la police, la couleur, l’alignement et les marges:

    composerLabel = QgsComposerLabel(c)
    composerLabel.setText("Hello world")
    composerLabel.adjustSizeToText()
    c.addItem(composerLabel)
    
  • légende

    legend = QgsComposerLegend(c)
    legend.model().setLayerSet(mapRenderer.layerSet())
    c.addItem(legend)
    
  • Échelle graphique

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

  • image

  • couche

  • table

Par défaut, les nouveaux éléments du composeur ont une position nulle (bord supérieur gauche de la page) et une taille à zéro. La position et la taille sont toujours mesurées en millimètres

# 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)

Par défaut, un cadre est dessiné autour de chaque élément. Voici comment le supprimer:

composerLabel.setFrame(False)

En plus de créer les éléments du composeur à la main, QGIS gère des modèles de composition qui sont des compositions dont l’ensemble des objets est enregistré dans un fichier .qpt (syntaxe XML). Malheureusement, cette fonctionnalité n’est pas encore disponible dans l’API.

Une fois la composition prête (les éléments de composeur ont été créés et ajoutés à la composition), nous pouvons en générer une sortie raster et/ou vecteur.

Les paramètres d’impression par défaut sont une taille de page en A4 et une résolution de 300dpi. Vous pouvez les changer si nécessaire. La taille du papier est paramétrée en millimètres

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

Sortie vers une image raster

Le code qui suit montre comment effectuer le rendu d’une composition dans une image raster:

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")

Export en PDF

Le code qui suite effectue un rendu d’une composition dans un fichier PDF:

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()