如何解决正确实现 set_facecolor() 以更新表面上的映射数据
我附上了一个简单的程序,它生成一个半球的表面图,指定一个点 A,并绘制每个其他点与 A 的接近度的热图。 for 循环导致 A 围绕圆顶旋转,并且每次迭代都会更新绘图。我正在使用 Python 3.7
使用全新的 plot_surface()
创建与距离表面点的距离成反比的值的二维数组并对其进行热映射是我获得的唯一成功,更新绘图会导致程序运行比我喜欢的要慢得多。
我想优化代码末尾的绘图部分,因为它是主要瓶颈。我在实现将 2D RGBA 数据重塑为矢量的任何答案时都遇到了麻烦,因此我可以利用 set_facecolor()
命令。我的尝试(在瓶颈部分注释),更改整个表面的颜色而不是热图。
set_facecolor()
是否适合用于此应用程序?如果不是,那是什么?应用热图后刷新图形的最佳方法是什么?
热图绘图的MATLAB实现:
超级简单:set(surf,'CData',inv_dist);
Python 3.7 中圆顶上的热图
# Heat Map on a Dome
# 6/7/21
# DGH
# Import the li-berries
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d # necessary for "ax = plt.axes(projection='3d')"
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# Get Hemisphere Coordinates
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# Spherical Coordinates for ranges of angles
r = 1 # radius
theta = [0,90] # measured from z-axis
theta_step = 1
Theta = np.linspace(max(theta),min(theta),int((max(theta)-min(theta))/theta_step+1))
phi = [-180,180] # measured from x-axis
phi_step = 2
Phi = np.linspace(max(phi),min(phi),int((max(phi)-min(phi))/phi_step+1))
# replicate vectors to make a meshgrid
Theta = np.tile(Theta,(Phi.shape[0],1)).transpose()
Phi = np.tile(Phi,(Theta.shape[0],1))
# convert from spherical to cartesian
X = np.multiply(np.multiply(r,np.sin(Theta*np.pi/180)),np.cos(Phi*np.pi/180))
Y = np.multiply(np.multiply(r,np.sin(Phi*np.pi/180))
Z = np.multiply(r,np.cos(Theta*np.pi/180))
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# Plot Hemisphere
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
fig = plt.figure()
ax = plt.axes(projection='3d')
surf = ax.plot_surface(X,Y,Z,cmap='viridis',edgecolor='none')
# turn of numbering along axes
ax.axes.xaxis.set_ticks([])
ax.axes.yaxis.set_ticks([])
ax.axes.zaxis.set_ticks([])
plt.show()
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# Synthesize Data and Plot
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# make data array
d_phi = np.linspace(-180,179,25)
d_theta = np.linspace(15,45,d_phi.size)
d_r = np.ones(d_phi.shape)
# convert from spherical to cartesian
dat_x = np.multiply(np.multiply(r,np.sin(d_theta*np.pi/180)),np.cos(d_phi*np.pi/180))
dat_y = np.multiply(np.multiply(r,np.sin(d_phi*np.pi/180))
dat_z = np.multiply(r,np.cos(d_theta*np.pi/180))
for i in range(0,d_phi.size):
# calculate distance to point on surface of sphere and inverts for a heatmap of "closeness"
dist = np.sqrt(np.square(X-dat_x[i]) + np.square(Y-dat_y[i]) + np.square(Z-dat_z[i]))
inv_dist = np.divide(1,(dist+1))
# get 2D-array of RGBA values for heat map
colors = plt.cm.ScalarMappable(cmap = "viridis").to_rgba(inv_dist)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# BottLENECK
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# apply facecolors (inefficiently)
surf = ax.plot_surface(X,rstride=1,cstride=1,facecolors=colors,linewidth=0,antialiased=False,shade=False,alpha=1)
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# Attempt at Optimization
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# color_vector = colors.reshape(colors.shape[0]*colors.shape[1],4)[:-1][:-1]
# or
# color_vector = colors.reshape(colors.shape[0]*colors.shape[1],4)
# surf.set_facecolor(color_vector)
# update figure [probably a better way to do this too]
fig.canvas.draw_idle()
fig.canvas.flush_events()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
print('i={}'.format(i))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。