Tuesday, 20 August 2019

vector - How can I programatically create and add features to a memory layer in QGIS 1.9?


I had a working plugin in QGIS 1.8 which read data from an MSAccess database and added it to a series of memory layers. There is some processing involved in the interim so I don't think simply using QGIS to read directly from the database is an option.


I would like to move from QGIS 1.8 to 1.9 (primarily due to the improved quality of the print composer). The plugin doesn't work with the new API.


I've tried a variety of methods that came up in google searches. One, modifying the below code - from http://www.qgis.org/pyqgis-cookbook/vector.html#memory-provider, i.e. adding geometry and attributes to the dataprovider and then updating the layer - to suit the new API worked a little but the attributes were not visible until I manully entered editing mode (similar to http://hub.qgis.org/issues/3713). An alternative approach, detailed in reply #1 of the above link, added the layer and attributes correctly but I was unable to add features to the layer.


Given that it should be a pretty simple task I'm hopeful that someone on here can offer a working example of how this should be done. (P.S. I am not a professional programmer and most of my coding is fairly crude - I welcome any guidance but ask that you excuse some ignorance on my part)


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


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...