Visualizzazione e Stampa di una Mappa

Esistono generalmente due approcci per visualizzare i dati come mappa: o in modo veloce utilizzando QgsMapRenderer oppure producendo un risultato piú raffinato componendo la mappa con la classe QgsComposition.

Visualizzazione Semplice

Visualizzare alcuni layer utilizzando QgsMapRenderer — create il dispositivo di destinazione (QImage, QPainter etc.), configurare l’insieme di layer, dimensione del risultato ed eseguire la visualizzazione

# create image
img = QImage(QSize(800, 600), QImage.Format_ARGB32_Premultiplied)

# set image's background color
color = QColor(255, 255, 255)
img.fill(color.rgb())

# create painter
p = QPainter()
p.begin(img)
p.setRenderHint(QPainter.Antialiasing)

render = QgsMapRenderer()

# set layer set
lst = [layer.getLayerID()]  # add ID of every layer
render.setLayerSet(lst)

# set extent
rect = QgsRect(render.fullExtent())
rect.scale(1.1)
render.setExtent(rect)

# set output size
render.setOutputSize(img.size(), img.logicalDpiX())

# do the rendering
render.render(p)

p.end()

# save image
img.save("render.png","png")

Visualizzare layer con diversi SR

Nel caso in cui si abbia piú di un layer con un diverso SR, il semplice esempio precedente probabilmente non funzionerá: per ottenere i valori corretti dai calcoli dell’estensione si dovrá impostare esplicitamente l’SR di destinazione ed abilitare la riproiezione OTF come nel prossimo esempio (dove viene riportata unicamente la parte di visualizzazione)

...
# set layer set
layers = QgsMapLayerRegistry.instance().mapLayers()
lst = layers.keys()
render.setLayerSet(lst)

# Set destination CRS to match the CRS of the first layer
render.setDestinationCrs(layers.values()[0].crs())
# Enable OTF reprojection
render.setProjectionsEnabled(True)
...

Risultato utilizzando il Compositore di Stampe

Il compositore di mappe é uno strumento molto utile nel caso in cui si voglia produrre un risultato piú sofisticato rispetto alla semplice visualizzazione mostrata sopra. Utilizzando il compositore é possibile creare composizioni di mappe complesse composte da viste, etichette, legenda, tabelle ed altri elementi che sono solitamente presenti sulle mappe cartacee. La composizione puó essere esportata in PDF, immagini raster o stampata direttamente tramite una stampante.

The composer consists of a bunch of classes. They all belong to the core library. QGIS application has a convenient GUI for placement of the elements, though it is not available in the GUI library. If you are not familiar with Qt Graphics View framework, then you are encouraged to check the documentation now, because the composer is based on it.

La classe principale del composer é QgsComposition che deriva da QGraphicsScene. Creiamone una

mapRenderer = iface.mapCanvas().mapRenderer()
c = QgsComposition(mapRenderer)
c.setPlotStyle(QgsComposition.Print)

Si noti che la composizione prende un’istanza di QgsMapRenderer. Il codice viene eseguito all’interno dell’applicazione QGIS e quindi utilizza la visualizzazione della mappa. La composizione utilizza diversi parametri della visualizzazione della mappa, soprattutto l’insieme predefinito di mappe e l’estensione corrente. Quando si utilizza il compositore in un’applicazione standalone, é possibile creare la propria istanza di mappa nello stesso modo mostrato nella sezione di cui sopra e passarla alla composizione.

É possibile aggiungere vari elementi (mappa. etichetta, ...) alla composizione — questi elementi devono essere discendenti della classe QgsComposerItem. Gli elementi attualmente supportati sono:

  • mappa — questo elemento dice alle librerie dove posizionare la mappa stessa. Qui creiamo una mappa e la stiriamo sull’intera pagina

    x, y = 0, 0
    w, h = c.paperWidth(), c.paperHeight()
    composerMap = QgsComposerMap(c, x ,y, w, h)
    c.addItem(composerMap)
    
  • etichetta — permetta la visualizzazione di etichette. É possibile modificarne il carattere, colore, allineamento e margine

    composerLabel = QgsComposerLabel(c)
    composerLabel.setText("Hello world")
    composerLabel.adjustSizeToText()
    c.addItem(composerLabel)
    
  • legenda

    legend = QgsComposerLegend(c)
    legend.model().setLayerSet(mapRenderer.layerSet())
    c.addItem(legend)
    
  • barra di scala

    item = QgsComposerScaleBar(c)
    item.setStyle('Numeric') # optionally modify the style
    item.setComposerMap(composerMap)
    item.applyDefaultSize()
    c.addItem(item)
    
  • freccia

  • immagine

  • forma

  • tabella

Come parametro predefinito il compositore appena creato ha posizione zero (angolo in alto a sinistra della pagina) e dimensione zero. La posizione e la dimensione sono sempre misurate in millimetri

# set label 1cm from the top and 2cm from the left of the page
composerLabel.setItemPosition(20, 10)
# set both label's position and size (width 10cm, height 3cm)
composerLabel.setItemPosition(20, 10, 100, 30)

Una cornice viene disegnata attorno ad ogni elemento da impostazione predefinita. Come rimuovere la cornice

composerLabel.setFrame(False)

Oltre a creare gli elementi del compositore manualmente, QGIS fornisce il supporto per i modelli del compositore, che sono essenzialmente delle composizioni aventi tutti gli elementi salvati in un file .qpt (con sintassi XML). Purtroppo questa funzionalitá non é ancora disponibile nelle API.

Una volta che la composizione é pronta (gli elementi del compositore sono stati creati ed aggiunti alla composizione), possiamo procedere alla creazione di un risultato raster e/o vettoriale.

Le impostazioni predefinite del risultato per la composizione sono il formato di pagina A4 e risoluzione 300 DPI. É possibile cambiarle se necessario. La dimensione della pagina é specificata in millimetri

c.setPaperSize(width, height)
c.setPrintResolution(dpi)

Esportare come immagine raster

Il seguente frammento di codice mostra come visualizzare una composizione come immagine raster

dpi = c.printResolution()
dpmm = dpi / 25.4
width = int(dpmm * c.paperWidth())
height = int(dpmm * c.paperHeight())

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

image.save("out.png", "png")

Esportare come PDF

Il seguente frammento di codice visualizza la composizione come file PDF

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

pdfPainter = QPainter(printer)
paperRectMM = printer.pageRect(QPrinter.Millimeter)
paperRectPixel = printer.pageRect(QPrinter.DevicePixel)
c.render(pdfPainter, paperRectPixel, paperRectMM)
pdfPainter.end()