Cómo manejar las capas en PyQGIS utilizando el registro

Hasta ahora, la mayoría de las veces, hemos manejado las capas en el código de la Python Console a través del método ‘activeLayer’ de iface. Como puede deducirse fácilmente, esto se limita a considerar una sola capa. El resto de la información necesaria, que podría ser obtenida de otras capas, se introducía dentro del código ya procesada. Últimamente, el empleo de las QgsMapLayerComboBox en el código de los plugins, con los filtros de QgsMapLayerProxyModel, facilita ampliamente su manejo.

Sin embargo, el manejo de capas en PyQGIS, más allá del método ‘activeLayer’ de iface, se puede hacer a través de los objetos de tres clases diferentes: QgsMapLayerRegistry, QgsMapCanvas y QgsLegendInterface. En el post de hoy se considerará el primero de ellos (también llamado el registro).

Para ello, se van a cargar a QGIS las tres capas vectoriales que se observan en la imagen siguiente:

registro1

Observe que la geometría de las capas es diferente y se pueden filtrar de manera independiente con una QgsMapLayerComboBox. Sin embargo, nuestro deseo es hacerlo en la Python Console empleando el registro. Se instancia de esta manera:

>>>registry = QgsMapLayerRegistry.instance()
>>>registry
<qgis._core.QgsMapLayerRegistry object at 0xa292a7c4>

para obtener un objeto de la misma clase. Con lo siguiente obtenemos el número de capas almacenadas en el registro:

>>>n = registry.count()
>>>n
3

Existen dos métodos importantes, ‘mapLayers’ y ‘mapLayer’, que como se diferencian en una sola letra su uso puede prestarse a confusión. El primero, permite obtener un diccionario donde los ‘keys’ son los códigos de las capas en el registro y los ‘values’ los objetos de la clase QgsMapLayer (que también pueden manejarse con los métodos de las clases heredadas QgsVectorLayer y QgsRasterLayer). El segundo, ‘mapLayer’, permite obtener sólo la Map Layer pasándole como argumento su correspondiente código de registro.

Con listas por comprensión es fácil comprobar lo anterior en una sola línea con el código siguiente:

>>>layers = [ layers_dict.values()[i] for i in range(n) ]
>>>layers
[<qgis._core.QgsVectorLayer object at 0xa29b2bfc>, <qgis._core.QgsVectorLayer object at 0xa2930e84>, 
<qgis._core.QgsVectorLayer object at 0xa2930974>]
>>>layers_keys = [ layers_dict.keys()[i] for i in range(n) ]
>>>layers_keys
[u'points20151007230509944', u'route20151007230509959', u'polygon20151007230509973']

Observe que los códigos del registro de capa incluyen, además del nombre de ésta, la fecha y un número entero. Es fácilmente previsible vislumbrar que estos valores son variables y no tiene sentido preservarlos para sesiones futuras. No los confunda con los nombres de capa que se obtienen de esta manera con el método ‘name’, en este caso, de QgsVectorLayer:

>>>layers_names = [ layers_dict.values()[i].name() for i in range(n) ]
>>>layers_names
[u'points', u'route', u'polygon']

Una vez hechas estas pruebas vamos a ejecutar un script que permita, con una función, obtener información para cada tipo de vectorial pasándole como argumento el nombre de la capa y que use las referencias a las Map Layers que se encuentra en el diccionario. El código es el siguiente:

def attr(layer_name):

    registry = QgsMapLayerRegistry.instance()

    n = registry.count()

    layers_dict = registry.mapLayers()
    
    layers_names = [ layers_dict.values()[i].name() for i in range(n) ]
    
    if layer_name in layers_names:
        idx = layers_names.index( layer_name )
    
    layers = [ layers_dict.values()[i] for i in range(n) ]
    
    print layers[idx].name()
    
    #selecting only one feature
    feat = layers[idx].getFeatures().next()
    
    if layers[idx].geometryType() == QGis.Point:
        print "There are " + str(layers[idx].featureCount()) + " points"

    if layers[idx].geometryType() == QGis.Line:
        print "length %.2f m" % feat.geometry().length()

    if layers[idx].geometryType() == QGis.Polygon:
        print "area %.2f km2" % (feat.geometry().area()/1e6)

attr('points')
attr('route')    
attr('polygon')

que produce este resultado:

points
There are 6 points
route
length 115989.71 m
polygon
area 309.23 km2

El resultado anterior también se produce con el código a continuación pero la referencia a las Map Layers las encuentra en los códigos de capa almacenadas en ‘layers_keys’.

def attr(layer_name):

    registry = QgsMapLayerRegistry.instance()

    n = registry.count()

    layers_dict = registry.mapLayers()
    
    layers_keys = [ layers_dict.keys()[i] for i in range(n) ]
    
    layers_names = [ layers_dict.values()[i].name() for i in range(n) ]
    
    if layer_name in layers_names:
        idx = layers_names.index( layer_name )
    
    layers = [ registry.mapLayer(layers_keys[i]) for i in range(n)]
    
    print layers[idx].name()
    
    #selecting only one feature
    feat = layers[idx].getFeatures().next()
    
    if layers[idx].geometryType() == QGis.Point:
        print "There are " + str(layers[idx].featureCount()) + " points"

    if layers[idx].geometryType() == QGis.Line:
        print "length %.2f m" % feat.geometry().length()

    if layers[idx].geometryType() == QGis.Polygon:
        print "area %.2f km2" % (feat.geometry().area()/1e6)
    
attr('points')
attr('route')    
attr('polygon')

En nuestro curso por Internet de PyQGIS se contemplan con detalle el desarrollo de plugins mediante el empleo de ‘Plugin Builder’.

PRÓXIMA SESIÓN EL 20 DE OCTUBRE

Esta entrada fue publicada en PyQGIS, QGIS, SIG, Software Libre. Guarda el enlace permanente.

2 respuestas a Cómo manejar las capas en PyQGIS utilizando el registro

  1. Pingback: Cómo manejar las capas en PyQGIS utilizando el Map Canvas | El Blog de José Guerrero

  2. Pingback: Cómo manejar las capas en PyQGIS utilizando la interface de leyendas (QgsLegendInterface) | 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