¿Cómo puedo crear y agregar funciones programáticamente a una capa de memoria en QGIS 1.9?

13

Tenía un complemento de trabajo en QGIS 1.8 que leía datos de una base de datos de MSAccess y los agregaba a una serie de capas de memoria. Hay algo de procesamiento involucrado mientras tanto, así que no creo que usar QGIS para leer directamente desde la base de datos sea una opción.

Me gustaría pasar de QGIS 1.8 a 1.9 (principalmente debido a la calidad mejorada del compositor de impresión). El complemento no funciona con la nueva API.

He intentado una variedad de métodos que surgieron en las búsquedas de Google. Uno, que modifica el código a continuación, desde enlace , es decir, agregando geometría y atributos al proveedor de datos y luego actualizar la capa - para adaptarse a la nueva API funcionó un poco, pero los atributos no fueron visibles hasta que ingresé al modo de edición (similar a enlace ). Un enfoque alternativo, detallado en la respuesta # 1 del enlace anterior, agregó la capa y los atributos correctamente pero no pude agregar características a la capa.

Dado que debería ser una tarea bastante simple, espero que alguien de aquí pueda ofrecer un ejemplo práctico de cómo debería hacerse esto. (P.S. No soy un programador profesional y la mayor parte de mi codificación es bastante burda. Acojo con agrado cualquier orientación, pero le pido que disculpe algo de ignorancia por mi parte)

# Receivers = a list of lists returned from a database query

# create layer
vl = QgsVectorLayer("Point", item, "memory")
pr = vl.dataProvider()

# add fields
pr.addAttributes( [ QgsField("Rec_No", QVariant.Int), QgsField("Include",  QVariant.String), QgsField("Label",  QVariant.String), QgsField("X", QVariant.Double),
                    QgsField("Y", QVariant.Double), QgsField("Z", QVariant.Double), QgsField("Height", QVariant.Double),
                    QgsField("Project_Re", QVariant.String), QgsField("NCA", QVariant.String),
                    QgsField("DayCrit", QVariant.Int), QgsField("EveCrit", QVariant.Int), QgsField("NightCrit", QVariant.Int) ] )

for i in range(len(Receivers)):          
  # add a feature
  fet = QgsFeature()
  X = Receivers[i][3]
  Y = Receivers[i][4]
  fet.setGeometry( QgsGeometry.fromPoint(QgsPoint(X,Y)) )

  # Details = a list of results returned from a database query specific to each result in 'Receivers'

  if Receivers[i][3] != 0:
    Include = 'Yes'
  else:
    Include = 'No'

  fet.setAttributeMap( { 0 : QVariant(Receivers[i][0]), 1 : QVariant(Include), 2 : QVariant(Receivers[i][2]),
                         3 : QVariant(Receivers[i][3]), 4 : QVariant(Receivers[i][4]), 5 : QVariant(Receivers[i][5]), 6 : QVariant(Receivers[i][6]),
                         7 : QVariant(Details[0]), 8 : QVariant(Details[1]), 9 : QVariant(Details[2]), 10 : QVariant(Details[3]), 11 : QVariant(Details[4]) } )
  pr.addFeatures( [ fet ] )

# add a style
vl.loadNamedStyle('C:/OSGeo4W/apps/qgis/python/plugins/Gopher2QGIS/styles/Receiver_Style.qml')

# update layer's extent when new features have been added
# because change of extent in provider is not propagated to the layer
vl.commitChanges()
vl.updateExtents()
vl.updateFieldMap()

QgsMapLayerRegistry.instance().addMapLayer(vl)
    
pregunta Adam Bioletti 12.05.2013 - 05:05

2 respuestas

8

Gracias a gsherman sobre el ejemplo del complemento PinPoint es perfecto.

Según entiendo, el proceso es:

  1. Cree la capa con los atributos en la cadena de construcción
  2. Agregar dicha capa al registro de mapas
  3. Comienza a editar en esa capa
  4. Agregue funciones y confirme los cambios

Aquí hay un extracto de mi código que ahora funciona.

layer =  QgsVectorLayer(
          "Point?field=Rec_No:integer&field=Include:string(120)&field=Label:string(120)&field=X:double&field=Y:double&field=Z:double&field=Height:double&field=Project_Re:string(120)&field=NCA:string(120)&field=DayCrit:integer&field=EveCrit:integer&field=NightCrit:integer",
          item,
          "memory")
QgsMapLayerRegistry.instance().addMapLayer(layer)

# Receivers = as in the above example 'Receivers' is a list of results
for i in range(len(Receivers)):

  # add a feature
  feature = QgsFeature()

  X = Receivers[i][3]
  Y = Receivers[i][4]
  feature.setGeometry( QgsGeometry.fromPoint(QgsPoint(X,Y)) )

  # Details = as in the above example 'Details' is a list of results

  if Receivers[i][1] != 0:
    Include = 'Yes'
  else:
    Include = 'No'

  values = [ QVariant(Receivers[i][0]), QVariant(Include), QVariant(Receivers[i][2]),
                         QVariant(Receivers[i][3]), QVariant(Receivers[i][4]), QVariant(Receivers[i][5]), QVariant(Receivers[i][6]),
                         QVariant(Details[0]), QVariant(Details[1]), QVariant(Details[2]), QVariant(Details[3]), QVariant(Details[4]) ]

  feature.setAttributes(values)
  layer.startEditing()
  layer.addFeature(feature, True)
  layer.commitChanges()
    
respondido por el Adam Bioletti 17.05.2013 - 06:59
6

Según la respuesta de Adam Bioletti, las pruebas adicionales del proceso descrito muestran que el único requisito esencial es comenzar a editar la capa de memoria antes de realizar cambios, como la creación de atributos y características, y luego cometer los cambios. Esto se puede hacer antes de agregar la capa al mapa de registro.

Aquí hay una actualización del código del Cookbook que funciona con la API 2.0:

# create layer
vl = QgsVectorLayer("Point", "temporary_points", "memory")
pr = vl.dataProvider()

# changes are only possible when editing the layer
vl.startEditing()
# add fields
pr.addAttributes([QgsField("name", QVariant.String),QgsField("age", QVariant.Int),QgsField("size", QVariant.Double)])

# add a feature
fet = QgsFeature()
fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(10,10)))
fet.setAttributes(["Johny", 2, 0.3])
pr.addFeatures([fet])

# commit to stop editing the layer
vl.commitChanges()

# update layer's extent when new features have been added
# because change of extent in provider is not propagated to the layer
vl.updateExtents()

# add layer to the legend
QgsMapLayerRegistry.instance().addMapLayer(vl)
    
respondido por el Jorge Gil 02.03.2015 - 10:52

Lea otras preguntas en las etiquetas