annotate text to axes and align as a circle

半腔热情 提交于 2021-01-28 07:58:42

问题


I am trying to plot text on axes and align this text to a circle.

More precisely there are points with different coordiantes (x,y) which are located inside this circle and created with:

ax.scatter(x,y,s=100)

I want to connect and label each point (Cnameb) with the circle. The coordinates of the text are defined with (xp,yp).

Thus the arrows between the points and the circle are different in length but the overall distance between the center and the circle is the same as the following figure shows --> (Note: the blue lines are the lines which should be printed between the points and the circle. The red lines are just for illustration.):

Because I have defined the radius and I know the coordinates of the points as well as the coordinates of the center point, I should be able to do the following steps:

  1. Calculate the distance DxMP between the single points and the center
  2. Calculate the distance between the the single points and the circle
  3. Calculate the angle alpha
  4. Calculate the points xp and yp which should be the coordinates of the text (the coordinates on the circle)

Wherefore I used the following code:

def legpoints(x,y):
    DxMP = np.sqrt(((x - 521953) ** 2) + (y - 435179) ** 2)#521953, 435179 are the x and y coordinates of the center of the circle
    DxCirc = np.sqrt((900000 - DxMP)**2)#The distance between the point x and the circle
    alpha = np.arccos((np.sqrt((x - 521953)**2)) / (DxMP))
    xp = x + (np.cos(alpha) * DxCirc) 
    yp = y + (np.sin(alpha) * DxCirc)
    return xp,yp


xp=legpoints(x,y)[0]
yp=legpoints(x,y)[1]

The zipped data have the shape (Cnameb,x,y,xp,yp):

[('Berlin', 735951.59991561132, 617707.36153527966, 1206703.3293253453, 1019231.2121256208), ('Berlin', 735965.58122088562, 617712.48195467936, 1206714.0793803122, 1019218.6083879157), ('Bremen', 425896.14258295257, 673875.68843362806, 665833.6191604546, 1270108.8219153266), ('Dortmund', 330448.62508515653, 502638.58154814231, 987816.52265995357, 734203.8568234311), ('Duisburg', 281456.9370223835, 495636.46544709487, 913803.62749559013, 654599.89177739131), ('Düsseldorf', 283849.70917473407, 471649.47447504522, 935371.04632360162, 571443.52693890885), ('Essen, Ruhr', 298590.41880710673, 497973.49884993531, 941640.19382135477, 678755.74152428762), ('Frankfurt am Main', 412037.5979210182, 345052.92773266998, 998077.35579369171, 825581.23014117288), ('Hamburg', 505147.96843631176, 726635.42284052074, 540149.82358692121, 1333686.6774791477), ('Hannover', 487540.73893698538, 594957.33199132804, 642620.87620513374, 1315004.3411755674), ('Köln', 292146.52126941859, 439340.70884408138, 962192.49751825235, 451474.98930779565), ('München', 623290.92919537693, 125422.12264187855, 801795.74103644479, 671052.90026201855), ('Stuttgart', 445743.44744934322, 196109.08652145317, 642879.16415181267, 814525.24510293454)]

With the following code I want to add the text to the axes and allign as a circle:

[ax.annotate(s=nme,xy=(x,y),xytext=(xpoint,ypoint),textcoords="data",arrowprops={"arrowstyle":"->"},color="black",alpha=0.8,fontsize=12) for nme,x,y,xpoint,ypoint in zip(Cnameb,x,y,xp,yp)]

But the result is not as desired because the text is not alligned as circle but undefined....

Can anybody help me please...?


回答1:


I don't see what the distance would do in the equation. You want to determine the point at which to locate the annotation and give this point to the annotation function.

import numpy as np
import matplotlib.pyplot as plt

texts=["Dresden","Berlin", "Freiburg"]
xy = np.array([[3.5,1],[3.,2.],[0,-2]])

center = np.array([1.,1.])
radius = 5 # radius

x,y = zip(*xy)
cx, cy = center
plt.scatter(x,y)
plt.scatter(cx, cy)

#plot a cirle
ct = np.linspace(0,2*np.pi)
circx, circy = radius*np.cos(ct)+cx, radius*np.sin(ct)+cy
plt.plot(circx, circy, ls=":")



def ann(x,y, cx, cy, r, text):
    angle = np.arctan2(y-cy, x-cx)
    xt, yt = r*np.cos(angle)+cx, r*np.sin(angle)+cy
    plt.annotate(text, xy=(x,y), xytext=(xt, yt), arrowprops={"arrowstyle":"->"})
    plt.scatter(xt, yt, c=0)

for t, xi,yi in zip(texts, x,y):
    ann(xi,yi, cx, cy, radius, t)

plt.gca().set_aspect("equal")
plt.show()



来源:https://stackoverflow.com/questions/44763978/annotate-text-to-axes-and-align-as-a-circle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!