简体   繁体   English

如何更新mplot3d对象中的facecolors?

[英]How to update the facecolors in a mplot3d object?

I'm trying to create a 3D surface plot whose facecolors values can be interactively updated through sliders. 我正在尝试创建一个3D表面图,其facecolors值可以通过滑块交互式更新。 It is worth noting that in my case the facecolors values don't have anything to do with the coordinates position of the surface. 值得注意的是,在我的情况下,facecolors值与曲面的坐标位置无关。 The surface is there only to represent a certain geometry, and the facecolors are the values mapped into that geometry. 此处的表面仅代表特定的几何图形,而facecolors是映射到该几何图形的值。

As a basic example, I tried to create a plane with the facecolors are provided by a function of an euclidean distance to a given center. 作为一个基本示例,我尝试创建一个平面,该平面的面色由到给定中心的欧几里德距离的函数提供。 The center is the parameter that I will be able to adjust through the sliders. 中心是我可以通过滑块调整的参数。 Here is my code: 这是我的代码:

from numpy import pi, sin
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm, colors
from matplotlib.widgets import Slider, Button, RadioButtons

def signal(amp, freq):
    return amp * sin(2 * pi * freq * t)

axis_color = 'lightgoldenrodyellow'

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

# Adjust the subplots region to leave some space for the sliders and buttons
fig.subplots_adjust(bottom=0.25)

x = np.linspace(0.0, 1.0, num=50)
y = np.linspace(0.0, 1.0, num=50)
t = np.linspace(0.0, 1.0, num=50)
x, y = np.meshgrid(x, y)
z = 1.0 * x + 2.0 * y
def colormapping_values(x_center, y_center):
    return (x-x_center)**2 + (y-y_center)**2

x0 = 0.5
y0 = 0.5
norm = colors.Normalize()
somtethin = cm.jet(norm(colormapping_values(x0, y0)))
surf = ax.plot_surface(x, y, z, facecolors=somtethin)
# Draw the initial plot
# The 'line' variable is used for modifying the line later

# Add two sliders for tweaking the parameters

# Define an axes area and draw a slider in it
x_center_slider_pos  = fig.add_axes([0.15, 0.15, 0.65, 0.03], facecolor=axis_color)
x_center_slider = Slider(x_center_slider_pos, 'X center', 0.0, 1.0, valinit=x0)

# Draw another slider
y_center_slider_pos = fig.add_axes([0.15, 0.1, 0.65, 0.03], facecolor=axis_color)
y_center_slider = Slider(y_center_slider_pos, 'Y center', 0.0, 1.0, valinit=y0)
# Define an action for modifying the line when any slider's value changes
def sliders_on_changed(val):
    print(cm.jet(colormapping_values(x_center_slider.val, y_center_slider.val)).shape)
    surf.set_facecolors(cm.jet(colormapping_values(x_center_slider.val, y_center_slider.val)))
    fig.canvas.draw_idle()
x_center_slider.on_changed(sliders_on_changed)
y_center_slider.on_changed(sliders_on_changed)

# Add a button for resetting the parameters
reset_button_ax = fig.add_axes([0.8, 0.025, 0.1, 0.04])
reset_button = Button(reset_button_ax, 'Reset', color=axis_color, hovercolor='0.975')
def reset_button_on_clicked(mouse_event):
    y_center_slider.reset()
    x_center_slider.reset()
reset_button.on_clicked(reset_button_on_clicked)

plt.show()

The initial plot is correct, however when I click the slider, I get a "ValueError: Invalid RGBA argument", in the line "surf.set_facecolors(cm.jet(colormapping_values(x_center_slider.val, y_center_slider.val)))". 初始图是正确的,但是当我单击滑块时,在“ surf.set_facecolors(cm.jet(colormapping_values(x_center_slider.val,y_center_slider.val)))”行中得到“ ValueError:无效的RGBA参数”。 I suppose I am doing something wrong when using that function. 我想我在使用该功能时做错了什么。 I've done my research, but I have not yet come to a conclusion of what I am doing wrong, as the use is almost identical to what I am doing when I pass the parameter facecolors 我已经完成了研究,但是还没有得出我做错了什么的结论,因为其用法与传递参数facecolors时所做的几乎相同

You need to give a 1D array or list of colours to .set_facecolors() , rather than the 2D array you are currently giving it. 您需要为.set_facecolors()提供一维数组或颜色列表,而不是当前提供的二维数组。

To do this, reshape your array to something with the shape ((len(x)-1 * len(y)-1), 4) . 为此,将数组重塑为形状为((len(x)-1 * len(y)-1), 4)的形状。 (note that the 4 is for the 4-channel colour value). (请注意, 4是4通道颜色值)。

c_len = (len(x)-1 * len(y)-1)

def sliders_on_changed(val):
    print(cm.jet(colormapping_values(x_center_slider.val, y_center_slider.val)).shape)
    surf.set_facecolors(
            cm.jet(colormapping_values(x_center_slider.val, y_center_slider.val)
                )[:-1, :-1].reshape(c_len, 4))
    surf.set_edgecolors(
            cm.jet(colormapping_values(x_center_slider.val, y_center_slider.val)
                )[:-1, :-1].reshape(c_len, 4))    
    fig.canvas.draw_idle()

Note you also need to set the edgecolors in the same way. 请注意,您还需要以相同的方式设置edgecolors。

Testing this out with some different slider values: 使用一些不同的滑块值进行测试:

在此处输入图片说明 在此处输入图片说明 在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM