Как добавить цветовую карту в 3D-график matplotlib

Я хочу добавить цветовую карту, чтобы показать градиент по оси x, но, к сожалению, вся фигура становится черной. Мне может чего-то не хватать, помогите мне в этом. Вот код.

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

Я использовал метод цветовой карты огнестрельного оружия, чтобы придать градиентный цвет 3D-графику, но ничего не работает. Пожалуйста, предложите мне, как действовать. Если есть какой-либо другой метод, с помощью которого я могу создать градиент с 6 цветами, это тоже будет хорошо.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Первая проблема здесь заключается в том, что количество записей в аргументе facecolors должно совпадать с количеством граней, иначе похоже, что matplotlib возвращается к выбору первого цвета в списке — здесь это черный.

Вторая проблема заключается в том, что вы пытаетесь создать прямоугольный параллелепипед всего с 6 гранями, а затем раскрасить его с помощью гладкой карты цветов. Многоугольники в matplotlib могут быть окрашены только одним цветом каждый. Итак, вы должны разделить свой кубоид.

Вот моя попытка решить эти две проблемы! Я создаю набор точек от 0 до 10, а затем создаю вершины в этих x-позициях. Я также строю массив x-позиций непосредственно из граней, взяв среднее значение x-позиции каждой из четырех вершин, составляющих каждую грань.

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

Надеюсь это поможет! Однако я не уверен, что смогу воспроизвести черные края. Я попытался сделать второй прямоугольный параллелепипед, как ваш оригинальный, с шестью гранями и facecolor = "none", но это выдало ошибку.

PS: я сохранил вам импорт с помощью plt.get_cmap.

Замечательно!. Это решило задачу. Большое спасибо. Но есть небольшое сомнение, когда я пытаюсь расширить тот же график до большего значения, скажем, x = 1000, сохраняя все остальные параметры одинаковыми. График сжимается в направлении x, но я хочу, чтобы он расширялся вдоль x, чтобы я мог привязать к нему горизонтальную полосу прокрутки. Так как мне нужно добавить еще несколько графиков на поверхность вдоль направления x. Поэтому его не будет видно, если он уменьшится. Прошу подсказать, как этого добиться. Я пробовал set_box_aspect метод, но он у меня не работает. Я также пытался настроить размер инжира, но ничего не работает.

Prashant Priyadarshi 12.04.2023 10:47

Другие вопросы по теме