Last active
February 18, 2024 11:35
-
-
Save battlecook/0c0bdb7097ec7c8fa160e342b1bf51ef to your computer and use it in GitHub Desktop.
stackoverflow comment (https://stackoverflow.com/questions/25227100/best-way-to-plot-an-angle-between-two-lines-in-matplotlib/25228427#25228427)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
import matplotlib.pyplot as plt | |
from matplotlib.lines import Line2D | |
from matplotlib.patches import 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][1]) / 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][1] - l2xy[0][1]) / 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") | |
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][1] + vertices[-1][1]) / 2.0 | |
separation_radius = max(x_width/2.0, y_width/2.0) | |
return [x_width + separation_radius, y_width + separation_radius, angle] | |
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.savefig('./vector_angle.png', dpi=300) |
I'll let you know after reviewing your code.
I always get the following error for your code:
Traceback (most recent call last):
File "/home/lars/documents/ba/202311-ba-alsbach-rl_based_so_for_fibre_reinforced_concrete/05-Code/plotting/plotGenerationBA/test.py", line 72, in
angle_plot = get_angle_plot(line_1, line_2, 1)
File "/home/lars/documents/ba/202311-ba-alsbach-rl_based_so_for_fibre_reinforced_concrete/05-Code/plotting/plotGenerationBA/test.py", line 34, in get_angle_plot
return Arc(
TypeError: init() takes 4 positional arguments but 7 were given
Edit:
I fixed it:
exchange
Arc(origin, len_x_axis*offset, len_y_axis*offset, 0,
theta1, theta2, color=color,
label = r'${:.4}^\circ$'.format(float(angle)))
with
Arc(origin, len_x_axis*offset, len_y_axis*offset, angle = 0.0,
theta1, theta2, color=color,
label = r'${:.4}^\circ$'.format(float(angle)))
fixed it for me.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Excellent script. I might make one modification that allows you to deal with lines in different quadrants. Let me know if you think those would work for more situations. Thanks!