Search code examples
pythonsimulationvispy

How to pick the nearest marker from clicked point in vispy?


In vispy library I have a list of points shown as markers, and I want to change the color of(or just get the index of) the point which is nearest to the clicked point.

I can get the pixels of the clicked point by event.pos, but i need its actual co-ordinate to compare it with others (or get pixel point of other markers to compare it with the event location).

I have this code to get the nearest point index.which takes input of an array and a point(clicked one)

def get_nearest_index(pos,p0):
    count=0
    col =[(1,1,1,0.5) for i in pos]
    dist= math.inf
    ind=0
    for i in range(len(pos)):
        d = (pos[i][0]-p0[0])**2+(pos[i][1]-p0[1])**2
        if d<dist:
            ind=i
            dist=d
    return ind

But the problem is i have to pass both of them in same co-ordinate system. Printing out event.pos returns pixels like: [319 313] while my positions, in pos array are:

[[-0.23801816  0.55117583 -0.56644607]
 [-0.91117247 -2.28957391 -1.3636486 ]
 [-1.81229627  0.50565064 -0.06175591]
 [-1.79744952  0.48388072 -0.00389405]
 [ 0.33729051 -0.4087148   0.57522977]]

So I need to convert one of them to another. Transformation like

tf = view.scene.transform
p0 = tf.map(pixel_pt)
print(str(pixel_pt) + "--->"+str(p0))

prints out [285 140 0 1]--->[ 4.44178173e+04 -1.60156369e+04 0.00000000e+00 1.00000000e+00] which is nowhere near the points.


Solution

  • When transforming the pixels to your local co-ordinates, you are using transform.map, which according to the vispy tutorial, gives you map co-ordinates. What you need to use is the inverse map.

    You could try doing this:

    tf = view.scene.transform
    point = tf.imap(event.pos)
    print(str(event.pos) + "--->"+str(point))
    

    Likewise, in case you need to transform specific sets of markers, this would be a better approach.

    ct = markers.node_transform(markers.root_node)
    point = ct.imap(event.pos)