Если я правильно понимаю логику правильного выбора зеленых линий, нет необходимости создавать KDTree на каждой итерации. Для каждой пары (p1, p2) синих точек линия должна быть проведена тогда и только тогда, когда выполняется следующее:
- p1 является одним из 3 ближайших соседей p2.
- p2 является одним из 3 ближайших соседей p1.
- dist (p1, p2) <55. </li>
Вы можете создать KDTree один раз и эффективно создать список зеленых линий. Вот часть реализации, которая возвращает список пар индексов для точек, между которыми необходимо провести зеленые линии. Время выполнения на моей машине составляет около 0,5 секунд на 10000 баллов.
import numpy as np
from scipy import spatial
data = np.random.randint(0, 1000, size=(10_000, 2))
def get_green_lines(data):
tree = spatial.cKDTree(data)
# each key in g points to indices of 3 nearest blue points
g = {i: set(tree.query(data[i,:], 4)[-1][1:]) for i in range(data.shape[0])}
green_lines = list()
for node, candidates in g.items():
for node2 in candidates:
if node2 < node:
# avoid double-counting
continue
if node in g[node2] and spatial.distance.euclidean(data[node,:], data[node2,:]) < 55:
green_lines.append((node, node2))
return green_lines
Вы можете приступить к построению зеленых линий следующим образом:
green_lines = get_green_lines(data)
fig, ax = plt.subplots()
ax.scatter(data[:, 0], data[:, 1], s=1)
from matplotlib import collections as mc
lines = [[data[i], data[j]] for i, j in green_lines]
line_collection = mc.LineCollection(lines, color='green')
ax.add_collection(line_collection)
Пример вывода: