matplotlib 带箭头的箭头,如果指向同一点,则会相互接触

bd1hkmkf  于 2023-11-22  发布在  其他
关注(0)|答案(1)|浏览(132)

所以,在Correct, "full length" left-right arrows in Matplotlib?之后,我意识到Matplotlib箭头还有一点棘手;考虑这个例子:

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()
ax.plot([0],[0])
ax.grid()
ax.set_xlim([0,10])
ax.set_ylim([0,10])
ax.annotate("", (2, 1), (4, 1), arrowprops={'arrowstyle':'<->', 'shrinkA': 0, 'shrinkB': 0})
ax.annotate("", (4, 1), (6, 1), arrowprops={'arrowstyle':'<->', 'shrinkA': 0, 'shrinkB': 0})
plt.show()

字符串
基本上,这里第一个箭头指向向右的点(x=4,y=1)作为其终点,第二个箭头指向向左的同一点作为其起点:
x1c 0d1x的数据
……事实上,它看起来很好。
然而,如果我删除网格(注解ax.grid()行),我会得到这样的结果:



因此,在这个例子中,我可以看到从两边指向(4,1)的箭头并不相互接触--我希望它们这样做,以便给予一个视觉指示,表明它们都指向同一个点。如果我们使用图像应用程序放大:



.很明显,箭头之间的差距只有一个像素。
从本质上讲,我需要与shrink*参数相反的参数(类似于“extend”)-我找不到这样的参数,所以我试图通过给shrink*负值来作弊,但它们产生的结果与正值相同(它们显式地进行收缩)。
有什么方法可以实现这一点吗?只是为了澄清-我希望获得以下内容(也就是说,上一个图像上的1像素宽的差距,也被绘制):



......当缩小时,看起来像这样:
x1c4d 1x的

pexxcrt2

pexxcrt21#

我发布这个作为一个答案,只是为了可读性(否则我会把它作为一个编辑发布到OP;很难找到一个简单的例子):
在下面的例子中,我尝试从多边形手动构造箭头;用一个小的eps ilon值替换箭头的“尖端”,将使它们看起来重叠/接触。(Point类只是为了可读性,更容易地指示考虑了哪些点坐标)。然而,问题是:

  • 在这一点上,阅读代码,我很容易忘记什么是第一点,什么是最后一点,以及以何种顺序执行绘图操作
  • 因此,其中一个自定义箭头显示为“填充”并位于线的”顶部”-另一个显示为线的“下方”(在z堆叠绘图顺序的意义上)
  • 当你放大那张图时,很快第二条线就消失了
  • 这种方法只适用于水平箭头线-其他任何东西都需要旋转和/或缩放多边形(可能类似于Custom arrow style for matplotlib, pyplot.annotate

也就是说,代码是:

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np

class Point(object): # https://stackoverflow.com/q/40923522/
  def __init__(self,x_init,y_init):
    super(Point, self).__init__()
    self.x = x_init
    self.y = y_init
    self.itrcnt = 0
  def __iter__(self):
    return self
  def __next__(self):
    ret = None
    if self.itrcnt == 0:
      ret = self.x
      self.itrcnt = 1
    elif self.itrcnt == 1:
      ret = self.y
      self.itrcnt = 2
    elif self.itrcnt == 2:
      self.itrcnt = 0
      raise StopIteration
    return ret
  def next(self):
    return self.__next__()

fig = plt.figure()
ax = fig.add_subplot()
ax.plot([0],[0])
#ax.grid()
ax.set_xlim([0,10])
ax.set_ylim([0,10])

p21 = Point(2, 1)
p41 = Point(4, 1)
p61 = Point(6, 1)

eps = 1e-2
poly21B = patches.Polygon( np.array([(p41.x+eps,p41.y), (p41.x-0.1,p41.y+0.1), (p41.x-0.1,p41.y-0.1)]), facecolor='0.9', edgecolor='0.2', closed=True)
ax.add_patch(poly21B) # must have, else no rendering of poly!
poly41A = patches.Polygon( np.array([(p41.x-eps,p41.y), (p41.x+0.1,p41.y+0.1), (p41.x+0.1,p41.y-0.1)]), facecolor='0.9', edgecolor='0.2', closed=True)
ax.add_patch(poly41A) # must have, else no rendering of poly!
#ax.annotate("", (2, 1), (4, 1), arrowprops={'arrowstyle':'wedge,tail_width=50,shrink_factor=0.5', 'shrinkA': 0, 'shrinkB': 0})
# note: if we thing of pX and pY as start and end points, arrowstyle text arrows are then "opposite"
ax.annotate("", p21, p41, arrowprops={'arrowstyle':'->', 'shrinkA': 0, 'shrinkB': 0, 'patchA': poly21B })
ax.annotate("", p41, p61, arrowprops={'arrowstyle':'<-', 'shrinkA': 0, 'shrinkB': 0, 'patchA': poly41A })
plt.show()

字符串
这导致:
x1c 0d1x的数据
放大像素,箭头的重叠似乎不错:



.然而,如果我在Matplotlib中进行(“data”)缩放,右边的行最终会消失:



所以这并不是一个真正的“生产就绪”解决方案。

相关问题