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

PolyGeo
65.5k29 gold badges115 silver badges350 bronze badges
asked Feb 12, 2019 at 17:45

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)
answered Feb 12, 2019 at 20:51
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

answered Feb 12, 2019 at 18:54
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 Commented Feb 12, 2019 at 19:58
  • 1
    I need to compare 100k+ points, if I use .equals() on so many features QGIS crashes. Commented Feb 12, 2019 at 20:12

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.