Important
La traduction est le fruit d’un effort communautaire auquel vous pouvez vous joindre. Cette page est actuellement traduite à 100.00%.
10. Rendu cartographique et Impression
Indication
Les extraits de code sur cette page nécessitent les importations suivantes :
1import os
2
3from qgis.core import (
4 QgsGeometry,
5 QgsMapSettings,
6 QgsPrintLayout,
7 QgsMapSettings,
8 QgsMapRendererParallelJob,
9 QgsLayoutItemLabel,
10 QgsLayoutItemLegend,
11 QgsLayoutItemMap,
12 QgsLayoutItemPolygon,
13 QgsLayoutItemScaleBar,
14 QgsLayoutExporter,
15 QgsLayoutItem,
16 QgsLayoutPoint,
17 QgsLayoutSize,
18 QgsUnitTypes,
19 QgsProject,
20 QgsFillSymbol,
21 QgsAbstractValidityCheck,
22 check,
23)
24
25from qgis.PyQt.QtGui import (
26 QPolygonF,
27 QColor,
28)
29
30from qgis.PyQt.QtCore import (
31 QPointF,
32 QRectF,
33 QSize,
34)
Il y a généralement deux approches lorsque les données d’entrée doivent être rendues sous forme de carte : soit le faire rapidement en utilisant QgsMapRendererJob, soit produire une sortie plus fine en composant la carte avec la classe QgsLayout
.
10.1. Rendu simple
Le rendu est effectué en créant un objet QgsMapSettings
pour définir les paramètres de rendu, puis en construisant un objet QgsMapRendererJob
avec ces paramètres. Ce dernier est ensuite utilisé pour créer l’image résultante.
Voici un exemple :
1image_location = os.path.join(QgsProject.instance().homePath(), "render.png")
2
3vlayer = iface.activeLayer()
4settings = QgsMapSettings()
5settings.setLayers([vlayer])
6settings.setBackgroundColor(QColor(255, 255, 255))
7settings.setOutputSize(QSize(800, 600))
8settings.setExtent(vlayer.extent())
9
10render = QgsMapRendererParallelJob(settings)
11
12def finished():
13 img = render.renderedImage()
14 # save the image; e.g. img.save("/Users/myuser/render.png","png")
15 img.save(image_location, "png")
16
17render.finished.connect(finished)
18
19# Start the rendering
20render.start()
21
22# The following loop is not normally required, we
23# are using it here because this is a standalone example.
24from qgis.PyQt.QtCore import QEventLoop
25loop = QEventLoop()
26render.finished.connect(loop.quit)
27loop.exec_()
10.2. Rendu des couches ayant différents SCR
Si vous avez plus d’une couche et qu’elles ont un CRS différent, l’exemple simple ci-dessus ne fonctionnera probablement pas : pour obtenir les bonnes valeurs à partir des calculs d’étendue, vous devez définir explicitement le CRS de destination
layers = [iface.activeLayer()]
settings = QgsMapSettings()
settings.setLayers(layers)
settings.setDestinationCrs(layers[0].crs())
10.3. Sortie en utilisant la mise en page
La mise en page est un outil très pratique si vous souhaitez obtenir un résultat plus sophistiqué que le simple rendu présenté ci-dessus. Il est possible de créer des mises en page complexes composées de cartes, d’étiquettes, de légendes, de tableaux et d’autres éléments qui sont généralement présents sur les cartes papier. Les mises en page peuvent ensuite être exportées au format PDF, SVG, en images raster ou directement imprimées sur une imprimante.
La mise en page consiste en un ensemble de classes. Elles appartiennent toutes à la bibliothèque centrale. L’application QGIS dispose d’une interface graphique pratique pour le placement des éléments, bien qu’elle ne soit pas disponible dans la bibliothèque GUI. Si vous n’êtes pas familiés avec le Qt Graphics View framework, alors vous êtes encouragé à consulter la documentation dès maintenant, car la mise en page est basée sur celui-ci.
La classe centrale de la mise en page est la classe QgsLayout
, qui est dérivée de la classe Qt QGraphicsScene. Créons une instance de celle-ci :
project = QgsProject.instance()
layout = QgsPrintLayout(project)
layout.initializeDefaults()
Cette méthode initialise la mise en page avec certains paramètres par défaut, spécifiquement en ajoutant une page A4 vide à la mise en page. Vous pouvez créer des mises en page sans appeler la méthode initializeDefaults()
, mais vous devrez vous charger vous-même d’ajouter des pages à la mise en page.
Le code précédent crée une mise en page « temporaire » qui n’est pas visible dans l’interface graphique. Cela peut être pratique pour, par exemple, ajouter rapidement quelques éléments et exporter sans modifier le projet lui-même ni exposer ces changements à l’utilisateur. Si vous voulez que la mise en page soit sauvegardée/restaurée avec le projet et disponible dans le gestionnaire de mise en page, alors ajoutez :
layout.setName("MyLayout")
project.layoutManager().addLayout(layout)
Nous pouvons maintenant ajouter divers éléments (carte, étiquette, …) à la mise en page. Tous ces objets sont représentés par des classes qui héritent de la classe de base QgsLayoutItem
.
Voici une description de certains des principaux éléments qui peuvent être ajoutés à une mise en page.
map — Ici nous créons une carte d’une taille personnalisée et rendons le canevas de la carte actuelle
1map = QgsLayoutItemMap(layout) 2# Set map item position and size (by default, it is a 0 width/0 height item placed at 0,0) 3map.attemptMove(QgsLayoutPoint(5,5, QgsUnitTypes.LayoutMillimeters)) 4map.attemptResize(QgsLayoutSize(200,200, QgsUnitTypes.LayoutMillimeters)) 5# Provide an extent to render 6map.zoomToExtent(iface.mapCanvas().extent()) 7layout.addLayoutItem(map)
étiquette — permet d’afficher des étiquettes. Il est possible d’en modifier la police, la couleur, l’alignement et les marges:
label = QgsLayoutItemLabel(layout) label.setText("Hello world") label.adjustSizeToText() layout.addLayoutItem(label)
légende
legend = QgsLayoutItemLegend(layout) legend.setLinkedMap(map) # map is an instance of QgsLayoutItemMap layout.addLayoutItem(legend)
Échelle graphique
1item = QgsLayoutItemScaleBar(layout) 2item.setStyle('Numeric') # optionally modify the style 3item.setLinkedMap(map) # map is an instance of QgsLayoutItemMap 4item.applyDefaultSize() 5layout.addLayoutItem(item)
Forme basée sur les nœuds
1polygon = QPolygonF() 2polygon.append(QPointF(0.0, 0.0)) 3polygon.append(QPointF(100.0, 0.0)) 4polygon.append(QPointF(200.0, 100.0)) 5polygon.append(QPointF(100.0, 200.0)) 6 7polygonItem = QgsLayoutItemPolygon(polygon, layout) 8layout.addLayoutItem(polygonItem) 9 10props = {} 11props["color"] = "green" 12props["style"] = "solid" 13props["style_border"] = "solid" 14props["color_border"] = "black" 15props["width_border"] = "10.0" 16props["joinstyle"] = "miter" 17 18symbol = QgsFillSymbol.createSimple(props) 19polygonItem.setSymbol(symbol)
Une fois qu’un élément est ajouté à la mise en page, il peut être déplacé et redimensionné :
item.attemptMove(QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters))
item.attemptResize(QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters))
Par défaut, un cadre est dessiné autour de chaque élément. Vous pouvez le supprimer comme suit
# for a composer label
label.setFrameEnabled(False)
Outre la création manuelle des éléments de mise en page, QGIS prend en charge les modèles de mise en page qui sont essentiellement des compositions dont tous les éléments sont enregistrés dans un fichier .qpt (avec une syntaxe XML).
Une fois que la composition est prête (les éléments de mise en page ont été créés et ajoutés à la composition), nous pouvons procéder à la production d’une sortie raster et/ou vecteur.
10.3.1. Validation d’une mise en page
Une mise en page comprend un certain nombre d’éléments interconnectés et il peut arriver que certaines de ces connexions soient endommagées au fil des modifications (par exemple, une légende connectée à une carte qui a été supprimée, une image sans fichier source associé, …) ou vous pourriez vouloir appliquer des contraintes particulières à des éléments de la mise en page. La classe QgsAbstractValidityCheck
pourrait bien vous être utile.
Une vérification basique consiste en :
@check.register(type=QgsAbstractValidityCheck.TypeLayoutCheck)
def my_layout_check(context, feedback):
results = ...
return results
Voici une méthode qui affiche un avertissement chaque fois qu’un élément carte de la mise en page est défini dans le système de projection web mercator :
1@check.register(type=QgsAbstractValidityCheck.TypeLayoutCheck)
2def layout_map_crs_choice_check(context, feedback):
3 layout = context.layout
4 results = []
5 for i in layout.items():
6 if isinstance(i, QgsLayoutItemMap) and i.crs().authid() == 'EPSG:3857':
7 res = QgsValidityCheckResult()
8 res.type = QgsValidityCheckResult.Warning
9 res.title = 'Map projection is misleading'
10 res.detailedDescription = 'The projection for the map item {} is set to <i>Web Mercator (EPSG:3857)</i> which misrepresents areas and shapes. Consider using an appropriate local projection instead.'.format(i.displayName())
11 results.append(res)
12
13 return results
Et voici un autre exemple, plus complexe, qui affiche un avertissement si un élément carte de la mise en page affiche une étendue spatiale qui n’est pas incluse dans l’emprise de validité du SCR qui lui est appliqué.
1@check.register(type=QgsAbstractValidityCheck.TypeLayoutCheck)
2def layout_map_crs_area_check(context, feedback):
3 layout = context.layout
4 results = []
5 for i in layout.items():
6 if isinstance(i, QgsLayoutItemMap):
7 bounds = i.crs().bounds()
8 ct = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:4326'), i.crs(), QgsProject.instance())
9 bounds_crs = ct.transformBoundingBox(bounds)
10
11 if not bounds_crs.contains(i.extent()):
12 res = QgsValidityCheckResult()
13 res.type = QgsValidityCheckResult.Warning
14 res.title = 'Map projection is incorrect'
15 res.detailedDescription = 'The projection for the map item {} is set to \'{}\', which is not valid for the area displayed within the map.'.format(i.displayName(), i.crs().authid())
16 results.append(res)
17
18 return results
10.3.2. Exporter la mise en page
Pour exporter une mise en page, la classe QgsLayoutExporter
doit être utilisée.
1base_path = os.path.join(QgsProject.instance().homePath())
2pdf_path = os.path.join(base_path, "output.pdf")
3
4exporter = QgsLayoutExporter(layout)
5exporter.exportToPdf(pdf_path, QgsLayoutExporter.PdfExportSettings())
Utilisez les méthodes exportToSvg()
ou exportToImage()
au cas où vous voudriez exporter respectivement vers un fichier SVG ou une image au lieu d’un fichier PDF.
10.3.3. Exporter un atlas
Si vous souhaitez exporter toutes les pages d’une mise en page pour laquelle l’option atlas est configurée et activée, vous devez utiliser la méthode atlas()
dans l’exportateur (QgsLayoutExporter
) avec de petits ajustements. Dans l’exemple suivant, les pages sont exportées en image PNG :
exporter.exportToImage(layout.atlas(), base_path, 'png', QgsLayoutExporter.ImageExportSettings())
Notez que les sorties seront enregistrées dans le dossier du chemin de base, en utilisant l’expression du nom de fichier de sortie configurée sur l’atlas.