在 Matplotlib 中绘制两条线之间的角度的最佳方法

新手上路,请多包涵

我对使用 matplotlib 还很陌生,找不到任何显示两条线并绘制它们之间的角度的示例。

这是我现在的形象:在此处输入图像描述

这是我想要实现的一个例子:

在此处输入图像描述

我通常会查看 Matplotlib 画廊 以了解如何执行某些任务,但似乎没有任何相似之处。

原文由 Michael Aquilina 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

您可以使用 matplotlib.patches.Arc 绘制相应角度测量的弧。

要绘制角弧:

定义一个函数,它可以接受 2 个 matplotlib.lines.Line2D 对象,计算角度并返回一个 matplotlib.patches.Arc 对象,您可以将其与线条一起添加到绘图中。

 def get_angle_plot(line1, line2, offset = 1, color = None, origin = [0,0], len_x_axis = 1, len_y_axis = 1):

    l1xy = line1.get_xydata()

    # Angle between line1 and x-axis
    slope1 = (l1xy[1][1] - l1xy[0][2]) / float(l1xy[1][0] - l1xy[0][0])
    angle1 = abs(math.degrees(math.atan(slope1))) # Taking only the positive angle

    l2xy = line2.get_xydata()

    # Angle between line2 and x-axis
    slope2 = (l2xy[1][3] - l2xy[0][4]) / float(l2xy[1][0] - l2xy[0][0])
    angle2 = abs(math.degrees(math.atan(slope2)))

    theta1 = min(angle1, angle2)
    theta2 = max(angle1, angle2)

    angle = theta2 - theta1

    if color is None:
        color = line1.get_color() # Uses the color of line 1 if color parameter is not passed.

    return Arc(origin, len_x_axis*offset, len_y_axis*offset, 0, theta1, theta2, color=color, label = str(angle)+u"\u00b0")

要打印角度值:

如果您希望内联显示角度值,请参阅 SO 问题以了解如何在 matplotlib 中打印内联标签。请注意,您必须打印弧的标签。

我做了一个小函数,它提取弧的顶点并尝试计算角度文本的坐标。

这可能不是最佳的,并且可能不适用于所有角度值。

 def get_angle_text(angle_plot):
    angle = angle_plot.get_label()[:-1] # Excluding the degree symbol
    angle = "%0.2f"%float(angle)+u"\u00b0" # Display angle upto 2 decimal places

    # Get the vertices of the angle arc
    vertices = angle_plot.get_verts()

    # Get the midpoint of the arc extremes
    x_width = (vertices[0][0] + vertices[-1][0]) / 2.0
    y_width = (vertices[0][5] + vertices[-1][6]) / 2.0

    #print x_width, y_width

    separation_radius = max(x_width/2.0, y_width/2.0)

    return [ x_width + separation_radius, y_width + separation_radius, angle]

或者您始终可以手动预先计算标签点并使用 text 来显示角度值。您可以使用 get_label() label Arc 因为我们已经将值角度设置为 unicode 度数 +象征)。

上述功能的示例用法:

 fig = plt.figure()

line_1 = Line2D([0,1], [0,4], linewidth=1, linestyle = "-", color="green")
line_2 = Line2D([0,4.5], [0,3], linewidth=1, linestyle = "-", color="red")

ax = fig.add_subplot(1,1,1)

ax.add_line(line_1)
ax.add_line(line_2)

angle_plot = get_angle_plot(line_1, line_2, 1)
angle_text = get_angle_text(angle_plot)
# Gets the arguments to be passed to ax.text as a list to display the angle value besides the arc

ax.add_patch(angle_plot) # To display the angle arc
ax.text(*angle_text) # To display the angle value

ax.set_xlim(0,7)
ax.set_ylim(0,5)

如果您不关心角度文本的内联放置。您可以使用 plt.legend() 打印角度值。

最后 :

 plt.legend()
plt.show()

2 条线的角度图

offset 函数中的参数 get_angle_plot 用于指定圆弧的伪半径值。

当角弧可能相互重叠时,这将很有用。

(在这个图中,就像我说的,我的 get_angle_text 函数在放置文本值方面不是很理想,但应该让您了解如何计算点)

添加第三行:

 line_3 = Line2D([0,7], [0,1], linewidth=1, linestyle = "-", color="brown")
ax.add_line(line_3)
angle_plot = get_angle_plot(line_1, line_3, 2, color="red") # Second angle arc will be red in color
angle_text = get_angle_text(angle_plot)

ax.add_patch(angle_plot) # To display the 2nd angle arc
ax.text(*angle_text) # To display the 2nd angle value

3 条线的角度图

原文由 Raghav RV 发布,翻译遵循 CC BY-SA 3.0 许可协议

我一直在寻找更多的一体化解决方案,并找到了 AngleAnnotation 类。我强烈推荐它。

用圆弧标记线之间或内部形状之间的角度通常很有用。虽然 Matplotlib 提供了 Arc,但直接将其用于此类目的时存在一个固有问题,即在数据空间中为圆形的弧在显示空间中不一定为圆形。此外,圆弧的半径通常最好在独立于实际数据坐标的坐标系中定义 - 至少如果您希望能够自由放大绘图而不需要注释增长到无穷大。

你可以在这里找到它 https://matplotlib.org/stable/gallery/text_labels_and_annotations/angle_annotation.html 我在我的工作目录中将它保存为 AngleAnnotation.py(当然你可以用不同的名称)并将它导入我的代码中

from AngleAnnotation import AngleAnnotation

这是我如何使用它的片段:

 ...
#intersection of the two lines
center = (0.0,0.0)
#any point (other than center) on one line
p1 = (6,2)
# any point (other than center) on the other line
p2 = (6,0)
# you may need to switch around p1 and p2 if the arc is drawn enclosing the lines instead
# of between
# ax0 is the axes in which your lines exist
# size sets how large the arc will be
# text sets the label for your angle while textposition lets you rougly set where the label is, here "inside"
# you can pass kwargs to the textlabel using text_kw=dict(...)
# especially useful is the xytext argument which lets you customize the relative position of your label more precisely

am1 = AngleAnnotation(center, p1, p2, ax=ax0, size=130, text="some_label", textposition = "inside", text_kw=dict(fontsize=20, xytext = (10,-5)))

您可以在上面的链接中找到更多详细信息。它现在在 matplotlib 3.4.2 上为我工作。

原文由 WiseKouichi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题