2014-03-07 129 views
2

我想將多個Mayavi對象合併爲一個「分組」對象,這樣我就可以將它們的所有屬性控制在一起。例如,我通過組合3個內置曲面(兩個球體和一個圓柱體)創建了以下雙凸透鏡形狀。現在我想要將統一的屬性(鏡面度,環境顏色等)分配給所有組成曲面(不是單獨)。另外,我想整體翻譯/旋轉鏡頭。我不知道如何做到這一點。如何在Mayavi2中連接/連接/分組多個對象

這裏是Mayavi的創建的雙凸透鏡(下面給出代碼):

enter image description here

正如它可以在下面的圖中可以看出,上述的透鏡由三個表面:

enter image description here


這裏是代碼用於構建雙凸透鏡:


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

回答

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

enter image description here

一個微小的差別是,這個表面是光滑的。這是抽樣單一表面的本質 - 即,這個結果是你的問題要求做的直接結果。如果這是圖形的一個重要特徵,我會建議一種完全不同的方法:將3個源代碼包裝到一個類中,並讓事件處理程序更新所有三個相關屬性。

+0

非常感謝您的回覆。我一定會嘗試你後來建議的第二種方法。現在,我正在試圖解決方案1.但是,我認爲這條線'z = c * np.cos(phi)*(h *( - 1)**(np.cos(phi)<0 ))'可能缺少一塊。你可以仔細檢查一下嗎?另外,你的例子激勵我添加一些東西來獲得我想要的「邊緣」。我將這些代碼和數字放在一個單獨的答案中(因爲註釋部分非常小) –

+1

是的,它應該是'z = c * np.cos(phi)+(h *( - 1)**(np。 cos(phi)<0))','+'不是'*'。抱歉。 – aestrivex

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

這裏是輸出: enter image description here