Como criar seu primeiro plugin para QGIS usando Python e Qt Designer? Parte III

Confira nosso curso online de QGIS

Aprenda a criar seu próprio plugin para QGIS. Nesta terceira parte, ensinamos a exportar seu mapa para PDF e PNG utilizando Python.

E chegamos à última parte do nosso tutorial de criação de plugins para o QGIS utilizando Python e o Qt Designer. Na primeira postagem, ensinamos como criar os arquivos base do plugin e como solicitar ao usuário pontos temporários para serem inseridos no mapa.

Na segunda postagem, vimos como salvar o shapefile do ponto inserido, como avaliar em qual região de um determinado zoneamento o ponto esta localizado e como corrigir erros no Python.

Caso você não tenha lido a primeira e segunda parte, você pode ler elas clicando nos links abaixo.

Nesta terceira parte do tutorial, iremos mostrar como criar um mapa no compositor de impressão, de forma que possamos exportar o ponto inserido e o zoneamento avaliado para outros usuários no formato PDF e PNG.

Preparando o Compositor de Impressão com PyQGIS

Antes de começarmos a inserirmos as funções relacionadas ao compositor de impressão, precisamos importar elas. Você deve inserir nas linhas iniciais do arquivo python (.py) as seguintes linhas:


from PyQt4.QtGui import QAction, QIcon, QFileDialog, QPrinter, QPainter, QImage, QColor # Nesta linha, foram adicionados os itens QPrinter, QPainter, QImage e QColor
from qgis.utils import iface # Adicione esta linha para importar o item iface

Agora que já importamos as funções necessárias, vamos incorporar, passo a passo, os itens do nosso mapa.

As próximas linhas de código serão inseridas no final do nosso arquivo python, logo após a verificação se os checkbox da área de estudo estão selecionados ou não.

Primeiro, iremos criar uma composição do tipo QgsComposition a qual irá receber a informação visual do nosso mapa. Confira o código abaixo.


# Criação de uma composição QgsComposition
mapRenderer = iface.mapCanvas().mapRenderer()
c = QgsComposition(mapRenderer)
c.setPlotStyle(QgsComposition.Print)

O próximo passo é definir onde será impresso nosso mapa em uma folha A4 (o QGIS define como padrão de saída folha A4 com resolução de 300 dpi). Note que após criar as variáveis, elas são inseridas dentro do nosso mapa usando a função addItem().


# Adicionando e definindo onde o mapa será inserido na folha
x, y = 0, 0
w, h = c.paperWidth(), c.paperHeight()
composerMap = QgsComposerMap(c, x, y, w, h)
c.addItem(composerMap)

Agora, vamos criar um item que receberá nossos textos e irá colocar eles em uma determinada parte da impressão.

Veja que dentro da função setText() devemos inserir o texto que será apresentado e na função setItemPosition() recebe a posição do nosso texto.


# Adiciona texto (label) ao mapa gerado
composerLabel = QgsComposerLabel(c)
composerLabel.setText("Blog 2 Engenheiros")
composerLabel.adjustSizeToText()
composerLabel.setItemPosition(100, 0)
c.addItem(composerLabel)

Por fim, vamos adicionar agora a legenda do nosso mapa.


# Adiciona legenda ao mapa
legend = QgsComposerLegend(c)
legend.model().setLayerSet(mapRenderer.layerSet())
legend.setItemPosition(10,10)
c.addItem(legend)

Já temos os elementos do nosso mapa no formato de código Python. Podemos também incluir outros itens, tais como escala (QgsComposerScaleBar) e polígonos baseados em pontos (QgsComposerPolygon), mas deixaremos eles de fora, neste tutorial.

Itens como figuras, flechas e tabelas ainda não suportados, ou seja, não podem ser inseridos por meio de python no QGIS (Documentation QGIS 2.18).

Com os itens inseridos, precisamos agora exportar o resultado para PDF ou para PNG.

Exportando mapa no formato PDF

Para exportar o mapa criado, utilize o código abaixo, lembrando de substituir (na função setOutputFileName) o caminho onde será gerado o arquivo pdf.

Neste exemplo, utilizei o mesmo caminho onde foi salvo o arquivo shapefile.


# Exportando o resultado para PDF
printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName(localSalvo+"_mapa.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()

Veja que podemos modificar várias opções, tais como tamanho do papel (setPaperSize), se a impressão é na folha toda (setFullPage) e resolução (setResolution).

Exportando o mapa no formato PNG

Agora, se você quer ter o mapa no formato png, você deverá utilizar o código abaixo, ao invés do código previamente apresentado.


# Exportando o mapa para PNG
dpi = c.printResolution()
dpmm = dpi / 25.4
width = int(dpmm * c.paperWidth())
height = int(dpmm * c.paperHeight())

# Cria uma imagem de saída e inicializa ela
image = QImage(QSize(width, height), QImage.Format_ARGB32)
image.setDotsPerMeterX(dpmm * 1000)
image.setDotsPerMeterY(dpmm * 1000)
image.fill(0)

# Cria a composição
imagePainter = QPainter(image)
c.renderPage( imagePainter, 0 )
imagePainter.end()

image.save(localSalvo+"_mapa.png", "png")

Caso você tenha seguido os passos corretamente e nenhum erro tenha acontecido, você obterá o seguinte mapa.

Mapa gerado após seguir os procedimentos que apresentamos.
Mapa gerado após seguir os procedimentos que apresentamos.

A aparência do nosso mapa não é a melhor de todas, por isso, vamos modificar um pouco os códigos que apresentamos para que ele fique mais apresentável, acrescentando também, em qual região de planejamento e bacia hidrográfica o ponto se encontra.

Melhorando a aparência do nosso mapa

A legenda será o primeiro item que iremos melhorar. Confira o código abaixo (as linhas com comentários são aquelas que foram inseridas).


# Adiciona legenda ao mapa
legend = QgsComposerLegend(c)
legend.model().setLayerSet(mapRenderer.layerSet())
legend.setItemPosition(10,10)
legend.setTitle("Legenda: ") # Acrescenta ou modifica o título da legenda
legend.setFrameOutlineWidth(0.5) # Modifica tamanho da linha no entorno da legenda
legend.setFrameEnabled(1) # Acrescenta linha no entorno da legenda
c.addItem(legend)

Com a legenda corrigida, vamos modificar o texto que foi inserido.

Além de aparecer “Blog 2 Engenheiros”, vamos fazer ele mostrar o local onde o ponto inserido pelo usuário caiu (conforme bacia hidrográfica e região de planejamento).


# Adiciona texto (label) ao mapa gerado
composerLabel = QgsComposerLabel(c)
composerLabel.setText("Blog 2 Engenheiros: ")
composerLabel.adjustSizeToText()
composerLabel.setItemPosition(c.paperWidth() - 100, c.paperHeight() - 24)
c.addItem(composerLabel)

# Adiciona texto referente à localização do ponto adicionado
regiaoLabel = QgsComposerLabel(c)
if self.dlg.checkBoxRP.isChecked():
	try:
		regiaoLabel.setText(pnt_selection[0] + u" esta localizado em " + rp_selection[0])
	except:
		regiaoLabel.setText(u"O ponto fornecido esta fora da área de interesse!!")
else:
	regiaoLabel.setText(u"O item Região de Planejamento não foi selecionado.")
regiaoLabel.adjustSizeToText()
regiaoLabel.setItemPosition(c.paperWidth() - 100, c.paperHeight() - 19)
c.addItem(regiaoLabel)

baciaLabel = QgsComposerLabel(c)
if self.dlg.checkBoxBH.isChecked():
	try:
		baciaLabel.setText(pnt_selection[0] + " esta na " + bh_selection[0])
	except:
		baciaLabel.setText(u"O ponto fornecido esta fora da área de interesse!!")
else:
	baciaLabel.setText(u"O item Bacias Hidrográficas não foi selecionado.")
baciaLabel.adjustSizeToText()
baciaLabel.setItemPosition(c.paperWidth() - 100, c.paperHeight() - 14)
c.addItem(baciaLabel)

Agora vamos adicionar uma grade de coordenadas e uma borda ao nosso mapa, lembrando que devemos modificar, para isso, a posição que o nosso mapa foi inserido.


# Adicionando e definindo onde o mapa será inserido na folha
x, y = 25, 25 # Variáveis que mostram a origem do nosso mapa na folha de impressão
w, h = c.paperWidth() - 50, c.paperHeight() - 50 # Variáveis mostrando o tamanho do nosso mapa
composerMap = QgsComposerMap(c, x, y, w, h)

composerMap.setFrameEnabled(1) # Liga a borda do nosso mapa
composerMap.setGridEnabled(True) # Liga a grade de coordenadas
composerMap.setGridIntervalX(20000) # Determina o intervalo da grade no eixo X
composerMap.setGridIntervalY(20000) # Determina o intervalo da grade no eixo X
composerMap.setShowGridAnnotation(True) # Mostra os valores das coordenadas
#composerMap.setGridAnnotationPrecision(0) # Precisão das coordenadas (Zero = não há casas decimais) (Por alguma razão, essa função não funciona).
composerMap.setGridStyle(QgsComposerMap.Cross) # Estilo da Grade

# Determina a posição e direção das coordenadas no topo do mapa
composerMap.setGridAnnotationPosition(QgsComposerMap.OutsideMapFrame, QgsComposerMap.Top)
composerMap.setGridAnnotationDirection(QgsComposerMap.Horizontal, QgsComposerMap.Top)

# Desabilita coordenadas na parte inferior do mapa
composerMap.setGridAnnotationPosition(QgsComposerMap.Disabled, QgsComposerMap.Bottom)

# Desabilita coordenadas na esquerda do mapa
composerMap.setGridAnnotationPosition(QgsComposerMap.Disabled, QgsComposerMap.Left)

# Determina a posição e direção das coordenadas na direita do mapa
composerMap.setGridAnnotationPosition(QgsComposerMap.OutsideMapFrame, QgsComposerMap.Right)
composerMap.setGridAnnotationDirection(QgsComposerMap.Vertical, QgsComposerMap.Right)

#composerMap.setAnnotationFrameDistance(1) # Distância da coordenada do mapa (Por alguma razão, essa função não funciona).
composerMap.setAnnotationFontColor(QColor(0, 0, 0)) # Cor da coordenada
c.addItem(composerMap)

O resultado das nossas modificação é apresentado na figura abaixo.

Após abrir o shapefile com os municípios do RJ, rodamos nosso plugin e este é o resultado.
Após abrir o shapefile com os municípios do RJ, rodamos nosso plugin e este é o resultado.

Lembre-se de, antes de utilizar o plugin, determinar corretamente o sistema de coordenadas, ajustar a legenda e as cores do seu mapa, para que, ao utilizar o plugin, o mapa final sai corretamente.

Você pode baixar o arquivo python clicando em ponto_exato_final.

Confira o vídeo (aqui) que realizamos mostrando como o plugin funciona (aproveite e se inscreva no nosso canal do Youtube) e se você quer conferir as postagens anteriores deste plugin, confira os links abaixo:

Ficou com alguma dúvida? Deixa ela nos comentários que iremos responder assim que possível.

Referências Consultadas:

Documentation QGIS 2.18: https://docs.qgis.org/2.18/en/docs/pyqgis_developer_cookbook/composer.html

GIS StackExchange “Setting an item position (variable) from LowerRight?”: https://gis.stackexchange.com/questions/206150/setting-an-item-position-variable-from-lowerright

GIS StackExchange “How can I add grid lines to a print composition using pyqgis?”: https://gis.stackexchange.com/questions/85724/how-can-i-add-grid-lines-to-a-print-composition-using-pyqgis


Clique na figura abaixo e assine nossa lista de emails para receber nosso ebook "Como criar mapas de localização com ArcGIS 10.x".

Apostila Mapa de Localização Banner

Author: Fernando BS

Engenheiro Ambiental e de Segurança do Trabalho. Atua nas áreas de geoprocessamento, mineração e hidrologia. Busca soluções utilizando softwares como QGIS, R e Python.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *