Mayavi 同步相机
Mayavi Sync Camera
我正在按照官方 mayaVI 站点 (Multiple mlab scene models example) 提供的脚本进行操作,并希望使用 sync_camera
命令在 qt GUI 中将两个图形同步在一起(就像显示),使得一个图中的任何 rotation/zoom 等自动 rotates/zooms 等以完全相同的方式同时出现在另一个图中。
sync_camera
命令在另一个官方 mayaVI 页面 Figure handling functions 上有简要介绍,但我没能在 class层次结构。
有没有人对此程序有任何经验或建议?
import numpy as np
from traits.api import HasTraits, Instance, Button, \
on_trait_change
from traitsui.api import View, Item, HSplit, Group
from mayavi import mlab
from mayavi.core.ui.api import MlabSceneModel, SceneEditor
class MyDialog(HasTraits):
scene1 = Instance(MlabSceneModel, ())
scene2 = Instance(MlabSceneModel, ())
button1 = Button('Redraw')
button2 = Button('Redraw')
@on_trait_change('button1')
def redraw_scene1(self):
self.redraw_scene(self.scene1)
@on_trait_change('button2')
def redraw_scene2(self):
self.redraw_scene(self.scene2)
def redraw_scene(self, scene):
# Notice how each mlab call points explicitely to the figure it
# applies to.
mlab.clf(figure=scene.mayavi_scene)
x, y, z, s = np.random.random((4, 100))
mlab.points3d(x, y, z, s, figure=scene.mayavi_scene)
# The layout of the dialog created
view = View(HSplit(
Group(
Item('scene1',
editor=SceneEditor(), height=250,
width=300),
'button1',
show_labels=False,
),
Group(
Item('scene2',
editor=SceneEditor(), height=250,
width=300, show_label=False),
'button2',
show_labels=False,
),
),
resizable=True,
)
m = MyDialog()
m.configure_traits()
解决方案是不使用 2-figure-in-1 方法(如最初发布的那样),而是创建 2 个单独的图形。为了我的需要,我重写了初始代码,使每个图形都在它自己的 class 中,然后简单地将它们并排放置在一个新的框架中。如果没有这种分离,我认为使用 sync_camera
函数是不可能的,因为它需要两个单独的图形作为输入。结果基本相同。我成功实现了sync_camera函数如下:
import sys, os, time
import numpy as np
os.environ['ETS_TOOLKIT'] = 'qt4'
from pyface.qt import QtGui, QtCore
from traits.api import HasTraits, Instance, on_trait_change, Str, Float, Range
from traitsui.api import View, Item, HSplit, Group
from mayavi import mlab
from mayavi.core.api import PipelineBase, Engine
from mayavi.core.ui.api import MayaviScene, MlabSceneModel, SceneEditor
class Mayavi1(HasTraits):
scene = Instance(MlabSceneModel, ())
@on_trait_change('scene.activated')
def update_plot(self):
Mayavi1.fig1 = mlab.figure(1)
self.scene.mlab.clf(figure=Mayavi1.fig1)
x, y, z, s = np.random.random((4, 100))
splot = self.scene.mlab.points3d(x, y, z, s, figure=Mayavi1.fig1)
#splot.actor.actor.scale = np.array([25,25,25]) #if plot-types different
view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene),
height=300, width=300, show_label=False),
resizable=True
)
class Mayavi2(HasTraits):
scene = Instance(MlabSceneModel, ())
@on_trait_change('scene.activated')
def update_plot(self):
Mayavi2.fig2 = mlab.figure(2)
self.scene.mlab.clf(figure=Mayavi2.fig2)
x, y, z, s = np.random.random((4, 100))
cplot = self.scene.mlab.points3d(x, y, z, s, figure=Mayavi2.fig2)
#cplot.actor.actor.position = np.array([1,1,1]) #if plot-types different
view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene),
height=300, width=300, show_label=False),
resizable=True
)
class P1(QtGui.QWidget):
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QtGui.QGridLayout(self)
layout.setContentsMargins(20,20,20,20) #W,N,E,S
layout.setSpacing(10)
self.visualization1 = Mayavi1()
self.ui1 = self.visualization1.edit_traits(parent=self, kind='subpanel').control
layout.addWidget(self.ui1, 0, 0, 1, 1)
self.ui1.setParent(self)
self.visualization2 = Mayavi2()
self.ui2 = self.visualization2.edit_traits(parent=self, kind='subpanel').control
layout.addWidget(self.ui2, 0, 2, 1, 1)
self.ui2.setParent(self)
mlab.sync_camera(self.visualization1,self.visualization2)
mlab.sync_camera(self.visualization2,self.visualization1)
#self.visualization1.scene.mlab.view(0,0,10,[1,1,1])
class Hierarchy(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Hierarchy, self).__init__(parent)
self.setGeometry(50, 50, 400, 400) #(int x, int y, int w, int h)
self.gotoP1()
def gotoP1(self):
self.P1f = P1(self)
self.setWindowTitle("Page1")
self.setCentralWidget(self.P1f)
self.show()
if __name__ == '__main__':
app = QtGui.QApplication.instance()
#app = QtGui.QApplication(sys.argv)
w = Hierarchy()
sys.exit(app.exec_())
但是,在我自己的版本中,我在每个图中使用了两个不同的数据源(一个是散点图,另一个是等高线图,等高线图的兴趣来源与散点图不同),并且由于摄像头连接,两者都没有同时出现在屏幕上(两者的原始坐标不同)。
因此,如果您一次只看到框架中的一个 3d 对象,请调整任一图形在 def update_plot(self)
中的位置,直到它们同时出现在屏幕上。这可以通过以下命令完成:
splot.actor.actor.scale = np.array([25,25,25]) #with splot for fig1
cplot.actor.actor.position = np.array([-64,-64,-64]) #with cplot for fig2
我强烈建议实际进入 mayaVI 管道(单击红灯以查看 real-time 中的输出代码)以根据需要调整绘图。如果有人在这方面需要任何进一步的帮助,请告诉我。
我正在按照官方 mayaVI 站点 (Multiple mlab scene models example) 提供的脚本进行操作,并希望使用 sync_camera
命令在 qt GUI 中将两个图形同步在一起(就像显示),使得一个图中的任何 rotation/zoom 等自动 rotates/zooms 等以完全相同的方式同时出现在另一个图中。
sync_camera
命令在另一个官方 mayaVI 页面 Figure handling functions 上有简要介绍,但我没能在 class层次结构。
有没有人对此程序有任何经验或建议?
import numpy as np
from traits.api import HasTraits, Instance, Button, \
on_trait_change
from traitsui.api import View, Item, HSplit, Group
from mayavi import mlab
from mayavi.core.ui.api import MlabSceneModel, SceneEditor
class MyDialog(HasTraits):
scene1 = Instance(MlabSceneModel, ())
scene2 = Instance(MlabSceneModel, ())
button1 = Button('Redraw')
button2 = Button('Redraw')
@on_trait_change('button1')
def redraw_scene1(self):
self.redraw_scene(self.scene1)
@on_trait_change('button2')
def redraw_scene2(self):
self.redraw_scene(self.scene2)
def redraw_scene(self, scene):
# Notice how each mlab call points explicitely to the figure it
# applies to.
mlab.clf(figure=scene.mayavi_scene)
x, y, z, s = np.random.random((4, 100))
mlab.points3d(x, y, z, s, figure=scene.mayavi_scene)
# The layout of the dialog created
view = View(HSplit(
Group(
Item('scene1',
editor=SceneEditor(), height=250,
width=300),
'button1',
show_labels=False,
),
Group(
Item('scene2',
editor=SceneEditor(), height=250,
width=300, show_label=False),
'button2',
show_labels=False,
),
),
resizable=True,
)
m = MyDialog()
m.configure_traits()
解决方案是不使用 2-figure-in-1 方法(如最初发布的那样),而是创建 2 个单独的图形。为了我的需要,我重写了初始代码,使每个图形都在它自己的 class 中,然后简单地将它们并排放置在一个新的框架中。如果没有这种分离,我认为使用 sync_camera
函数是不可能的,因为它需要两个单独的图形作为输入。结果基本相同。我成功实现了sync_camera函数如下:
import sys, os, time
import numpy as np
os.environ['ETS_TOOLKIT'] = 'qt4'
from pyface.qt import QtGui, QtCore
from traits.api import HasTraits, Instance, on_trait_change, Str, Float, Range
from traitsui.api import View, Item, HSplit, Group
from mayavi import mlab
from mayavi.core.api import PipelineBase, Engine
from mayavi.core.ui.api import MayaviScene, MlabSceneModel, SceneEditor
class Mayavi1(HasTraits):
scene = Instance(MlabSceneModel, ())
@on_trait_change('scene.activated')
def update_plot(self):
Mayavi1.fig1 = mlab.figure(1)
self.scene.mlab.clf(figure=Mayavi1.fig1)
x, y, z, s = np.random.random((4, 100))
splot = self.scene.mlab.points3d(x, y, z, s, figure=Mayavi1.fig1)
#splot.actor.actor.scale = np.array([25,25,25]) #if plot-types different
view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene),
height=300, width=300, show_label=False),
resizable=True
)
class Mayavi2(HasTraits):
scene = Instance(MlabSceneModel, ())
@on_trait_change('scene.activated')
def update_plot(self):
Mayavi2.fig2 = mlab.figure(2)
self.scene.mlab.clf(figure=Mayavi2.fig2)
x, y, z, s = np.random.random((4, 100))
cplot = self.scene.mlab.points3d(x, y, z, s, figure=Mayavi2.fig2)
#cplot.actor.actor.position = np.array([1,1,1]) #if plot-types different
view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene),
height=300, width=300, show_label=False),
resizable=True
)
class P1(QtGui.QWidget):
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QtGui.QGridLayout(self)
layout.setContentsMargins(20,20,20,20) #W,N,E,S
layout.setSpacing(10)
self.visualization1 = Mayavi1()
self.ui1 = self.visualization1.edit_traits(parent=self, kind='subpanel').control
layout.addWidget(self.ui1, 0, 0, 1, 1)
self.ui1.setParent(self)
self.visualization2 = Mayavi2()
self.ui2 = self.visualization2.edit_traits(parent=self, kind='subpanel').control
layout.addWidget(self.ui2, 0, 2, 1, 1)
self.ui2.setParent(self)
mlab.sync_camera(self.visualization1,self.visualization2)
mlab.sync_camera(self.visualization2,self.visualization1)
#self.visualization1.scene.mlab.view(0,0,10,[1,1,1])
class Hierarchy(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Hierarchy, self).__init__(parent)
self.setGeometry(50, 50, 400, 400) #(int x, int y, int w, int h)
self.gotoP1()
def gotoP1(self):
self.P1f = P1(self)
self.setWindowTitle("Page1")
self.setCentralWidget(self.P1f)
self.show()
if __name__ == '__main__':
app = QtGui.QApplication.instance()
#app = QtGui.QApplication(sys.argv)
w = Hierarchy()
sys.exit(app.exec_())
但是,在我自己的版本中,我在每个图中使用了两个不同的数据源(一个是散点图,另一个是等高线图,等高线图的兴趣来源与散点图不同),并且由于摄像头连接,两者都没有同时出现在屏幕上(两者的原始坐标不同)。
因此,如果您一次只看到框架中的一个 3d 对象,请调整任一图形在 def update_plot(self)
中的位置,直到它们同时出现在屏幕上。这可以通过以下命令完成:
splot.actor.actor.scale = np.array([25,25,25]) #with splot for fig1
cplot.actor.actor.position = np.array([-64,-64,-64]) #with cplot for fig2
我强烈建议实际进入 mayaVI 管道(单击红灯以查看 real-time 中的输出代码)以根据需要调整绘图。如果有人在这方面需要任何进一步的帮助,请告诉我。