简体   繁体   English

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

[英]connectionstyle arc3 (FancyArrowPatch) and path CURVE3 - two quadratic Bezier curves, different outcomes?

I started from a similar problem as mentioned here: Draw rounded fancyarrowpatch with midpoint arrow in matplotlib 我从这里提到的类似问题开始: 在matplotlib中用中点箭头绘制圆形的fancyarrowpatch

Just that I would like to add a label to an arrow, ideally in variable places. 只是我想在箭头上添加标签,最好在可变的地方。 I tried to reconstruct coordinates with the path vertices, but the labels still were all over the place. 我试图用路径顶点重建坐标,但是标签仍然到处都是。 Then, I tried to follow the description of the connectionstyle arc3 然后,我尝试遵循connection3 arc3的描述

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

class Arc3(rad=0.0) 类Arc3(rad = 0.0)

Creates a simple quadratic bezier curve between two points. 在两点之间创建简单的二次贝塞尔曲线。 The curve is created so that the middle control point (C1) is located at the same distance from the start (C0) and end points(C2) and the distance of the C1 to the line connecting C0-C2 is rad times the distance of C0-C2. 创建曲线以使中间控制点(C1)距起点(C0)和终点(C2)的距离相同,并且C1到连接C0-C2的线的距离为rad乘以距离C0-C2。

I reconstructed this and noticed that the Curve drawn by FancyArrowPatch is NOT the same as a quadratic Bezier curve with the specified points. 我对此进行了重构,并注意到FancyArrowPatch绘制的曲线与具有指定点的二次Bezier曲线不同。

Minimal example: 最小示例:

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()

Which gives 这使

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

Black line: FancyArrowPatch (don't know why there is no arrowhead) 黑线:FancyArrowPatch(不知道为什么没有箭头)

Red line: PathPatch 红线:PathPatch

Blue labels: Points on quadratic Bezier Curve between (0,0) and (1,1) with control point at same distance from start and end, and rad*(distance startpoint to endpoint) from the connection line between start and end. 蓝色标签:(0,0)和(1,1)之间的二次贝塞尔曲线上的点,控制点距起点和终点的距离相同,而rad *(起点和终点的距离)距起点和终点之间的连接线。 (as described in connectionstyle arc3). (如connectionstyle arc3中所述)。

(Unfortunately I can't just give FancyArrowPatch the constructed path, because I need its shrink/patch options.) (不幸的是,我不能只给FancyArrowPatch构造路径,因为我需要它的收缩/补丁选项。)

So the question is how I reliably put a label on an arrow, and how FancyArrowPatch is actually constructing its path. 所以问题是我如何可靠地在箭头上放置标签,以及FancyArrowPatch实际上是如何构建其路径的。

(I know I can have the vertices returned, but I use identical code for different arrow lengths (only start and end point differ), and these paths can look very different from each other). (我知道我可以返回顶点,但是我对不同的箭头长度使用相同的代码(只有起点和终点不同),并且这些路径看起来彼此非常不同)。

The curve you create as Path lives in data space. 您创建为Path的曲线位于数据空间中。 The FancyArrowPatch curve that is automatically generated lives in display space. 自动生成的FancyArrowPatch曲线位于显示空间中。 This means that they will be equal only if the distance between points in data space is propotional to the distance between points in display space. 这意味着仅当数据空间中的点之间的距离与显示空间中的点之间的距离成比例时,它们才相等。 This is in general only the case when the axes aspect ratio is equal. 通常只有轴长宽比相等时才是这种情况。

This is somehow similar to the more intuitive (inverse) case of a circle defined in data coordinates. 这在某种程度上类似于在数据坐标中定义的圆的更直观(相反)的情况。 In such case a documentation would say something like "draws a circle, ie a line which has the same distance to a given center point everywhere". 在这种情况下,文档会说“画一个圆,即到任何地方到给定中心点的距离相同的线”。 Yet, if you plot a circle it would rather look like an ellipse, unless you set the aspect ratio of the axes to be 1. 但是,如果绘制圆,则除非将轴的长宽比设置为1,否则它看起来像是椭圆形。

Indeed, when setting ax.set_aspect("equal") , in the case above you'd get 确实,在设置ax.set_aspect("equal") ,在上述情况下

在此处输入图片说明

Since the Arc3 itself will not know anything about the coordinate system it will be used in, the Arc3 documentation is completely correct. 由于Arc3本身对使用的坐标系Arc3 ,因此Arc3文档是完全正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM