1

Given a list of points obstacles (given as a list of row, column matrix coordinates, an ndarray of shape (n, 2)), return a map of size size (where size is the shape of the 2D NumPy array) in which the value of r, c is the Euclidean distance to the closest "obstacle."

def gen_distgrid(size, obstacles):
    n_obstacles = obstacles.shape[0]
    distgrids = np.zeros((n_obstacles + 4, size[0], size[1]))
    for layer in range(n_obstacles):
        for i in range(size[0]):
            for j in range(size[1]):
                distgrids[layer, i, j] = np.linalg.norm(obstacles[layer,:] - [i,j])
    for i in range(size[0]):
            for j in range(size[1]):
                distgrids[n_obstacles + 0, i, j] = i
                distgrids[n_obstacles + 1, i, j] = (size[0] - i)
                distgrids[n_obstacles + 2, i, j] = j
                distgrids[n_obstacles + 3, i, j] = (size[1] - j)
    distgrid = np.min(distgrids, axis=0)
    return distgrid

My method is really slow, and I feel like there should be a better one.

Simon Kuang
  • 3,715
  • 4
  • 24
  • 53

2 Answers2

0

Here is a solution to a similar problem using a KD-tree with Numpy and SciPy. Just insert your obstacles into the KD-tree and query the tree for each grid point to get its nearest neighbor.

Community
  • 1
  • 1
dpmcmlxxvi
  • 1,212
  • 1
  • 9
  • 12
0

I ended up using a KD-tree from SciPy. It has a very easy distance function.

from scipy.spatial import cKDTree as KDTree
def gen_distgrid(obstacles):
    n_obstacles = obstacles.shape[0]
    obstacles = np.vstack((obstacles, [0,0], [0, size[1] - 1], [size[0] - 1, 0], [size[0] - 1, size[1] - 1]))

    distgrid = np.zeros((size[0], size[1]))
    obs_tree = KDTree(data=obstacles)

    i_v = np.arange(size[0])
    j_v = np.arange(size[1])

    coordmat = np.dstack(np.meshgrid(i_v, j_v, indexing='ij'))
    obs_dists, obs_locs = obs_tree.query(coordmat)

    top_dists = np.repeat(i_v, size[1]).reshape(size)
    bottom_dists = np.repeat(size[0] - i_v, size[1]).reshape(size)
    left_dists = np.repeat(j_v, size[0]).reshape(np.transpose(size)).T
    right_dists = np.repeat(size[1] - j_v, size[0]).reshape(np.transpose(size)).T

    dists = np.min([obs_dists, top_dists, bottom_dists, left_dists, right_dists], axis=0)
    return dists
Simon Kuang
  • 3,715
  • 4
  • 24
  • 53