Как я могу установить цветовую карту относительно радиуса фигуры?
А как мне закрыть концы цилиндра (на элементе, а не на верхнем и нижнем основаниях)?
Мой сценарий:
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from math import sin, cos, pi
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
h, w = 60,30
znew = np.random.randint(low=90, high=110, size=(60,30))
theta = np.linspace(0,2*pi, h)
Z = np.linspace(0,1,w)
Z,theta = np.meshgrid(Z, theta)
R = 1
X = (R*np.cos(theta))*znew
Y = (R*np.sin(theta))*znew
ax1 = ax.plot_surface(X,Y,Z,linewidth = 0, cmap = "coolwarm",
vmin= 80,vmax=130, shade = True, alpha = 0.75)
fig.colorbar(ax1, shrink=0.9, aspect=5)
plt.show()
Радиус цилиндра в каждой точке разный. Я хотел бы изобразить радиус в каждой точке, чтобы горы и долины были выделены цветом. znew - это массив, который содержит профиль высотной отметки и соответствует цилиндру. Но концы не совсем совпадают.
Что это: znew = array(60,30)
? Отредактируйте свой вопрос, чтобы сделать его воспроизводимым
Если ваши данные znew
не являются периодическими в theta
, тогда вы не получите закрытой поверхности.
Обновленный скрипт. znew теперь состоит из случайных данных. Но вы можете воспроизвести это. Я просто хочу раскрасить все значения в соответствии с их радиусом. В оригинале возникают долины и горы.
Сначала вам нужно использовать аргумент ключевого слова facecolors
plot_surface
, чтобы нарисовать вашу поверхность произвольными (не на основе Z
) цветами. Вы должны передать явный цвет RGBA четыре для каждой точки, что означает, что нам нужно выбрать объект цветовой карты с ключами, заданными радиусом в каждой точке. Наконец, это нарушит свойство mappable результирующей поверхности, поэтому нам придется создать цветовую панель, вручную указав ей использовать наши радиусы для цветов:
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.cm as cm
from matplotlib.colors import Normalize
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
h, w = 60,30
#znew = np.random.randint(low=90, high=110, size=(h,w))
theta = np.linspace(0,2*np.pi, h)
Z = np.linspace(0,1,w)
Z,theta = np.meshgrid(Z, theta)
znew = 100 + 10*np.cos(theta/2)*np.cos(2*Z*np.pi)
R = 1
X = (R*np.cos(theta))*znew
Y = (R*np.sin(theta))*znew
true_radius = np.sqrt(X**2 + Y**2)
norm = Normalize()
colors = norm(true_radius) # auto-adjust true radius into [0,1] for color mapping
cmap = cm.get_cmap("coolwarm")
ax.plot_surface(X, Y, Z, linewidth=0, facecolors=cmap(colors), shade=True, alpha=0.75)
# the surface is not mappable, we need to handle the colorbar manually
mappable = cm.ScalarMappable(cmap=cmap)
mappable.set_array(colors)
fig.colorbar(mappable, shrink=0.9, aspect=5)
plt.show()
Обратите внимание, что я изменил радиусы на что-то более плавное, чтобы результат выглядел менее хаотичным. true_radius
arary содержит фактические радиусы в единицах данных, которые после нормализации становятся colors
(по сути, colors = (true_radius - true_radius.min())/true_radius.ptp()
).
Результат:
Наконец, обратите внимание, что я создал такие радиусы, что цилиндр не закрывается плавно. Это имитирует ваш случайный ввод примера. Есть ничего такого, вы можете это сделать, если радиусы не являются 2π-периодическими в theta
. Это не имеет ничего общего с визуализацией, это геометрия.
Я не уверен, что ваш MCVE завершен. Если ваш
theta
переходит от 0 до 2 * pi включительно и znew не зависит от theta, тогда поверхность должна быть закрыта. И я не понимаю вашего главного вопроса о палитре.