Comment utiliser le compositeur de cartes dans un script autonome?

9

J'essaie de suivre la section de rendu de carte du livre de recettes pyqgis, mais j'aimerais tester cela en tant qu'application autonome. Je peux faire la première partie, en utilisant un rendu simple, mais je suis un peu coincé à faire le deuxième exemple en utilisant le compositeur de carte comme script autonome.

Voici un exemple autonome pour le peu que je peux faire:

from qgis.core import *
from qgis.gui import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtXml import *

QgsApplication.setPrefixPath("/usr/", True)
QgsApplication.initQgis()

fh = open("eg.csv","w")
fh.write("""
x,y,name
153.0278, -27.4679, Brisbane
144.2500, -23.4500, Longreach
145.7753, -16.9256, Cairns
""")
fh.close()

uri = "eg.csv?delimiter=%s&xField=%s&yField=%s" % (",", "x", "y")
layer = QgsVectorLayer(uri, "eglayer", "delimitedtext")
QgsMapLayerRegistry.instance().addMapLayer(layer)
img = QImage(QSize(800,600), QImage.Format_ARGB32_Premultiplied)
color = QColor(255,255,255)
img.fill(color.rgb())
p = QPainter()
p.begin(img)
render = QgsMapRenderer()
lst = [ layer.getLayerID() ]  # add ID of every layer
render.setLayerSet(lst)
rect = QgsRectangle(render.fullExtent())
rect.scale(1.1)
render.setExtent(rect)
render.setOutputSize(img.size(), img.logicalDpiX())
render.render(p)
p.end()
img.save("render.png","png")

Ce que j'aimerais vraiment faire, c'est la même chose, mais utilisez QgsCompositionet enregistrez comme par exemple pdf. Le livre de cuisine dit:

Lorsque vous utilisez Composer dans une application autonome, vous pouvez créer votre propre instance de rendu de carte de la même manière que celle indiquée dans la section ci-dessus et la transmettre à la composition.

Ce bit, je ne pouvais pas le faire, toutes mes tentatives obtenaient une carte vide ou un défaut de segmentation. J'utilise linux mint 13, en utilisant qgis 1.8.0. Ce serait formidable si quelqu'un pouvait me montrer comment modifier l'exemple simple en un exemple qui utilise le compositeur.

rjad
la source

Réponses:

8

Sur la base des commentaires, cette réponse fonctionne pour les versions antérieures à2.4
Pour référence future, voici un exemple autonome de travail.

from qgis.core import *
from qgis.gui import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtXml import *

QgsApplication.setPrefixPath("/usr", True)
QgsApplication.initQgis()
app = QgsApplication([], True)

fh = open("eg.csv","w")
fh.write("""
x,y,name
153.0278, -27.4679, Brisbane
144.2500, -23.4500, Longreach
145.7753, -16.9256, Cairns
""")
fh.close()

uri = "eg.csv?delimiter=%s&xField=%s&yField=%s" % (",", "x", "y")
layer = QgsVectorLayer(uri, "eglayer", "delimitedtext")
print layer.isValid()
layerset = []
QgsMapLayerRegistry.instance().addMapLayer(layer)
layerset.append(layer.getLayerID())

myMapRenderer = QgsMapRenderer()
myMapRenderer.setLayerSet(layerset)
mapRectangle = QgsRectangle(140,-28,155,-15)
myMapRenderer.setExtent(mapRectangle)

comp = QgsComposition(myMapRenderer)
comp.setPlotStyle(QgsComposition.Print)
composerMap = QgsComposerMap(comp, 5,5,200,200)
composerMap.setNewExtent(mapRectangle)
comp.addItem(composerMap)
printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName("out.pdf")
printer.setPaperSize(QSizeF(comp.paperWidth(), comp.paperHeight()),    QPrinter.Millimeter)
printer.setFullPage(True)
printer.setColorMode(QPrinter.Color)
printer.setResolution(comp.printResolution())

pdfPainter = QPainter(printer)
paperRectMM = printer.pageRect(QPrinter.Millimeter)
paperRectPixel = printer.pageRect(QPrinter.DevicePixel)
comp.render(pdfPainter, paperRectPixel, paperRectMM)
pdfPainter.end()
app.exitQgis()
rjad
la source
Quand je fais cela, j'obtiens un pdf, mais c'est vide. J'utilise 2.10 (je dois changer .getLayerID () en .id ())
Conley Owens
Ouais, désolé, ça ne marche plus pour moi non plus. Fonctionne sur 1.8.0, mais je viens de le tester sur 2.4.0 et ne semble plus fonctionner.
rjad
L'ajout de composerMap.setNewExtent (mapRectangle) semble le faire fonctionner.
rjad
Malheureusement, cela ne fonctionne plus sur 2.8.3. J'ai changé getLayerID () en .id () et n'ai toujours qu'une page vierge. Le rendu de texte statique, etc. fonctionne. Des idées sur ce que pourrait être le problème?
chriserik
QgsMapRenderer est déconseillé dans 2.4et au-dessus, voir cette réponse basée sur le même exemple qui devrait fonctionner gis.stackexchange.com/a/223127/36886
raphael
3

QgsMapRenderer est obsolète dans la version 2.4 et supérieure, j'ai mis à jour la partie obsolète de cette réponse en quelque chose qui devrait fonctionner de 2.4à 2.18.2.

from qgis.core import *
from qgis.gui import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtXml import *

QgsApplication.setPrefixPath("/usr", True)
QgsApplication.initQgis()
app = QgsApplication([], True)

fh = open("eg.csv","w")
fh.write("""
x,y,name
153.0278, -27.4679, Brisbane
144.2500, -23.4500, Longreach
145.7753, -16.9256, Cairns
""")
fh.close()

uri = "eg.csv?delimiter=%s&xField=%s&yField=%s" % (",", "x", "y")
layer = QgsVectorLayer(uri, "eglayer", "delimitedtext")
print layer.isValid()
layerset = []
QgsMapLayerRegistry.instance().addMapLayer(layer)
layerset.append(layer.getLayerID())

def create_composition(layer_list, extent):
#New code for versions 2.4 and above
    ms = QgsMapSettings()
    ms.setLayers(layer_list)
    ms.setExtent(extent)
    comp = QgsComposition(ms)
    return comp, ms

comp, ms = create_composition(layerset, QgsRectangle(140,-28,155,-15))

comp.setPlotStyle(QgsComposition.Print)
composerMap = QgsComposerMap(comp, 5,5,200,200)

#Uses mapsettings value
composerMap.setNewExtent(ms.extent())

comp.addItem(composerMap)
printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName("out.pdf")
printer.setPaperSize(QSizeF(comp.paperWidth(), comp.paperHeight()),    QPrinter.Millimeter)
printer.setFullPage(True)
printer.setColorMode(QPrinter.Color)
printer.setResolution(comp.printResolution())

pdfPainter = QPainter(printer)
paperRectMM = printer.pageRect(QPrinter.Millimeter)
paperRectPixel = printer.pageRect(QPrinter.DevicePixel)
comp.render(pdfPainter, paperRectPixel, paperRectMM)
pdfPainter.end()
app.exitQgis()
raphael
la source
layer.getLayerID()ne fonctionne pas et doit être changé en:layer.id()
Camarade Che
@ Mr.Che veuillez inclure votre version du système d'exploitation et de QGIS
raphael
Win 7 et version QGIS: i.stack.imgur.com/8u8Ed.png
Camarade Che
2

Peut-être que ce code est utile, bien qu'il ne s'agisse pas d'une application autonome:

from qgis.core import *
from qgis.utils import iface
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import os   
# Clear map canvas
QgsMapLayerRegistry.instance().removeAllMapLayers()
iface.mapCanvas().refresh()
# Open QGIS project
QgsProject.instance().setFileName('composerimage_demo.qgs')
QgsProject.instance().read()
# Set up composition
mapRenderer = iface.mapCanvas().mapRenderer()
c = QgsComposition(mapRenderer)
c.setPlotStyle(QgsComposition.Print)
# Set dimensions and resolution
c.setPaperSize(160,185)
dpi = c.printResolution()
dpmm = (dpi / 25.4)
width = int(dpmm * c.paperWidth())
height = int(dpmm * c.paperHeight())
# Add map to composition
x, y = 0, 0
w, h = c.paperWidth(), c.paperHeight()
composerMap = QgsComposerMap(c, x,y,w,h)
composerMap.setFrame(True) # Does not work with QGIS 1.9-Master. Use hasFrame() instead.
c.addItem(composerMap)
# 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 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()
# Save image to disk (other extensions possible)
image.save('composerimage_demo.jpg')
# Clear map canvas
QgsMapLayerRegistry.instance().removeAllMapLayers()
iface.mapCanvas().refresh()

La carte est basée sur un projet QGIS. Vous pouvez trouver un exemple complet ici: http://www.qgis.nl/media/2013/08/composerimage_demo.zip

Saké
la source
Merci, mais mon problème est que je ne sais pas comment faire passer un objet mapRenderer valide QgsCompositionsans appeler iface.mapCanvas().mapRenderer().
rjad