Renderizando e rotulando Shapefile com PyQGIS

8

Estou com alguns problemas ao trabalhar com a API QGIS para python. Fiquei mais confortável trabalhando no console python no QGIS, mas encontro problemas ao tentar executar o código fora do QGIS.

Basicamente, quero pegar um shapefile, rotulá-lo com base no nome do atributo especificado e renderizar uma imagem. O código funciona no QGIS, mas não funciona fora do QGIS. Então, de onde vem o meu problema?

import sys
import qgis
import PyQt4

from qgis.core import *
from qgis.utils import *
from qgis.gui import *


from PyQt4.QtCore import *
from PyQt4.QtGui import *

#initialize QGIS
QgsApplication.setPrefixPath( r"C:\OSGeo4W64\apps\qgis", True )

QgsApplication.initQgis()

#Add layer to instance
file = QgsVectorLayer("Good Shape File", "BMAS", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(file)


#Adjust layer Settings
#Code sample from http://gis.stackexchange.com/questions/77870/how-to-label-vector-features-programmatically
palyr = QgsPalLayerSettings() 
palyr.enabled = True 
palyr.fieldName = 'Attribute' 
palyr.placement= QgsPalLayerSettings.OverPoint 
palyr.setDataDefinedProperty(QgsPalLayerSettings.Size,True,True,'8','') 
palyr.writeToLayer(file)

if file.isValid():
  print "File is valid."


mapRenderer = iface.mapCanvas().mapRenderer()

lst = [file.id()]
mapRenderer.setLayerSet(lst)

mapRenderer.setLayerSet( lst )
c = QgsComposition(mapRenderer)
c.setPlotStyle(QgsComposition.Print)
x, y = 0, 0
w, h = c.paperWidth(), c.paperHeight()
composerMap = QgsComposerMap(c, x,y,w,h)
c.addItem(composerMap)
composerLabel = QgsComposerLabel(c)

composerLabel.adjustSizeToText()
c.addItem(composerLabel)
composerLabel.setItemPosition(20,10)
composerLabel.setItemPosition(20,10, 100, 30)

legend = QgsComposerLegend(c)
legend.model().setLayerSet(mapRenderer.layerSet())
c.addItem(legend)

#set image sizing
dpi = c.printResolution()
dpmm = dpi / 25.4
width = int(dpmm * c.paperWidth())
height = int(dpmm * c.paperHeight())
img = QImage(QSize(width, height), QImage.Format_ARGB32)
img.setDotsPerMeterX(dpmm * 1000)
img.setDotsPerMeterY(dpmm * 1000)
img.fill(0)
imagePainter = QPainter(img)
sourceArea = QRectF(0, 0, c.paperWidth(), c.paperHeight())
targetArea = QRectF(0, 0, width, height)

#renders image
c.render(imagePainter, targetArea, sourceArea)
imagePainter.end()
img.save("E:/QGisTestImages/out.png", "png")

Sou capaz de fazer o exemplo de renderização simples no livro de receitas python, então acho que meus caminhos estão configurados corretamente.

"Arquivo de boa forma" deve ser substituído por um bom local de caminho, se você deseja executar isso. E palyr.fieldName = 'Attribute' deve ser definido como um nome de campo válido para esse shapefile.

Edit: Eu me livrei do iface e inseri o código pela extensão entre a inicialização do mapRenderer e a declaração lst.

mapRenderer = QgsMapRenderer()

rect = file.extent()
mapRenderer.setExtent(rect)
mapRenderer.setLabelingEngine(QgsPalLabeling())
lst = [file.id()]

Editar: eu adicionei

app = QgsApplication([], True)

depois de

QgsApplication.initQgis()

e o código funcionou.

meio-campo
fonte
1
Para começar, você não pode usar ifacefora do QGIS. Isso precisa sermapRenderer = QgsMapRenderer()
Nathan W
Tudo bem, parece que eu não inicializei o mapRenderer com informações suficientes. O console congela em c = QgsComposition (mapRenderer) depois que adicionei as informações sobre a extensão da camada e o mecanismo de identificação. O código ainda funciona no QGIS, mas precisa ser redimensionado.
midfield99
1
Parece que a inicialização do QgsApplication foi o problema. E parece que esse problema foi abordado em gis.stackexchange.com/questions/69626/… . Portanto, declarar uma variável do aplicativo e adicionar um app.exitQgis () funcionou.
midfield99
Estou com problemas ao criar pngs com o método mencionado acima. Meu arquivo shapefile é lido corretamente, uma imagem é criada, mas sempre fica completamente branca. Como você pode ver nas impressões, os valores mapRenderer.extent () são sempre zero. Isso é normal ou preciso aprofundar isso? As verificações subsequentes com dpi, largura e altura do QgsComposition entregam alguns valores, embora eu não tenha idéia se eles estão corretos ou não. Eu também experimentei várias opções diferentes de impressão / renderização, como c.render (), ou o material em PDFs. Eu nunca recebo erros, mas meu pag
Bob3k
Hey moderador que excluiu meu último post sobre o mesmo tópico, por favor, deixe este aqui. Isso é completamente relevante, porque não acredito que as respostas acima ainda funcionem e não sou a única que está lutando aqui. Ou eu sou louco, ou os dois bits de código não funcionam mais. Eu copiei e ajustei para o meu uso e, para a minha vida, não consigo obter um detalhe do shapefile com outra coisa senão uma tela branca que diz 'Legenda: Contornos' no canto superior esquerdo. Meu objetivo é para dar uma shapefile (SHP) e convertê-lo em um tif com as linhas de contorno marcados em elevação eu sou capaz de abrir o s.
Marc

Respostas:

2

A combinação de remover iface e declarar a variável do aplicativo parece ter funcionado. Agora eu recebo uma imagem renderizada do shapefile com cada recurso rotulado com o atributo com base em 'Atributo'.

meio-campo
fonte