Search code examples
pythonnumpymatrixangle

Find nearest item given an angle in 2D numpy array


Given a numpy 2D array, what would be the best way to get the nearest item (for this example '1') from a specified coordinate (where 'X' is located) given an angle.

For example, lets say we have 'X' located at (1,25) in a 2D array shown below. Say with an angle 225 degrees, assuming 0 degrees goes straight to the right and 90 degrees goes straight up. How can I get the nearest coordinate of a '1' located towards that vector direction?

[
0000000000000000000000000000
0000000000000000000000000X00
0000000000000000000000000000
1110000000000000000000000000
1111100000000000000000000000
1111110000000000000000000000
1111111000000000000000000000
1111111110000000000000000000
1111111111100000000000000000
]

Solution

  • I'm assuming by towards that direction you mean something like on that ray. In that case 255° has no solution so I took the liberty of changing that to 195°.

    You could then brute-force it:

    import numpy as np
    
    a = """
    0000000000000000000000000000
    0000000000000000000000000X00
    0000000000000000000000000000
    1110000000000000000000000000
    1111100000000000000000000000
    1111110000000000000000000000
    1111111000000000000000000000
    1111111110000000000000000000
    1111111111100000000000000000
    """
    
    a = np.array([[int(i) for i in row] for row in a.strip().replace('X', '2').split()], dtype=np.uint8)
    
    x = np.argwhere(a==2)[0]
    y = np.argwhere(a==1)
    d = y-x
    
    phi = 195 # 255 has no solutions
    
    on_ray = np.abs(d@(np.sin(np.radians(-phi-90)), np.cos(np.radians(-phi-90))))<np.sqrt(0.5)
    
    show_ray = np.zeros_like(a)
    show_ray[tuple(y[on_ray].T)] = 1
    print(show_ray)
    
    ymin=y[on_ray][np.argmin(np.einsum('ij,ij->i', d[on_ray], d[on_ray]))]
    print(ymin)
    

    Output:

    # [[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
    #  [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
    #  [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
    #  [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
    #  [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
    #  [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
    #  [0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
    #  [1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
    #  [1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
    # [6 6]