Maud van Lier
Maud van Lier

Reputation: 13

Changing arrowhead style of 2 of the six vectors in a 3D plot

I would like to lay emphasis on the fact that two of the vectors pointing towards one specific point (environment) are different from the other vectors. I thought of doing so by changing the arrow head of these specific vectors going to that one point. So, in the figure that results from my code, I want to make the arrowheads pointing towards 'environment' to have a distinctly different shape from the other arrowheads. Preferably, the one's pointing towards environment should be filled, while the others are not. Could someone help me out?

import matplotlib.pyplot as plt
import numpy as np


# Define vectors
vectors = np.array([[0, 0, 18], [18, 0, 0], [0, 18, 0]])

# Origin point
origin = np.array([0, 0, 0])

# Define specific points along the vectors
point1 = np.array(vectors[0])  # Select a point on the first vector
point2 = np.array(vectors[1])  # Select a point on the second vector
point3 = np.array(vectors[2])

# Plot setup
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# Define colors for each vector
colors = ['k', 'k', 'k']

# Plot each vector
for i, (vector, color) in enumerate(zip(vectors, colors)):
    if i == 1:  # Assuming the first vector needs a double-headed arrow
        # Arrow from the origin to the vector end
        ax.quiver(origin[0], origin[1], origin[2], vector[0], vector[1], vector[2],
                  arrow_length_ratio=0.1, color=color)
        # Arrow from the vector end back to the origin
        ax.quiver(vector[0], vector[1], vector[2], -vector[0], -vector[1], -vector[2],
                  arrow_length_ratio=0.1, color=color)
    else:
        # Single-headed arrows for the other vectors
        ax.quiver(origin[0], origin[1], origin[2], -vector[0], -vector[1], -vector[2],
                  arrow_length_ratio=0.1, color=color, pivot='tip')

    # Plot the surface
x_points = [point1[0], point2[0], point3[0]]
y_points = [point1[1], point2[1], point3[1]]
z_points = [point1[2], point2[2], point3[2]]

# Connect each point to every other point on different vectors
for i in range(3):
    for j in range(i + 1, 3):
        # Calculate the direction of the arrow
        arrow_direction = np.array([x_points[j] - x_points[i],
                                    y_points[j] - y_points[i],
                                    z_points[j] - z_points[i],
                                    x_points[i] - x_points[j],
                                    y_points[i] - y_points[j],
                                    z_points[i] - z_points[j]])
        # Plot arrow
        ax.quiver(x_points[i], y_points[i], z_points[i],
                  arrow_direction[0], arrow_direction[1], arrow_direction[2],
                  color='b', alpha=1, arrow_length_ratio=0.1)
        ax.quiver(x_points[j], y_points[j], z_points[j],
                  arrow_direction[3], arrow_direction[4], arrow_direction[5],
                  color='b', alpha=1, arrow_length_ratio=0.1)

# Define the text box properties
text_content = [
    "History",
    "Adaptive Repertoire",
    "Environment"
]

# Define the coordinates for each text box
text_coordinates = [
    (5, 5, 30),  # Adjust as needed
    (-15, 25, -5),  # Adjust as needed
    (15, -20, -15)  # Adjust as needed
]

# Add text boxes to the plot
for text, (x, y, z) in zip(text_content, text_coordinates):
    ax.text(x, y, z, text, fontsize=10, color='black', ha='center', va='center',
            bbox=dict(boxstyle='round', facecolor='white', alpha=0))

# Set plot limits
ax.set_xlim([-20, 20])
ax.set_ylim([-20, 20])
ax.set_zlim([-20, 20])

# Remove axis numbers and ticks
# ax.set_axis_off()

# Set labels
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

# Adjust the view angle so that arrowheads face towards the user
ax.view_init(elev=29, azim=45)

plt.show()

Upvotes: 1

Views: 53

Answers (0)

Related Questions