This SO question provides some help in order to keep annotations from overlapping on each other, but it just stacks the annotations upwards instead of keeping it as close to possible to the (x,y) position it was supposed to be at. Now it just stacks things straight up to where their original x,y position is meaningless.
The relevant part is this:
def get_text_positions(x_data, y_data, txt_width, txt_height):
a = zip(y_data, x_data)
text_positions = y_data.copy()
for index, (y, x) in enumerate(a):
local_text_positions = [i for i in a if i[0] > (y - txt_height)
and (abs(i[1] - x) < txt_width * 2) and i != (y,x)]
if local_text_positions:
sorted_ltp = sorted(local_text_positions)
if abs(sorted_ltp[0][0] - y) < txt_height: #True == collision
differ = np.diff(sorted_ltp, axis=0)
a[index] = (sorted_ltp[-1][0] + txt_height, a[index][1])
text_positions[index] = sorted_ltp[-1][0] + txt_height
for k, (j, m) in enumerate(differ):
#j is the vertical distance between words
if j > txt_height * 2: #if True then room to fit a word in
a[index] = (sorted_ltp[k][0] + txt_height, a[index][1])
text_positions[index] = sorted_ltp[k][0] + txt_height
break
return text_positions
I think the magic is happening at the line j > txt_height
, but I want to start moving things left and right if there is overlap.
Edit: I did not adjust anything from the outer for loop, because it looks to be calculating if any of the text positions are in the same 'neighborhood'. if local_text_positions: then runs if any of them are overlapping. np.diff is taking the first order difference... but I don't know what is going on after the j>txt_height like I mentioned in the question.