3

I am trying to find all points in a vector layer that do not have a duplicate point.

To do this, for each point I create a list of features that intersect its bounding box ('candidates') then check if any candidate is an exact geometry match. I've included the exact code below.

However, no matter how I tweak the code I don't end up with any duplicate points. I know for a fact there are many duplicate points (various topology checks and knowledge of dataset) so there's something wrong.

Is this an issue with using the bounding box, or another part of my code?

I'm using Python because every existing tool I've found only flags duplicates, but tool suggestions are fine too.

Working with QGIS 3.4x64 and Python 3.7 on Windows 10.

geoms = {} # { vertex id : geom }

for v in point_layer.getFeatures():
    if not v.hasGeometry():
        continue

    geoms[v.id()] = v.geometry() 

index = QgsSpatialIndex()
no_dup = [] #list of vertex IDs with no duplicates 
    for v_id, geometry in geoms.items():
    candidates = index.intersects(geometry.boundingBox()) 
    duplicates = [] 

    for candidate_id in candidates:
        if geometry.isGeosEqual(geoms[candidate_id]):
            duplicates.append(v_id)

    if len(duplicates) == 1: #only one point in location
        no_dup.append(v_id)

Note: I considered creating a buffer instead of using the boundary box but I have over 100k features and would prefer not to create another layer

2 Answers 2

3

Solved: I hadn't populated the QgsSpatialIndex properly.

index = QgsSpatialIndex()
geoms = {} # { vertex id : geom }
for v in point_layer.getFeatures():
    if not v.hasGeometry():
        continue

    geoms[v.id()] = v.geometry() #pop vertex geoms dict
    index.addFeature(v)
1

You could use equals() :

geoms = {}

point_layer = iface.activeLayer()
for v in point_layer.getFeatures():
    if not v.hasGeometry():
        continue
    geoms[v.id()] = v.geometry() 

no_dup = []
for v_id1, geom1 in geoms.items():
    i = 0
    for v_id2, geom2 in geoms.items():
        if v_id1 != v_id2 and geom1.equals(geom2):
            i += 1
    if i == 0:
        no_dup.append(v_id)

print('nb {}'.format(len(no_dup)))

See How to check if two qgsPoints are equal in PyQgis

2
  • You can replace geom1.equals(geom2) by geom1.intersects(geom1.buffer(10, 12))) if you want to check equality within a 10 meters buffer (without creating any layer). Check QGIS API to discover available QgsGeometry methods : qgis.org/api/classQgsGeometry.html
    – sigeal
    Feb 12, 2019 at 19:58
  • 1
    I need to compare 100k+ points, if I use .equals() on so many features QGIS crashes.
    – jyingling
    Feb 12, 2019 at 20:12

Your Answer

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

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