Как подключить событие к matplotlib.collections.PatchCollection - PullRequest
0 голосов
/ 21 марта 2020

Используя matplotlib.collections.PatchCollection, я создал диаграмму, которая показывает сетку шестиугольников: hexagons

Теперь я хочу сделать график интерактивным, т.е. добавить некоторую форму обработки событий. В частности, я хочу иметь возможность навести курсор на любой из шестиугольников и, когда я это сделаю, я хочу залить все соседние шестиугольники определенным цветом.

Но давайте начнем с простого: как я могу подключить патч, то есть шестиугольник, к событию?

Я сохранил координаты центра каждого шестиугольника в массиве numpy. Итак, мне нужен способ сообщить мне индекс шестиугольника, на который я нажал, или мой курсор в данный момент закончен. Всего 100 шестиугольников. Когда я нажимаю на шестигранник № 43, мне просто нужно получить этот индекс, а затем, я думаю, я знаю, как определить расстояние до всех соседей. Но как мне получить этот индекс?

Кто-нибудь знает?

1 Ответ

1 голос
/ 21 марта 2020

PatchCollection, как и все коллекции, обладает свойством contains(), которое может указывать, для какого члена коллекции (если есть) было инициировано событие.

Единственный «трюк» заключается в том, что вы должны убедиться, что изначально у вас есть массив лицевых красок, размер которого совпадает с количеством членов в вашей коллекции, иначе все станет грязно. Здесь я использую PathCollection.set_facecolors() после создания, чтобы убедиться в этом.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle
from matplotlib.collections import PatchCollection


def hover(event):
    if event.inaxes == ax:
        cont, ind = p.contains(event)
        if cont:
            idx = ind['ind'][0]
            colors = p.get_facecolors()
            colors[idx] = highlight_color
            p.set_facecolors(colors)
        else:
            p.set_facecolors([default_color] * N)
    fig.canvas.draw()


default_color = (0, 0, 1, 1)
highlight_color = (1, 0, 0, 1)

N = 10
r = 1
x, y = np.random.randint(10, 50, size=(2, N))
patches = [Circle((xi, yi), r) for xi, yi in zip(x, y)]
p = PatchCollection(patches)
p.set_facecolors([default_color] * N)

fig, ax = plt.subplots()
ax.add_collection(p)
ax.set_xlim(0, 50)
ax.set_ylim(0, 50)

fig.canvas.mpl_connect("motion_notify_event", hover)

plt.show()
...