I want to add the colormap to show the gradient along x axis but unfortunately the whole figure turns black. I might be lacking something kindly help me in this. Here is the code.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.cm as cm
import numpy as np
# Create a 3D figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Define the vertices of the rectangular rod
vertices = np.array([
[0, -0.5, -0.5],
[0, -0.5, 0.5],
[0, 0.5, 0.5],
[0, 0.5, -0.5],
[10, -0.5, -0.5],
[10, -0.5, 0.5],
[10, 0.5, 0.5],
[10, 0.5, -0.5]
])
# Define the faces of the rectangular rod
faces = np.array([
[0, 1, 2, 3],
[4, 5, 6, 7],
[0, 1, 5, 4],
[1, 2, 6, 5],
[2, 3, 7, 6],
[3, 0, 4, 7]
])
# Map the x-coordinate of each vertex to a color in the colormap
x = vertices[:, 0]
norm = plt.Normalize(x.min(), x.max())
colors = cm.gnuplot(norm(x))
# Create a Poly3DCollection object with the vertices, faces, and colors
rect = Poly3DCollection(vertices[faces], alpha=0.8, facecolors=colors, edgecolors='black')
# Add the rectangular rod to the plot
ax.add_collection3d(rect)
# Set the limits of the x, y, and z axes
ax.set_xlim([0, 10])
ax.set_ylim([-1, 1])
ax.set_zlim([-1, 1])
# Add labels to the axes
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# Show the plot
plt.show()
I have used gunplot colormapping methodto give the gradiant color to the 3d plot but nothing works. Kindly suggest me how to proceed. If there is any other method using which i can create a gradiant with 6 colors that would also be fine.
The first problem here is that the number of entries in the facecolors
argument has to match the number of faces, otherwise it looks like matplotlib falls back to picking out the first colour in the list - here, that's black.
The second problem is that you're trying to create a cuboid with just 6 faces, but then colour it with a smooth colourmap. The polygons in matplotlib can only be coloured with a single colour each. So you have to subdivide your cuboid.
Here's my attempt at fixing these two problems! I create a set of points between 0 and 10 and then create vertices at these x-positions. I also construct the array of x-positions directly from the faces, taking an average of the x-position of each of the four vertices making up each face.
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
# Create a 3D figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Define the vertices of the rectangular rod
N_sub = 50 # Set higher for better resolution; lower for better performance!
vertices = np.concatenate([
np.array([[x, -0.5, -0.5],
[x, -0.5, 0.5],
[x, 0.5, 0.5],
[x, 0.5, -0.5]])
for x in np.linspace(0, 10, N_sub + 1)], axis=0)
# Define the faces of the rectangular rod
offset = (N_sub) * 4
faces = np.concatenate([
[[0, 1, 2, 3]],
*[np.array([[3, 0, 4, 7],
[0, 1, 5, 4],
[1, 2, 6, 5],
[2, 3, 7, 6]]) + 4 * x for x in range(0, N_sub)],
[[0 + offset, 1 + offset, 2 + offset, 3 + offset]]
], axis=0)
# Map the x-coordinate of each face to a color in the colormap
x = np.array([np.mean([vertices[idx, 0] for idx in face]) for face in faces])
norm = plt.Normalize(x.min(), x.max())
cmap = plt.get_cmap("gnuplot")
colors = cmap(norm(x))
# Create a Poly3DCollection object with the vertices, faces, and colors
rect = Poly3DCollection(vertices[faces], alpha=0.8, facecolors=colors)
# Add the rectangular rod to the plot
ax.add_collection3d(rect)
# Set the limits of the x, y, and z axes
ax.set_xlim([0, 10])
ax.set_ylim([-1, 1])
ax.set_zlim([-1, 1])
# Add labels to the axes
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# Show the plot
plt.show()
Hope this helps! I'm not sure I'm able to replicate the black edges however. I tried doing a second cuboid, like your original one, with six faces and facecolor="none"
but this threw an error.
PS: I saved you an import by using plt.get_cmap
.