Come usare il compositore di mappe in uno script autonomo?


9

Sto cercando di seguire la sezione di rendering della mappa dal ricettario di pyqgis, ma vorrei testarlo come un'applicazione autonoma. Posso fare la prima parte, usando il rendering semplice, ma sono un po 'bloccato a fare il secondo esempio usando il compositore di mappe come script autonomo.

Ecco un esempio autonomo per il bit che posso fare:

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

Quello che mi piacerebbe davvero fare è lo stesso, ma uso QgsCompositione salva come ad esempio pdf. Il libro di cucina dice:

Quando si utilizza il compositore in un'applicazione autonoma, è possibile creare la propria istanza del renderer della mappa nello stesso modo mostrato nella sezione precedente e passarla alla composizione.

Questo po 'non ho potuto fare, tutti i miei tentativi hanno ottenuto una mappa vuota o segfault. Sto eseguendo Linux mint 13, usando qgis 1.8.0. Sarebbe bello se qualcuno potesse mostrarmi come modificare il semplice esempio in uno che utilizza il compositore.

Risposte:


8

Sulla base dei commenti, questa risposta funziona per le versioni precedenti a2.4
Per riferimento futuro, ecco un esempio autonomo funzionante.

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

Quando lo faccio, ottengo un pdf, ma è vuoto. Sto usando 2.10 (devo cambiare .getLayerID () in .id ())
Conley Owens

Sì, scusa, non funziona più neanche per me. Funziona su 1.8.0, ma l'ho appena testato su 2.4.0 e sembra non funzionare più.
rjad,

L'aggiunta di composerMap.setNewExtent (mapRectangle) sembra farlo funzionare.
rjad,

Sfortunatamente, questo non funziona più su 2.8.3. Ho cambiato getLayerID () in .id () e ho ancora solo una pagina vuota. Il rendering di testo statico ecc. Funziona. Qualche idea su quale potrebbe essere il problema?
Chriserik,

QgsMapRenderer è obsoleto 2.4e superiore, vedi questa risposta basata sullo stesso esempio che dovrebbe funzionare gis.stackexchange.com/a/223127/36886
raphael

3

QgsMapRenderer è obsoleto in 2.4 e versioni successive, ho aggiornato la parte obsoleta da questa risposta a qualcosa che dovrebbe funzionare da 2.4a 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()

layer.getLayerID()non funziona e deve essere modificato in:layer.id()
Compagno Che

@ Mr.Che, per favore, includi la tua versione di OS e QGIS
Raffaele,

Vinci la versione 7 e QGIS: i.stack.imgur.com/8u8Ed.png
Compagno Che

2

Forse questo codice è utile, sebbene non sia un'applicazione autonoma:

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 mappa si basa su un progetto QGIS. Puoi trovare un esempio completo qui: http://www.qgis.nl/media/2013/08/composerimage_demo.zip


Grazie, ma il mio problema è che non so come ottenere un oggetto mapRenderer valido da passare QgsCompositionsenza chiamare iface.mapCanvas().mapRenderer().
rjad,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.