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.

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

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

layer.getLayerID()nie działa i musi zostać zmieniony na:layer.id()
Towarzysz Che

@ Mr.Che, proszę podać wersję systemu operacyjnego i QGIS
raphael


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


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.