Map Renderer con PyQGIS

Para convertir un mapa GIS dinámico en una imagen estática o documento se debe renderizar para captar la Map View de QGIS y crear una versión gráfica del mapa. Para ello se requiere el concurso de varias clases; entre las que se cuentan como las más importantes QgsMapRenderer, QgsComposition, QgsComposerMap, QgsComposerLabel, QImage y QPainter. La clase QFont podría ser considerada si queremos cambiar las fuentes tipográficas que, por defecto, asumen las clases precedentes.

Para realizar este post tomé una porción de código del libro de Joel Lawhead (QGIS Python Programming Cookbook, 2015) y, usando mi función getPat, me dispuse a explorar de manera más exhaustiva los métodos de las clases ya mencionadas en el párrafo anterior. Es verdaderamente útil porque de las más de 500 opciones, entre métodos y constantes, presentes en algunas de ellas, getPat las reduce, en la mayoría de los casos, a sólo unas pocas candidatas.

Para probar el código usé el shapefile del condado de Hancock que se encuentra disponible en Internet. Esta versión que presento a continuación es todavía de prueba. Tiene algunas líneas comentadas y también faltan algunos de los nombres de las constantes del diccionario. La documentación es muy “espesa” y cuesta, a veces, encontrar las definiciones. El objectivo de mi código es cargar el shapefile y renderizar la Map View en una imagen jpg. Esta presenta 2 labels rotados de manera arbitraria para verificar el uso correcto de los parámetros correspondientes. Se habilitan los frames del composer map y de los labels donde también se asignan espesores y colores. Además, se habilita la Grid para desplegar la georreferenciación con gran cantidad de parámetros usados.

El código fue el siguiente:

from PyQt4.QtGui import *
from PyQt4.QtCore import *

def myFont(text):
    
    my_dictionary = {1:'family', 
                     2:'pointSize', 
                     3:3, 
                     4:4, 
                     5:5, 
                     6:'setItalic', 
                     7:'setUnderline', 
                     8:8, 
                     9:9, 
                     10:10}
    
    text = text.split(',')
    lista = []
    
    i = 1
    
    for item in text:
        print str(my_dictionary[i]) + " =", item
        i += 1
        if item.isnumeric() == True:
            lista.append(int(item))
        else:
            lista.append(item)

def composer(name_label):

    layer = QgsVectorLayer("/home/zeito/pyqgis_data/hancock.shp", "hancock", "ogr")

    renderer = layer.rendererV2()
    symbol = renderer.symbol()
    symbol.setColor(QColor('blue'))

    reg = QgsMapLayerRegistry.instance()
    
    reg.addMapLayer(layer)

    layers = reg.mapLayers().keys()
    
    #mr is a QgsMapRenderer object
    mr = iface.mapCanvas().mapRenderer()

    mr.setLayerSet(layers)

    rect = QgsRectangle(layer.extent())

    rect.scale(1.2)

    mr.setExtent(rect)

    #c is a QgsComposition object
    c = QgsComposition(mr)

    c.setPlotStyle(QgsComposition.Print)
    
    #Set Paper Size
    c.setPaperSize(215.9, 279.4) #letter

    w, h = c.paperWidth() * .50, c.paperHeight() * .50

    x = (c.paperWidth() - w) / 2
    y = ((c.paperHeight() - h)) / 2

    #Create an object of QgsComposerMap class
    composerMap = QgsComposerMap(c, x, y, w, h)
    composerMap.setNewExtent(rect)
    composerMap.setFrameEnabled(True)
    composerMap.setBackgroundEnabled(True)
    composerMap.setBackgroundColor(QColor('yellow'))
    composerMap.setFrameOutlineColor(QColor('green'))
    composerMap.setFrameOutlineWidth(3)
    
    #Parametros de la Grid dentro del composerMap
    composerMap.setGridEnabled(True)
    composerMap.setGridFrameStyle(1)
#    composerMap.setGridAnnotationPosition(20,20)
    composerMap.setGridAnnotationPrecision(2)
    composerMap.setGridIntervalX(0.1)
    composerMap.setGridIntervalY(0.1)
    composerMap.setShowGridAnnotation(True)
    c.addItem(composerMap)

    #default print resolution in 300 dpi
    dpi = c.printResolution()
    c.setPrintResolution(dpi)

    mm_in_inch = 25.4
    dpmm = dpi / mm_in_inch

    width = int(dpmm * c.paperWidth())
    height = int(dpmm * c.paperHeight())

    #Create an object of QFont class
    #Type fonts: "Times", "Courier New", "OldEnglish", "Serif", "Fantasy"
    my_font = QFont('Courier New')
    cap = my_font.capitalization()
    my_font.setCapitalization(cap)
    my_font.setItalic(True)
#    my_font.setBold(True)
    my_font.setPointSize(34)
    my_font.setUnderline(True) #
    my_font.setOverline(True)
    print "letter spacing = ", my_font.letterSpacing()
    lst = my_font.letterSpacingType()
    print "QFont.spacingType", lst
    my_font.setLetterSpacing(0, 0)
#    my_font.setRawName(u"My Serif")
    print "my_font = ", my_font.rawName()
    s1 = my_font.key()
    
    myFont(s1) #funcion
    
    my_font2 = QFont('Serif')
    my_font2.setPointSize(12)
    my_font2.setOverline(True)
    my_font2.setUnderline(True)
    
    s2 = my_font2.key()
    
    myFont(s2)
    
    #Create an object of QgsComposerLabel class
    label = QgsComposerLabel(c)
    label.setItemRotation(90, True)
    label.setFont(QFont(my_font))
    label.setFontColor(QColor('white'))
    label.setFrameOutlineColor(QColor('green'))
    label.setText(name_label)
    label.adjustSizeToText()
    label.setItemPosition(80, 40, True)
    label.setFrameEnabled(True)
    label.setBackgroundEnabled(True)
    label.setBackgroundColor(QColor('blue'))
    c.addItem(label)

    #Create an object of QgsComposerLabel class
    label2 = QgsComposerLabel(c)
    label2.setFont(QFont(my_font2))
    label2.setText('label2')
    label2.adjustSizeToText()
    label2.setFrameEnabled(True)
    label2.setItemRotation(30, True)
    label2.setItemPosition(80, 40, True)
    label2.setFontColor(QColor('black'))
    c.addItem(label2)

    #Create an object of QImage class
    image = QImage(QSize(width, height), QImage.Format_ARGB32)
    image.setDotsPerMeterX(dpmm * 1000)
    image.setDotsPerMeterY(dpmm * 1000)
    image.fill(0)

    #Create an object of QPainter class
    imagePainter = QPainter(image)
    imagePainter.rotate(360.0) #same that 0
    sourceArea = QRectF(0, 0, c.paperWidth(), c.paperHeight())
    targetArea = QRectF(0, 0, width, height)
    c.render(imagePainter, targetArea, sourceArea)
    imagePainter.end()
    
    image.save("/home/zeito/Desktop/map.jpg", "jpg")

Cuando se ejecuta en la Python Console ésta es la imagen que produce (las proporciones no son las de una hoja tamaño carta para facilitar su visualización):

composer

A continuación, se coloca la salida de la Python Consola que permite verificar algunos de los parámetros que han sido habilitados para las fuentes del label1 y del label2; respectivamente.

>>>composer('hancock') 
letter spacing =  0.0
QFont.spacingType 0
my_font =  
family = Courier New
pointSize = 34
3 = -1
4 = 5
5 = 50
setItalic = 1
setUnderline = 1
8 = 0
9 = 0
10 = 0
family = Serif
pointSize = 12
3 = -1
4 = 5
5 = 50
setItalic = 0
setUnderline = 1
8 = 0
9 = 0
10 = 0
Esta entrada fue publicada en PyQGIS, QGIS, SIG, Software Libre. Guarda el enlace permanente.

Una respuesta a Map Renderer con PyQGIS

  1. Pingback: Labels y Grid en Map Composer con PyQGIS | El Blog de José Guerrero

Responder

Por favor, inicia sesión con uno de estos métodos para publicar tu comentario:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s