I am trying to implement the Jump Flooding algorithm to draw a Voronoi diagram from an array of points. The code below works correctly but is extremely slow for large N. The reason it is slow is that there is a loop that adds new information to an array being iterated. This array lists neighbor points. If I do not include this appending, the Voronoi diagram is nonsensical, with most points not being reached by the algorithm. I don't understand why a simple sweep through neighbors identified in the original neighbor search doesn't hit all the points on the grid. Can you suggest what is wrong with my code and if there is a performant alternative to appending all found neighbors to a gigantic array? Or is this perhaps simply a python problem and rewriting in C/C++ etc. will fix the performance issue?
import matplotlib.pyplot as plt
import numpy as np
from time import time
# array = np.zeros((5, 5))
# originalSeeds = {1: [2, 2], 2: [4, 1], 3: [0, 4]}
array = np.zeros((10, 10))
originalSeeds = {1: [2, 2], 2: [4, 1], 3: [0, 4]}
# array = np.zeros((200, 200))
# originalSeeds = {1: [20, 20], 2: [40, 10], 3: [0, 40]}
for key, value in originalSeeds.items():
array[value[0], value[1]] = key
seeds = {1: [], 2: [], 3: []}
# this is constantly updated list of neighbors
colors = [1, 2, 3]
colorvalues = {1: 1, 2: 2, 3: 3}
# plt.imshow(array)
# plt.show()
start = time()
step = 2**(int(np.log2(array.shape[0])))
def distance(crd1, crd2):
return np.linalg.norm(crd1 - crd2)
while step >= 1:
for color in colors:
originalSeedCoords = originalSeeds[color]
# neighbor displacments
disp = step * np.array([[1, 1], [0, 1], [-1, 1], [1, -1], [1, 0], [-1, -1], [0, -1], [-1, 0]])
for element in disp:
center = originalSeeds[color]
idx = center + np.array(element)
if idx[0] > array.shape[0] - 1 or idx[1] > array.shape[1] - 1 or idx[0] < 0 or idx[1] < 0:
continue
else:
if array[idx[0], idx[1]] == color:
continue
elif array[idx[0], idx[1]] == 0:
array[idx[0], idx[1]] = colorvalues[color]
seeds[color].append(list(idx))
else:
currColor = array[idx[0], idx[1]]
if distance(idx, originalSeeds[color]) < distance(idx, originalSeeds[currColor]):
array[idx[0], idx[1]] = colorvalues[color]
seeds[color].append(list(idx))
else:
array[idx[0], idx[1]] = colorvalues[currColor]
seeds[currColor].append(list(idx))
for color in colors:
for seed in seeds[color]: # this list may grov during iteration, filling in uncharted points
for element in disp:
center = seed
idx = center + np.array(element)
if idx[0] > array.shape[0] - 1 or idx[1] > array.shape[1] - 1 or idx[0] < 0 or idx[1] < 0:
continue
else:
if array[idx[0], idx[1]] == color:
continue
elif array[idx[0], idx[1]] == 0:
array[idx[0], idx[1]] = colorvalues[color]
if list(idx) not in seeds[color]:
seeds[color].append(list(idx))
else:
currColor = array[idx[0], idx[1]]
if distance(idx, originalSeeds[color]) < distance(idx, originalSeeds[currColor]):
array[idx[0], idx[1]] = colorvalues[color]
if list(idx) not in seeds[color]:
seeds[color].append(list(idx))
else:
array[idx[0], idx[1]] = colorvalues[currColor]
if list(idx) not in seeds[currColor]:
seeds[currColor].append(list(idx))
step = step // 2
# step -= 1