我想将多个Mayavi对象组合成一个“分组”对象,以便我一起控制它们的所有属性。例如,我通过组合3个内置表面(两个球体和一个圆柱体)创建了以下双凸透镜形状。现在我想一次为所有组成表面分配统一的属性(镜面反射,环境颜色等)(不是单独的)。另外,我想翻译/旋转镜头作为一个整体。我不知道如何做到这一点。
这是在Mayavi中创建的双凸透镜(下面给出的代码):
如下图所示,上述镜头由三个表面组成:
以下是构建双凸透镜的代码:
import numpy as np
from mayavi import mlab
from mayavi.sources.builtin_surface import BuiltinSurface
from mayavi.modules.surface import Surface
from mayavi.filters.transform_data import TransformData
def lensUsingMayaviBuiltinSphere(radius=0.5, semiDiam=0.25, thickness=0.9):
"""
Render a bi-convex lens
"""
engine = mlab.get_engine()
sag = radius - np.sqrt(radius**2 - semiDiam**2)
cyl_height = thickness - 2.0*sag # thickness of the cylinder in between
# Create Mayavi data sources -- sphere_h1_src, sphere_h2_src, cylinder_src
# half 1: source = sphere_h1_src
sphere_h1_src = BuiltinSurface()
engine.add_source(sphere_h1_src)
sphere_h1_src.source = 'sphere'
sphere_h1_src.data_source.radius = radius
sphere_h1_src.data_source.center = np.array([ 0., 0., -np.sqrt(radius**2 - semiDiam**2) + cyl_height/2.0])
sphere_h1_src.data_source.end_phi = np.rad2deg(np.arcsin(semiDiam/radius)) #60.0
sphere_h1_src.data_source.end_theta = 360.0
sphere_h1_src.data_source.phi_resolution = 300
sphere_h1_src.data_source.theta_resolution = 300
# half 2: source = sphere_h2_src
sphere_h2_src = BuiltinSurface()
engine.add_source(sphere_h2_src)
sphere_h2_src.source = 'sphere'
sphere_h2_src.data_source.radius = radius
sphere_h2_src.data_source.center = np.array([ 0., 0., np.sqrt(radius**2 - semiDiam**2) - cyl_height/2.0])
sphere_h2_src.data_source.start_phi = 180.0 - np.rad2deg(np.arcsin(semiDiam/radius))
sphere_h2_src.data_source.end_phi = 180.0
sphere_h2_src.data_source.end_theta = 360.0
sphere_h2_src.data_source.phi_resolution = 300
sphere_h2_src.data_source.theta_resolution = 300
# cylinder source data in between
cylinder_src = BuiltinSurface()
engine.add_source(cylinder_src)
cylinder_src.source = 'cylinder'
cylinder_src.data_source.center = np.array([ 0., 0., 0.])
if cyl_height > 0:
cylinder_src.data_source.height = cyl_height
else:
cylinder_src.data_source.height = 0.0
cylinder_src.data_source.radius = semiDiam
cylinder_src.data_source.capping = False
cylinder_src.data_source.resolution = 50
# Add transformation filter to align cylinder length along z-axis
transform_data_filter = TransformData()
engine.add_filter(transform_data_filter, cylinder_src)
Rt_c = [ 1.0000, 0.0000, 0.0000, 0.00,
0.0000, 0.0000, -1.0000, 0.00,
0.0000, 1.0000, 0.0000, 0.00,
0.0000, 0.0000, 0.0000, 1.00]
transform_data_filter.transform.matrix.__setstate__({'elements': Rt_c})
transform_data_filter.widget.set_transform(transform_data_filter.transform)
transform_data_filter.filter.update()
transform_data_filter.widget.enabled = False # disable the rotation control further.
# Add surface modules to each source
right_surface = Surface()
engine.add_filter(right_surface, sphere_h1_src)
left_surface = Surface()
engine.add_filter(left_surface, sphere_h2_src)
cyl_surface = Surface()
engine.add_filter(cyl_surface, transform_data_filter)
fig = mlab.figure()
# Add lens
lensUsingMayaviBuiltinSphere(radius=2, semiDiam=1.2)
mlab.show()
答案 0 :(得分:1)
我不知道如何以您想要的方式组合来源。我认为实际上这可能是不可能的,因为BuiltinSurface
对象具有特定的vtk源,而不是你想要的。然而,应该可以简单地使用提供您想要的不同来源。在这种情况下,您可以使用mlab.mesh
生成双凸透镜:
a,c,h=3,1,.2
phi,theta = np.mgrid[0:2*np.pi:np.pi/250, 0:2*np.pi:np.pi/250]
x=a*np.cos(theta)*np.sin(phi)
y=a*np.sin(theta)*np.sin(phi)
z=c*np.cos(phi)+(h*(-1)**(np.cos(phi)<0))
mlab.mesh(x,y,z,color=(1,1,1)
mlab.show()
一个小的区别是这个表面是光滑的。这是对单个表面进行采样的本质 - 即,这个结果是您的问题所要求的直接结果。如果这是你图中的一个重要特征,我建议采用一种完全不同的方法:将3个源包装在一个类中,让事件处理程序更新所有三个的相关属性。
答案 1 :(得分:1)
基于@aestrivex的代码,这是获得所需输出的一种方法(具有锐边的镜头)。请注意,这不是连接多个Mayavi对象的解决方案。
import numpy as np
from mayavi import mlab
# Control parameters
# r is the semi-diameter of the lens
# c controls the center thickness of the lens
# h controls the curvature of the surfaces (lesser the value more the curvature)
r, c, h = 3, .75, .9
delta_phi = np.pi/250.0 # phi == azimuth (0 <= phi <= pi)
delta_theta = np.pi/100.0 # theta == zenith (0 <= theta <= pi)
phi, theta = np.mgrid[0:2.0*np.pi + delta_phi:delta_phi,0:np.pi + delta_theta:delta_theta]
# The Exact threshold values for masking tz, txy will change depending upon the
# sampling of theta. txy is always slightly less than tz. tz should be around 0.3
tz, txy = 0.279, 0.275
x = r*np.sin(theta)*np.cos(phi)*(np.abs(np.cos(theta)) > txy)
y = r*np.sin(theta)*np.sin(phi)*(np.abs(np.cos(theta)) > txy)
z = c*np.cos(theta)*(h**(-1)*( np.abs(np.cos(theta)) > tz))
mlab.mesh(x,y,z,color=(1,1,1))
mlab.show()
这是输出: