10. Representación del Mapa e Impresión

Consejo

Los fragmentos de código en esta página necesitan las siguientes importaciones:

 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)
22
23from qgis.PyQt.QtGui import (
24    QPolygonF,
25    QColor,
26)
27
28from qgis.PyQt.QtCore import (
29    QPointF,
30    QRectF,
31    QSize,
32)

Por lo general, hay dos enfoques cuando los datos de entrada deben representarse como un mapa: hacerlo de manera rápida usando QgsMapRendererJob o producir una salida más ajustada componiendo el mapa con la clase QgsLayout.

10.1. Representación Simple

La renderización se realiza creando un objeto QgsMapSettings para definir la configuración de renderizado, y luego construir una clase QgsMapRendererJob con esos ajustes. Este último se utiliza para crear la imagen resultante.

He aquí un ejemplo:

 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. Representando capas con diferente SRC

Si tiene más de una capa y tienen un SRC diferente, el simple ejemplo anterior probablemente no funcionará: para obtener los valores correctos de los cálculos de extensión, debe establecer explícitamente el SRC de destino

layers = [iface.activeLayer()]
settings = QgsMapSettings()
settings.setLayers(layers)
settings.setDestinationCrs(layers[0].crs())

10.3. Salida usando diseño de impresión

El diseño de impresión es una herramienta muy útil si desea realizar una salida más sofisticada que la representación simple que se muestra arriba. Es posible crear diseños de mapas complejos que constan de vistas de mapa, etiquetas, leyendas, tablas y otros elementos que suelen estar presentes en los mapas de papel. Los diseños se pueden exportar a PDF, imágenes rasterizadas o imprimir directamente en una impresora.

El diseño consta de varias clases. Todos pertenecen a la biblioteca principal. La aplicación QGIS tiene una GUI conveniente para la ubicación de los elementos, aunque no está disponible en la biblioteca de la GUI. Si no está familiarizado con Qt Graphics View framework, entonces le recomendamos que consulte la documentación ahora, porque el diseño se basa en ella.

La clase central del diseño es la clase QgsLayout, que deriva de la clase de Qt QGraphicsScene . Creemos una instancia de ello:

project = QgsProject.instance()
layout = QgsPrintLayout(project)
layout.initializeDefaults()

Esto inicializa el diseño con algunas configuraciones predeterminadas, específicamente agregando una página A4 vacía al diseño. Puede crear diseños sin llamar al método initializeDefaults(), pero deberá encargarse de agregar páginas al diseño usted mismo.

El código anterior crea un diseño «temporal» que no es visible en la GUI. Puede ser útil p.Ej. agregue rápidamente algunos elementos y exporte sin modificar el proyecto en sí ni exponer estos cambios al usuario. Si desea que el diseño se guarde/restaure junto con el proyecto y esté disponible en el administrador de diseño, agregue:

layout.setName("MyLayout")
project.layoutManager().addLayout(layout)

Ahora podemos agregar varios elementos (mapa, etiqueta, …) al diseño. Todos estos objetos están representados por clases que heredan de la clase base QgsLayoutItem.

Aquí hay una descripción de algunos de los elementos de diseño principales que se pueden agregar a un diseño.

  • mapa — Aquí creamos un mapa de un tamaño personalizado y renderizamos el lienzo del mapa actual.

    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)
    
  • etiqueta — permite mostrar etiquetas. Es posible modificar su letra, color, alineación y margen.

    label = QgsLayoutItemLabel(layout)
    label.setText("Hello world")
    label.adjustSizeToText()
    layout.addLayoutItem(label)
    
  • leyenda

    legend = QgsLayoutItemLegend(layout)
    legend.setLinkedMap(map) # map is an instance of QgsLayoutItemMap
    layout.addLayoutItem(legend)
    
  • barra de escala

    1item = QgsLayoutItemScaleBar(layout)
    2item.setStyle('Numeric') # optionally modify the style
    3item.setLinkedMap(map) # map is an instance of QgsLayoutItemMap
    4item.applyDefaultSize()
    5layout.addLayoutItem(item)
    
  • flecha

  • imagen

  • forma básica

  • forma basada en nodos

     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)
    
  • tabla

Una vez que un elemento es añadido a la composiciónm puede ser movida y redimensionadas:

item.attemptMove(QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters))
item.attemptResize(QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters))

Un cuadro es dibujado alrededor de cada elemento por defecto. Puede borrarlo como sigue:

# for a composer label
label.setFrameEnabled(False)

Además de crear los elementos de diseño a mano, QGIS tiene soporte para plantillas de diseño que son esencialmente composiciones con todos sus elementos guardados en un archivo .qpt (con sintaxis XML).

Una vez que la composición está lista (los elementos de diseño se han creado y agregado a la composición), podemos proceder a producir una salida rasterizada y/o vectorial.

10.3.1. Exportando la composición

Para exportar una composición, la clase QgsLayoutExporter debe ser usada.

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

Use exportToImage() en caso de que desee exportar a una imagen en lugar de un archivo PDF.

10.3.2. Exportar un atlas de diseño

Si desea exportar todas las páginas de un diseño que tiene la opción de atlas configurada y habilitada, debe usar el método atlas() en el exportador (QgsLayoutExporter) con pequeños ajustes. En el siguiente ejemplo, las páginas se exportan a imágenes PNG:

exporter.exportToImage(layout.atlas(), base_path, 'png', QgsLayoutExporter.ImageExportSettings())

Observe que las salidas se guardarán en la carpeta de ruta base, utilizando la expresión de nombre de archivo de salida configurada en atlas.