1

Is there a way to select all features of a single layer which intersect each other and share the same attribute values?

1 Answer 1

2

Copy the Python code below into Python console or run it from editor window.

Using the active layer the script first finds all unique attribute combinations, and assigns the features to these groups. Field names, that should not be included in the groups, can be specified in list ignore_fields. Values in these fields are ignored, neither unique nor not.

Then it checks group by group, if unique combinations of 2 features intersect. If they intersect, then their ids are saved. Finally all features with their ids in the list are selected.

from itertools import combinations

# get layer
layer = iface.activeLayer()
prov = layer.dataProvider()

# declare dictionary holding unique attribut groups
attr_dict = {}

# fields not to include in grouping
ignore_fields = ['gid']  # eg ['gid']
ignore_fni = [prov.fieldNameIndex(i) for i in ignore_fields]
ignore_fni.sort(reverse=True)

# find all unique attribute groups and link them to a list of feature ids
for feat in prov.getFeatures():
    # get attributes
    attr_list = feat.attributes()
    # remove attributes to be ignored
    for fni in ignore_fni:
        attr_list.pop(fni)
    # convert list to hashable type
    tup = tuple(attr_list)
    # if in dict, append fid to list, else add to dict
    if tup in attr_dict:
        attr_dict[tup].append(feat.id())
    else:
        attr_dict[tup] = [feat.id()]

# set for all features intersecting with some other feature
intersecting = set([])

# for each group
for key, value in attr_dict.iteritems():
    # get all unique combination of 2 features
    pairs = [comb for comb in combinations(value, 2)]

    # check if these 2 features intersect
    for pair in pairs:
        pair = list(pair)
        request = QgsFeatureRequest().setFilterFids(pair)
        features = prov.getFeatures(request)
        f1 = features.next()
        f2 = features.next()

        # if they intersect save their ids to the set
        if f1.geometry().intersects(f2.geometry()):
            intersecting.update(pair)

# finally select all features intersecting with 
# another feature of the same group
layer.setSelectedFeatures(list(intersecting))

Test case: lines having 3 attributes, first numeric, second text, and a third which should be excluded from grouping (shown in brackets)

Intersecting lines

7
  • Thank you, but unfortunately this isn't working: File'"<input>", line 1 for pair in pairs: ^ IndentationError: unexpected indent'
    – Lunar Sea
    Commented Apr 4, 2016 at 18:37
  • Each indent you can see in the code has to be a multiple of 4 blanks.
    – Detlev
    Commented Apr 4, 2016 at 19:07
  • I've copied the code into LibreOffice Writer and every indent has 4, 8 or 12 blanks. I don't have any Python experience.
    – Lunar Sea
    Commented Apr 4, 2016 at 20:20
  • Try without the empty lines, but this is usually no problem. Why don't you use the editor of python console in Qgis? It is easy to use and integrated in Qgis. Thats where I build the code.
    – Detlev
    Commented Apr 4, 2016 at 20:28
  • Thanks, everything works fine in the editor. Is there a way to select intersecting features with different gid (primary key) values but sharing the same attributes?
    – Lunar Sea
    Commented Apr 4, 2016 at 20:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.