patternpythonMinor
Iterate over million points to get unique closest point
Viewed 0 times
millionuniquepointpointsiterategetclosestover
Problem
Let's say we've two parallel galaxies with same amount of stars. What I want to do is to find the nearest neighbour of GalaxyA in GalaxyB. But if that particular neighbour is shared by other star(closer to another GalaxyA star) then look another nearest neighbour. This way we will get unique nearest neighbour for each star.
I've implemented this logic in using 4-5 different algorithms. So far below one is fastest one:
Where pts are GalaxyA stars and targetpts are GalaxyB stars. hou is software dependent module.
More readable code(same as
I've implemented this logic in using 4-5 different algorithms. So far below one is fastest one:
node = hou.pwd()
geo = node.geometry()
pts = geo.points()
targetpts = node.inputs()[1].geometry().points()
if len(targetpts) >= len(pts):
from operator import itemgetter
# add 'uniqueNeighbour' attribute
geo.addAttrib(hou.attribType.Point, 'uniqueNeighbour', -1)
# setup targetpts list
targetptslist = []
targetptslist = [(n, targetpt.position()) for n, targetpt in enumerate(targetpts)]
# get the distance to every point in target geo
for pt in pts:
neardistlist = []
p1 = pt.position()
neardistlist = [(targetptslist[i][0], (p1 - targetptslist[i][1]).length()) for i in range(len(targetptslist))]
# sort the list by min distance
neardistlist.sort(key = itemgetter(1))
# check the neardistlist to see if this point has already been taken then remove this from the targetptslist
nearestpt = (neardistlist[0][0])
for j in range(len(targetptslist)):
ptn = targetptslist[j][0]
if ptn == nearestpt:
del targetptslist[j]
break
if hou.updateProgressAndCheckForInterrupt(): break # respect keyboard interruption
# update 'uniqueNeighbour' attribute
pt.setAttribValue('uniqueNeighbour', nearestpt)
if hou.updateProgressAndCheckForInterrupt(): break # respect keyboard interruption
else:
raise hou.NodeError('Target points must be equal or more than source points!')Where pts are GalaxyA stars and targetpts are GalaxyB stars. hou is software dependent module.
More readable code(same as
Solution
The question doesn't make it clear exactly what your problem is, and so it is hard for us to help you. You are trying to find a matching in a weighted bipartite graph, but what are the conditions on that matching?
-
Are you looking for a stable matching? That is, one where there's no two items that could both be brought closer in the matching by pairing them.
-
Are you looking for a locally minimum matching? That is, one where the sum of distances between the pairs in the matching cannot be reduced by swapping two of the assignments.
-
Are you looking for a globally minimum matching? That is, one where the sum of distances between the pairs in the matching is minimized among all matchings.
The algorithm in your post does not find any of these types of matching. So if we are to believe your code, then any matching will do, in which case why not use the built-in function
-
Are you looking for a stable matching? That is, one where there's no two items that could both be brought closer in the matching by pairing them.
-
Are you looking for a locally minimum matching? That is, one where the sum of distances between the pairs in the matching cannot be reduced by swapping two of the assignments.
-
Are you looking for a globally minimum matching? That is, one where the sum of distances between the pairs in the matching is minimized among all matchings.
The algorithm in your post does not find any of these types of matching. So if we are to believe your code, then any matching will do, in which case why not use the built-in function
zip?Context
StackExchange Code Review Q#140292, answer score: 3
Revisions (0)
No revisions yet.