Renderização em impressão de mapas

Em geral, há duas abordagens quando os dados de entrada deve ser processado como um mapa: quer fazê-lo maneira rápida usando: class: QgsMapRenderer ou produzir saída mais afinadas, compondo o mapa na classe de amigos: class:` classe QgsComposition`.

Renderização simples

Renderizar algumas camadas usando: class: QgsMapRenderer — cria um dispositivo de pintura de destino (` QImage`,` QPainter` etc.), configurar conjunto de camadas, extensão, tamanho de saída e fazer a renderização

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

Renderizando camadas com CRS diferente

Se você tiver mais de uma camada e eles têm CRS diferente, o simples exemplo acima provavelmente não vai funcionar: para obter os valores corretos dos cálculos de extensão, você tem que definir explicitamente a CRS de destino e permitem reprojeção OTF como no exemplo abaixo (apenas a parte de configuração do renderizador é relatada)

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

Saída usando Compositor de Mapa

Compositor de Mapa é uma ferramenta muito útil se você gostaria de fazer uma produção mais sofisticada do que a prestação simples mostrado acima. Usando o compositor é possível criar layouts mapa complexas consistindo de visualizações de mapas, etiquetas, legenda, tabelas e outros elementos que estão normalmente presentes em mapas de papel. Os layouts podem ser depois exportados para PDF, imagens raster ou diretamente impresso em uma impressora.

O compositor é composto por um grupo de classes. Todos eles pertencem à biblioteca principal. A aplicação QGIS tem uma interface conveniente para a colocação dos elementos, no entanto, não está disponível na biblioteca gráfica. Se você não estiver familiarizado com o Qt Graphics View framework, então, incentivamos você a verificar a documentação agora, porque o compositor é baseado nele .

A classe central de composição é: class: QgsComposition que é derivada de: class:` QGraphicsScene`. Vamos criar um

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

Note-se que a composição leva uma instância de: class: QgsMapRenderer. No código esperamos que estamos executando dentro aplicativo QGIS e, assim, usar o renderizador mapa do mapa de lona. A composição utiliza vários parâmetros do renderizador mapa, o mais importante o conjunto padrão de camadas de mapas e da extensão atual. Ao utilizar compositor em um aplicativo independente, você pode criar sua própria instância mapa processador da mesma forma como mostrado na seção acima e passá-lo para a composição.

É possível adicionar vários elementos (mapa, etiqueta, ...) para a composição — estes elementos têm de ser descendentes de: class: classe QgsComposerItem. Itens atualmente suportados são:

  • map — este item diz as bibliotecas onde colocar o próprio mapa. Aqui criamos um mapa e esticamos sobre o tamanho do papel inteiro

    x, y = 0, 0
    w, h = c.paperWidth(), c.paperHeight()
    composerMap = QgsComposerMap(c, x ,y, w, h)
    c.addItem(composerMap)
    
  • label — permite exibir rótulos. É possível modificar a sua fonte, cor, alinhamento e margem

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

    legend = QgsComposerLegend(c)
    legend.model().setLayerSet(mapRenderer.layerSet())
    c.addItem(legend)
    
  • barra de escala

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

  • Imagem

  • Formato

  • Tabela

Por padrão, os itens de composição recém-criados têm posição zero (canto superior esquerdo da página) e tamanho zero. A posição e tamanho são sempre medido em milímetros

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

Um quadro é desenhado em torno de cada item por padrão. Como remover o quadro

composerLabel.setFrame(False)

Além de criar os itens compositor à mão, QGIS tem suporte para modelos compositor que são essencialmente composições com todos os seus itens salvos em um arquivo .qpt (com a sintaxe XML). Infelizmente essa funcionalidade ainda não está disponível na API.

Uma vez que a composição está pronta (os itens do compositor tenham sido criados e adicionados à composição), podemos prosseguir para produzir um raster e / ou um vetor de saída.

As definições de saída padrão para a composição são página de tamanho A4 e resolução de 300 DPI. Você pode alterá-los, se necessário. O tamanho do papel é especificada em milímetros

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

Exportando para um arquivo de imagem

O seguinte fragmento de código mostra como renderizar a composição para uma imagem 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")

Exportando em PDF

O seguinte fragmento de código renderiza a composição para um arquivo 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()