5

I'm trying to implement / reuse Add Feature functionality in my python plugin. there a class/function that handles geometry creation on canvas based on layer geometry definition? I'm checking API but I can't find a function that gives you functionality to digitize geometry and pass it as a feature to layer - or something similar.

I managed to get layer to editing mode now I can't find a way to implement this.

So basically ---> enter image description here with PyQGIS API.

menes
  • 1,421
  • 2
  • 7
  • 24
Greg
  • 521
  • 1
  • 5
  • 14
  • 1
    So you want users to digitize new features which are then added to an existing vector? – BritishSteel Apr 03 '15 at 13:20
  • Yes. I can't find a function to do that. – Greg Apr 03 '15 at 13:24
  • 1
    Have you looked up the word rubberband in relation to PyQGIS? That might get you on the right track. – BritishSteel Apr 03 '15 at 13:26
  • I found QgsRubberBand(self.canvas, QGis.Polygon) I hope I figure out how it works. Thanks for pointers :) – Greg Apr 03 '15 at 13:38
  • I'll go and check rubberband and QgsMapTool functionality. I think implementing your own geometry creaton tool is a hard way to such a simple goal... – Greg Apr 03 '15 at 13:54
  • I just found a way to add geometries to an existing file. I will add it as an answer within the next minutes. It might turn out to be useful, although you would have to add some things to it, to make it fully work your way. – BritishSteel Apr 03 '15 at 13:57
  • @Greg Did you find a solution to this? If you could answer your own question that would be a great help. – Matt Jun 24 '15 at 14:19
  • No I couldn't find a solution for this unfortunately. I still think this could be a great feature to add... – Greg Jul 13 '15 at 10:55

3 Answers3

8

I spent a while trying to figure this out too.

The button is found in the QgisInterface class.

# Find the layer to edit
layer = qgis.utils.iface.activeLayer()
layer.startEditing()
# Implement the Add Feature button
qgis.utils.iface.actionAddFeature().trigger()

Then add the features you wish to add to the layer.

Nicola
  • 183
  • 2
  • 6
6

A complete solution with also saving the layer, as requested in a comment:

# Get the active layer
layer = iface.activeLayer()

# Define a function called when a feature is added to the layer
def feature_added():

    # Disconnect from the signal
    layer.featureAdded.disconnect()

    # Save changes and end edit mode
    layer.commitChanges()

# Connect the layer to the signal featureAdded, so when a feature is
# added to the layer, the feature_added function is called    
layer.featureAdded.connect(feature_added)

# Set the layer in edit mode
layer.startEditing()

# Activate the QGIS add feature tool
iface.actionAddFeature().trigger()
Marioba
  • 356
  • 2
  • 7
2

Here would be a way to add a new feature to a polygon vector:

# reference your layer, such as the active layer
lyr = iface.activeLayer()

# get the vertexes of your new geometry and add them to a list
coordinatePairs = []
coordinatePairs.append(QgsPoint(-80.23, -3.28))
coordinatePairs.append(QgsPoint(-65.58, -4.21))
coordinatePairs.append(QgsPoint(-65.87, 9.50))
coordinatePairs.append(QgsPoint(-80.10, 10.44))

# create a polygon using the above coordinates
newPolygon = QgsGeometry.fromPolygon([coordinatePairs])

# create a feature, add the polygon to it
feature = QgsFeature()
feature.setGeometry(newPolygon)

# access the layer"s data provider, add the feature to it
dataProvider = lyr.dataProvider()
dataProvider.addFeatures([feature])

# refresh map canvas to see the result
iface.mapCanvas().refresh()

With my comments I think this should be pretty self-explanatory.

In this case you would not even have to start an edit session, and you would write this feature directly to the file, which might not exactly be what you are trying to implement.

Either way, what is now missing is that the points that are appended to this list, are not hard-coded but are actually coming from the user. You would therefore have to combine all of this with a click event that gets the coordinates on click and appends them to the list. Since this is all done via a plugin I would also suggest you add a button that lets you start the editing (i.e. setting new points) and lets you stop it (so a button that allows toggling, like the typical "Add Feature" button, but you could surely add two separate buttons as well). The button functionality would, of course, come from PyQt, and then reference to your PyQGIS functions. You also might want to add a line that combines each single point that is set to be used as a vertex. Although optional, that would greatly enhance the user experience.

The above example, by the way, would create a polygon that more or less hides Colombia:

enter image description here

PS: for inspiration I looked at the PyQGIS Cookbook that was released by Packt Pub a few days ago.

BritishSteel
  • 6,637
  • 4
  • 38
  • 64
  • 1
    Yes I know I can do this by defining points and group them into geometry (polygon). That's exactly what I'm trying to avoid. I'd like user to create polygons by clicking on map canvas to preview geometry. Thanks for your comment. I'm sure someone will find it useful. – Greg Apr 03 '15 at 14:22
  • Hi @Greg, I'm trying to do the same thing as you. Did you find how to use the "Add Feature" tool programmatically ? – kaycee Aug 16 '16 at 16:37