I have a workflow to eliminate small polygons within a layer and merge them with adjacent polygons. My input is the result of a polygonization of a raster (has no overlaps) and it has one field "class".
Input:
In the first step I loop over all features and if a polygon is of class 0 (blue), and is too small, i change its class to a suitable neighbour.
Next I dissolve the features, according to their changed class values.
As you can see, the blue areas are dissolved successfully, however the island in the middle appears to have changed value. Actually there are now two polygons laying on top of each other there, a light green one, and the original one. The light green basically filled a hole during the dissolve process. This happens only for a couple of polygons, and not all of them.
Here's the code to change the values of the polygons:
def KFB_for_1_class (input, field_, c, area_threshold):
feats = []
dis_temp = r"z:\dis.shp"
layer = iface.addVectorLayer(input,"","ogr")
layer.startEditing()
layer_cpy = iface.addVectorLayer(input,"","ogr")
print "cleaning class "+str(c)
for f in layer.getFeatures():
if f[field_] == c and f["area"] < area_threshold:
org_int = f[field_]
candidates = []
for f2 in layer_cpy.getFeatures():
if f.geometry().touches(f2.geometry()):
if f2[field_] not in candidates and f2[field_] != org_int:
candidates.append(f2[field_])
candidates.sort()
if len(candidates) >0:
f[field_] = candidates[0]
for i in (candidates):
if abs(org_int - i) <= abs(f[field_] - org_int):
f[field_] = i
f["area"] = area_threshold + 1
layer.updateFeature(f)
feats.append(f["id"])
print "feature " +str(f["id"]) + " changed from " + str(org_int) + " to " + str(f["int"])
print feats
layer.commitChanges()
To dissolve I use this:
processing.runalg("qgis:dissolve", input, False , "class", dis_temp)
What I tried:
- using other dissolve tools within QGis (OGR, SAGA, [GRASS I could not get to work])
- cleaning Topology with v.clean according to Dissolve polygons in QGIS (GEOS) with tolerance
Both did not work. The different tools all ended up creating the same error.
How can I resolve this?