Wie verwende ich Map Composer in einem eigenständigen Skript?

9

Ich versuche, dem Abschnitt zum Rendern von Karten aus dem Pyqgis-Kochbuch zu folgen , möchte dies jedoch als eigenständige Anwendung testen. Ich kann den ersten Teil mit einfachem Rendering ausführen, aber beim zweiten Beispiel mit dem Map Composer als eigenständigem Skript bin ich etwas festgefahren.

Hier ist ein eigenständiges Beispiel für das, was ich tun kann:

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

Was ich wirklich gerne machen würde, ist dasselbe, aber benutze QgsCompositionund speichere wie zum Beispiel pdf. Das Kochbuch sagt:

Wenn Sie Composer in einer eigenständigen Anwendung verwenden, können Sie Ihre eigene Map-Renderer-Instanz auf die gleiche Weise wie im obigen Abschnitt gezeigt erstellen und an die Komposition übergeben.

Dieses Bit konnte ich nicht machen, alle meine Versuche bekommen entweder eine leere Karte oder einen Segfault. Ich verwende Linux Mint 13 mit QGIS 1.8.0. Es wäre großartig, wenn mir jemand zeigen könnte, wie man das einfache Beispiel in ein Beispiel ändert, das den Komponisten verwendet.

rjad
quelle

Antworten:

8

Basierend auf den Kommentaren funktioniert diese Antwort für Versionen vor.2.4
Zum späteren Nachschlagen finden Sie hier ein eigenständiges Beispiel.

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
quelle
Wenn ich das mache, bekomme ich ein PDF, aber es ist leer. Ich benutze 2.10 (ich muss .getLayerID () in .id () ändern)
Conley Owens
Ja, tut mir leid, es funktioniert auch nicht mehr bei mir. Funktioniert mit 1.8.0, aber ich habe es gerade mit 2.4.0 getestet und scheint nicht mehr zu funktionieren.
rjad
Das Hinzufügen von composerMap.setNewExtent (mapRectangle) scheint zu funktionieren.
rjad
Leider funktioniert dies unter 2.8.3 nicht mehr. Ich habe getLayerID () in .id () geändert und erhalte immer noch nur eine leere Seite. Das Rendern von statischem Text usw. funktioniert. Irgendwelche Ideen, wo das Problem liegen könnte?
Chrisiserik
QgsMapRenderer ist in 2.4und darüber veraltet. Diese Antwort basiert auf demselben Beispiel, das funktionieren sollte. Gis.stackexchange.com/a/223127/36886
raphael
3

QgsMapRenderer wird in 2.4 als veraltet und oben habe ich den veralteten Teil von aktualisiert diese Antwort auf etwas , das von der Arbeit sollte 2.4zu 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
quelle
layer.getLayerID()funktioniert nicht und muss geändert werden zu:layer.id()
Mr. Che
@ Mr.Che bitte geben Sie Ihr Betriebssystem und QGIS-Version
Raphael
Win 7 und QGIS-Version: i.stack.imgur.com/8u8Ed.png
Mr. Che
2

Vielleicht ist dieser Code hilfreich, obwohl es sich nicht um eine eigenständige Anwendung handelt:

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

Die Karte basiert auf einem QGIS-Projekt. Ein vollständiges Beispiel finden Sie hier: http://www.qgis.nl/media/2013/08/composerimage_demo.zip

Sake
quelle
Vielen Dank, aber mein Problem ist, dass ich nicht weiß, wie ich ein gültiges mapRenderer-Objekt erhalten kann, an das ich übergeben kann, QgsCompositionohne es aufzurufen iface.mapCanvas().mapRenderer().
rjad