HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Iterate over million points to get unique closest point

Submitted by: @import:stackexchange-codereview··
0
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:

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 zip?

Context

StackExchange Code Review Q#140292, answer score: 3

Revisions (0)

No revisions yet.