Как таковой, объект, созданный с помощью вызова plt.annotate
, представляет собой «аннотацию» matplotlib, которая имеет много методов, и ограничивающий прямоугольник, который можно получить, вызвав .get_window_extent()
возвращающего объекта.
Если у вас нет десятков тысяч точек - которые в любом случае не помещались бы на графике такого рода, вы можете просто сохранить эти координаты в списке - и линейно проверять наличие столкновений при добавлении другого объекта. (Для нескольких тысяч объектов это становится недостижимым, и нужно будет использовать стратегию, лучше, чем линейную).
Теперь есть еще одна проблема: что делать, если столкновение произойдет? Более простое решение - просто не отображать метку-нарушителя - но вы можете попытаться немного переместить новую аннотацию, чтобы она не перекрывалась. Это может быть сложно - но если мы выберем простую наивную стратегию, скажем, просто переместим элемент по оси y, пока он больше не будет перекрываться, вы можете получить хороший результат для довольно разреженной карты, даже если с некоторыми исправления.
«Умная» стратегия может собрать все близлежащие ярлыки и попытаться плотно расположить их вместе, что потребует нескольких часов или даже дней работы.
Итак, поскольку у вас нет примера с данными, которые мы можем воспроизвести локально, я напишу «переместить более поздние аннотации вниз по оси y, пока они не будут соответствовать» стратегии. «По крайней мере, вы получите отправную точку .
from matplotlib.transforms import Bbox
...
text_rectangles = []
y_step = 0.05
# This will have far better results if the labels are sorted descending in the y axis -
#
mapa_df1["sort_key"] = [coord[1] for coord in mapa_df1["coords"]]
mapa_df1.sort_values("sort_key", ascending=False, inplace=True)
del mapa_df1["sort_key"]
for idx, row in mapa_df1.iterrows():
text = plt.annotate(s=row['l'], xy=row['coords'])
rect = text.get_window_extent()
for other_rect in text_rectangles():
while bbox.intersection(rect, other_rect): # overlapping
x, y = text.get_position()
text.set_position(x, y - y_step)
rect = text.get_window_extent()
text_rectangles.append(rect)
После этого вы можете получить один из экземпляров Annotation, созданных в интерактивном режиме, и изучить его методы и свойства - можно даже взаимодействовать с указателем в зависимости от серверной части рендеринга, так, например, метки могут быть нарисованы с уровнем прозрачности и стать полностью непрозрачными, когда указатель мыши при этом будет висеть (см. Возможно, чтобы метки появлялись при наведении курсора на точку в matplotlib? , например).