Jak korzystać z kompozytora map w samodzielnym skrypcie?

9

Próbuję śledzić sekcję renderowania mapy z książki kucharskiej pyqgis, ale chciałbym przetestować to jako samodzielną aplikację. Mogę zrobić pierwszą część, używając prostego renderowania, ale trochę utknąłem, robiąc drugi przykład, używając kompozytora map jako samodzielnego skryptu.

Oto samodzielny przykład fragmentu, który mogę zrobić:

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

To, co naprawdę chciałbym zrobić, to to samo, ale użyj QgsCompositioni zapisz jak na przykład pdf. Książka kucharska mówi:

Używając kompozytora w samodzielnej aplikacji, możesz utworzyć własną instancję renderera map w taki sam sposób, jak pokazano w powyższej sekcji i przekazać ją do kompozycji.

Tego kawałka nie mogłem zrobić, wszystkie moje próby albo otrzymały pustą mapę, albo segfault. Korzystam z Linuksa mint 13, używając qgis 1.8.0. Byłoby wspaniale, gdyby ktoś mógł mi pokazać, jak zmodyfikować prosty przykład do tego, który używa kompozytora.

rjad
źródło

Odpowiedzi:

8

W oparciu o komentarze ta odpowiedź działa w przypadku wersji wcześniejszych.2.4
W celu odniesienia w przyszłości, oto działający samodzielny przykład.

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
źródło
Kiedy to robię, dostaję pdf, ale jest pusty. Używam 2.10 (muszę zmienić .getLayerID () na .id ())
Conley Owens
Tak, przepraszam, to też nie działa dla mnie. Działa na 1.8.0, ale właśnie przetestowałem go na 2.4.0 i wydaje się, że już nie działa.
rjad
Wydaje się, że dodanie composerMap.setNewExtent (mapRectangle) powoduje, że działa.
rjad
Niestety nie działa to już w wersji 2.8.3. Zmieniłem getLayerID () na .id () i nadal otrzymuję tylko pustą stronę. Renderowanie tekstu statycznego itp. Działa. Wszelkie pomysły na temat problemu?
chriserik
QgsMapRenderer jest przestarzały 2.4i powyżej, zobacz tę odpowiedź na podstawie tego samego przykładu, który powinien działać gis.stackexchange.com/a/223127/36886
raphael
3

QgsMapRenderer jest przestarzały w wersji 2.4 i nowszych, zaktualizowałem przestarzałą część tej odpowiedzi na coś, co powinno działać od 2.4do 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()
Rafael
źródło
layer.getLayerID()nie działa i musi zostać zmieniony na:layer.id()
Towarzysz Che
@ Mr.Che, proszę podać wersję systemu operacyjnego i QGIS
raphael
Win 7 i wersja QGIS: i.stack.imgur.com/8u8Ed.png
Towarzysz Che
2

Może ten kod jest pomocny, chociaż nie jest to samodzielna aplikacja:

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

Mapa oparta jest na projekcie QGIS. Kompletny przykład można znaleźć tutaj: http://www.qgis.nl/media/2013/08/composerimage_demo.zip

Wzgląd
źródło
Dzięki, ale moim problemem jest to, że nie wiem, jak uzyskać prawidłowy obiekt mapRenderer, do którego można przejść QgsCompositionbez wywoływania iface.mapCanvas().mapRenderer().
rjad