connectionstyle arc3(FancyArrowPatch)和路径CURVE3 - 两条二次贝塞尔曲线,不同的结果?

时间:2018-06-15 07:56:25

标签: python matplotlib bezier

我从这里提到的类似问题开始: Draw rounded fancyarrowpatch with midpoint arrow in matplotlib

只是我想在箭头上添加标签,理想情况是在变量位置。我试图用路径顶点重建坐标,但标签仍然遍布整个地方。 然后,我尝试按照connectionstyle arc3

的描述

https://matplotlib.org/api/_as_gen/matplotlib.patches.ConnectionStyle.html?highlight=connectionstyle

类Arc3(rad = 0.0)

在两点之间创建一个简单的二次贝塞尔曲线。创建曲线使得中间控制点(C1)位于距起点(C0)和终点(C2)相同的距离处,并且C1到连接C0-C2的线的距离是rad的距离。 C0-C2

我重建了这个并注意到FancyArrowPatch绘制的曲线与具有指定点的二次贝塞尔曲线不同。

最小例子:

import numpy
import matplotlib
from matplotlib import pyplot as plt
import matplotlib.path as mpath
import matplotlib.patches as mpatches
from matplotlib.patches import FancyArrowPatch, Circle

fig = plt.figure(frameon=False)
ax = fig.add_subplot(111, frame_on=False)

rad=0.3
shrink=0.3

# Setting up circles as start and end points
size = 0.1
n1 = Circle([0,0], radius=size, alpha=0., fill=False, linewidth=0.1)
n2 = Circle([1,1], radius=size, alpha=0., fill=False, linewidth=0.1)
ax.add_patch(n1)
ax.add_patch(n2)

# Create a fancy arrow between start and end point
e = FancyArrowPatch(n1.center, n2.center,
    connectionstyle='arc3,rad=%s' % rad,
    arrowstyle='simple',
    clip_on=False,
    linewidth=2.,
    shrinkA=shrink,shrinkB=shrink
    )

ax.add_patch(e)

# Start point
vs=numpy.asarray(n1.center)
# End point
ve=numpy.asarray(n2.center)
# Connection vector start->end
vD=ve-vs
# Perpendicular vector to vD
vp=numpy.asarray([vD[1],-vD[0]]) 
# Control point: same distance from start and end point, and rad*|vD| from the connection line between start and end
vc=vs+0.5*vD+rad*vp 

Path=mpath.Path
pp1 = mpatches.PathPatch(
    Path([vs, vc, ve],
     [Path.MOVETO, Path.CURVE3, Path.CURVE3]), color="red", transform=ax.transData,fc='None')

ax.add_patch(pp1)

# Putting labels on quadratic Bezier curve at various points
# Uses start point, control point and end point from above
for tt in numpy.arange(0,1.1,0.1):
    vl=((1-tt)**2)*vs+(2*(1-tt)*tt)*vc+(tt**2)*ve
    string = str(tt)
    ax.text(vl[0], vl[1], string,
        fontsize=10,bbox={'alpha':0.5, 'pad':2},
        verticalalignment='center',
        horizontalalignment='center')

plt.show()

哪个给出了

https://i.imgur.com/6XD8txW.png

黑线:FancyArrowPatch(不知道为什么没有箭头)

红线:PathPatch

蓝色标签:在(0,0)和(1,1)之间的二次贝塞尔曲线上的点,控制点与开始和结束的距离相同,并且从开始和结束之间的连接线的rad *(距离起点到终点)结束。 (如connectionstyle arc3中所述)。

(不幸的是,我不能只为FancyArrowPatch提供构建的路径,因为我需要它的缩小/补丁选项。)

所以问题是我如何可靠地在箭头上放置标签,以及FancyArrowPatch如何实际构建其路径。

(我知道我可以返回顶点,但我对不同的箭头长度使用相同的代码(只有起点和终点不同),这些路径看起来彼此差异很大。)

1 个答案:

答案 0 :(得分:0)

您创建为Path的曲线位于数据空间中。自动生成的FancyArrowPatch曲线位于显示空间中。 这意味着只有当数据空间中的点之间的距离与显示空间中的点之间的距离成比例时,它们才是相等的。这通常仅在轴纵横比相等的情况下。

这在某种程度上类似于数据坐标中定义的圆的更直观(反向)情况。在这种情况下,文档会说“画一个圆圈,即到达给定中心点到处都有相同距离的线”。然而,如果你绘制一个圆形,它看起来就像一个椭圆,除非你将轴的纵横比设置为1。

确实,在设置ax.set_aspect("equal")时,在上面的情况下你会得到

enter image description here

由于Arc3本身对它将使用的坐标系不了解,Arc3 documentation完全正确。