Как сделать стрелку, которая петли в matplotlib?
Каков правильный способ рисовать стрелку, которая возвращается назад, чтобы указать на ее начало в matplotlib? я попробовал:
plt.figure()
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.annotate("", xy=(0.6, 0.9),
xycoords="figure fraction",
xytext = (0.6, 0.8),
textcoords="figure fraction",
fontsize = 10, \
color = "k",
arrowprops=dict(edgecolor='black',
connectionstyle="angle,angleA=-180,angleB=45",
arrowstyle = '<|-',
facecolor="k",
linewidth=1,
shrinkA = 0,
shrinkB = 0))
plt.show()
это не дает правильного результата:
![arrow]()
Аргументы connectionstyle
трудно выполнить с этой страницы (http://matplotlib.org/users/annotations_guide.html).
Я ищу что-то вроде this или this:
![loopy arrow]()
update: ответ, связанный с не показывает, как это сделать с plt.annotate
, у которого есть другие функции, которые я хочу использовать. предложение использовать маркер $\circlearrowleft$
не является реальным решением.
Ответы
Ответ 1
Кажется, что самый простой способ создать легко изменяемую стрелку цикла - использовать patches. Я вставил код, чтобы сделать это ниже. Измените переменные в разделе переменных, и все должно вращаться и масштабироваться. Вы можете играть с патчем, который создает голову стрелки, чтобы сделать другую форму, хотя я подозреваю, что этот треугольник будет самым простым.
%matplotlib inline
# from __future__ import division #Uncomment for python2.7
import matplotlib.pyplot as plt
from matplotlib.patches import Arc, RegularPolygon
import numpy as np
from numpy import radians as rad
fig = plt.figure(figsize=(9,9))
ax = plt.gca()
def drawCirc(ax,radius,centX,centY,angle_,theta2_,color_='black'):
#========Line
arc = Arc([centX,centY],radius,radius,angle=angle_,
theta1=0,theta2=theta2_,capstyle='round',linestyle='-',lw=10,color=color_)
ax.add_patch(arc)
#========Create the arrow head
endX=centX+(radius/2)*np.cos(rad(theta2_+angle_)) #Do trig to determine end position
endY=centY+(radius/2)*np.sin(rad(theta2_+angle_))
ax.add_patch( #Create triangle as arrow head
RegularPolygon(
(endX, endY), # (x,y)
3, # number of vertices
radius/9, # radius
rad(angle_+theta2_), # orientation
color=color_
)
)
ax.set_xlim([centX-radius,centY+radius]) and ax.set_ylim([centY-radius,centY+radius])
# Make sure you keep the axes scaled or else arrow will distort
drawCirc(ax,1,1,1,0,250)
drawCirc(ax,2,1,1,90,330,color_='blue')
plt.show()
![введите описание изображения здесь]()
Ответ 2
Я не нахожу никакого способа сделать цикл, используя plt.annotate
только один раз, но используя его четыре раза работает:
import matplotlib.pyplot as plt
fig,ax = plt.subplots()
# coordinates of the center of the loop
x_center = 0.5
y_center = 0.5
radius = 0.2
# linewidth of the arrow
linewidth = 1
ax.annotate("", (x_center + radius, y_center), (x_center, y_center + radius),
arrowprops=dict(arrowstyle="-",
shrinkA=10, # creates a gap between the start point and end point of the arrow
shrinkB=0,
linewidth=linewidth,
connectionstyle="angle,angleB=-90,angleA=180,rad=10"))
ax.annotate("", (x_center, y_center - radius), (x_center + radius, y_center),
arrowprops=dict(arrowstyle="-",
shrinkA=0,
shrinkB=0,
linewidth=linewidth,
connectionstyle="angle,angleB=180,angleA=-90,rad=10"))
ax.annotate("", (x_center - radius, y_center), (x_center, y_center - radius),
arrowprops=dict(arrowstyle="-",
shrinkA=0,
shrinkB=0,
linewidth=linewidth,
connectionstyle="angle,angleB=-90,angleA=180,rad=10"))
ax.annotate("", (x_center, y_center + radius), (x_center - radius, y_center),
arrowprops=dict(arrowstyle="-|>",
facecolor="k",
linewidth=linewidth,
shrinkA=0,
shrinkB=0,
connectionstyle="angle,angleB=180,angleA=-90,rad=10"))
plt.show()
![введите описание изображения здесь]()
Ответ 3
Попробуйте следующее:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_xlim(1,3)
ax.set_ylim(1,3)
ax.plot([2.5],[2.5],marker=r'$\circlearrowleft$',ms=100)
plt.show()
![введите описание изображения здесь]()
Ответ 4
В моем предложении используется только команда plot
import matplotlib.pyplot as plt
import numpy as np
def circarrowdraw(x0, y0, radius=1, aspect=1, direction=270, closingangle=-330,
arrowheadrelativesize=0.3, arrowheadopenangle=30, *args):
"""
Circular arrow drawing. x0 and y0 are the anchor points.
direction gives the angle of the circle center relative to the anchor
in degrees. closingangle indicates how much of the circle is drawn
in degrees with positive being counterclockwise and negative being
clockwise. aspect is important to make the aspect of the arrow
fit the current figure.
"""
xc = x0 + radius * np.cos(direction * np.pi / 180)
yc = y0 + aspect * radius * np.sin(direction * np.pi / 180)
headcorrectionangle = 5
if closingangle < 0:
step = -1
else:
step = 1
x = [xc + radius * np.cos((ang + 180 + direction) * np.pi / 180)
for ang in np.arange(0, closingangle, step)]
y = [yc + aspect * radius * np.sin((ang + 180 + direction) * np.pi / 180)
for ang in np.arange(0, closingangle, step)]
plt.plot(x, y, *args)
xlast = x[-1]
ylast = y[-1]
l = radius * arrowheadrelativesize
headangle = (direction + closingangle + (90 - headcorrectionangle) *
np.sign(closingangle))
x = [xlast +
l * np.cos((headangle + arrowheadopenangle) * np.pi / 180),
xlast,
xlast +
l * np.cos((headangle - arrowheadopenangle) * np.pi / 180)]
y = [ylast +
aspect * l * np.sin((headangle + arrowheadopenangle) * np.pi / 180),
ylast,
ylast +
aspect * l * np.sin((headangle - arrowheadopenangle) * np.pi / 180)]
plt.plot(x, y, *args)
Чтобы проверить это:
plt.figure()
plt.plot(np.arange(10)**2, 'b.')
bb = plt.gca().axis()
asp = (bb[3] - bb[2]) / (bb[1] - bb[0])
circarrowdraw(6, 36 , radius=0.4, aspect=asp, direction=90)
plt.grid()
plt.show()
![введите описание изображения здесь]()
Ответ 5
Другая возможность - использовать tikz для создания фигуры:
\documentclass {minimal}
\usepackage {tikz}
\begin{document}
\usetikzlibrary {arrows}
\begin {tikzpicture}[scale=1.8]
\draw[-angle 90, line width=5.0mm, rounded corners=20pt]
(0.25,0)-- (1.0, 0.0) -- (1.0, -3.0) -- (-3.0, -3.0) -- (-3.0, 0) --(-1,0);
\end{tikzpicture}
\end{document}
Это результат:
![введите описание изображения здесь]()
в matplotlib есть бэкэнд pgf/tikz, который вы можете сгенерировать свой вывод matplotlib для кода tikz, который может обрабатывать pdflatex или lualatex.
Таким образом, таким образом, я думаю, вы можете легко вставить фигуру цикла в
ваш рисунок matplotlib.
См. Например:
http://matplotlib.org/users/whats_new.html#pgf-tikz-backend