Камера синхронизации Mayavi

Я следую сценарию, указанному на официальном сайте mayaVI (Пример нескольких моделей сцен mlab) и хотел бы использовать команду sync_camera для синхронизации двух фигур вместе в графическом интерфейсе qt (как показано), чтобы любое вращение/масштабирование и т. д. на одной фигуре автоматически поворачивало/масштабировало и т. д. другую в точно таким же образом, в то же время.

Команда sync_camera кратко описана на другой официальной странице mayaVI Функции обработки рисунков, но мне не удалось найти много информации о его правильном использовании для успешного использования в иерархии классов.

Есть ли у кого-нибудь опыт этой процедуры или совет?

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

person evambivalence    schedule 06.02.2018    source источник


Ответы (1)


Решение состоит в том, чтобы не использовать метод 2 фигур в 1 (как было изначально опубликовано), а создать 2 отдельные фигуры. Для своих нужд я переписал первоначальный код таким образом, что каждая фигура находится в своем собственном классе, а затем просто поместил их в новый кадр рядом. Я не думаю, что использование функции 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_())       

Однако в моей собственной версии я использую два разных источника данных на каждом графике (один график рассеяния, а другой контурный график, причем интересующее начало контурного графика отличается от графика рассеяния), и из-за подключения камеры , ни один из них не отображается на экране одновременно с другим (исходные координаты у обоих разные).

Таким образом, если вы видите только один из трехмерных объектов в кадре за раз, отрегулируйте положение внутри 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 (с нажатой красной лампочкой, чтобы увидеть выходной код в режиме реального времени), чтобы настроить ваши графики по мере необходимости. Если кому-то нужна дополнительная помощь с этим в будущем, пожалуйста, дайте мне знать.

person evambivalence    schedule 15.02.2018