Skip to content

Cannot add an Actor containing vtkUnstructuredGrid through TrameApp's callback function #865

@FemLearner

Description

@FemLearner

Describe the bug

I hope to dynamically add actors in the callback function input_calculate_file of the imported file, I found that vtkCubeSource can be added, but vtkUnstructuredGrid cannot . I put the function content of add_my_file() into TrameApp's pipeline initialization function _stupuvtk, and it succeeded.How ever, in the callback function input_calculate_file it did not work. Im my test example the VFileInput is just used to trigger the function input_calculate_file and the file is always "Mine_Res-20.000000hz-21840mesh-23218node.plt"

Image

Successful Code

from trame.app import TrameApp
from trame.decorators import change
from trame.ui.vuetify3 import SinglePageLayout,SinglePageWithDrawerLayout
from trame.widgets import vuetify3, vtklocal,trame
from trame.app import get_server
from trame.widgets import vtk as vtk_widgets
# Required for rendering initialization, not necessary for
# local rendering, but doesn't hurt to include it
import vtkmodules.vtkRenderingOpenGL2  # noqa
from trame_vtk.modules.vtk.serializers import configure_serializer
from vtkmodules.vtkCommonDataModel import vtkDataObject
from vtkmodules.vtkFiltersCore import vtkContourFilter
from vtkmodules.vtkFiltersSources import vtkConeSource, vtkCubeSource
import random
# Required for interactor initialization
import vtk
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch  # noqa
from vtkmodules.vtkIOXML import vtkXMLUnstructuredGridReader
from vtkmodules.vtkRenderingAnnotation import vtkCubeAxesActor
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkDataSetMapper,
    vtkPolyDataMapper,
    vtkRenderer,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
)

class Cone(TrameApp):
    def __init__(self, server=None):
        super().__init__(server)
        self._setup_vtk()
        self._build_ui()
        self.state.active_ui = None
        self.state.impot_success = False
        self.state.array_list = []
    def _setup_vtk(self):
        self.reader = None
        self.renderer = vtkRenderer()
        self.render_window = vtkRenderWindow()
        self.renderer.SetBackground(0.8, 0.8, 0.8)
        self.render_window.AddRenderer(self.renderer)
        self.renderWindowInteractor =vtkRenderWindowInteractor()
        self.renderWindowInteractor.SetRenderWindow(self.render_window)
        self.renderWindowInteractor.GetInteractorStyle().SetCurrentStyleToTrackballCamera()
        self.mesh_mapper = vtkDataSetMapper()
        self.mesh_actor = vtkActor()
        self.contour = vtkContourFilter()
        self.contour_mapper = vtkPolyDataMapper()
        self.contour_actor = vtkActor()
        self.contour_value = None
        self.default_max = 0
        self.default_min = 0
        self.cube_axes = vtkCubeAxesActor()
        self.dataset_arrays =[]

        reader = vtk.vtkTecplotReader()
        reader.SetFileName("Mine_Res-20.000000hz-21840mesh-23218node.plt")
        reader.Update()
        output = reader.GetOutput()
        # 处理多块数据集
        if output.IsA("vtkMultiBlockDataSet"):
            print("多块数据集,块数:", output.GetNumberOfBlocks())
            reader = None
            for i in range(output.GetNumberOfBlocks()):
                block = output.GetBlock(i)
                if block:
                    print(f"块{i}类型:", block.GetClassName())
                    if block.IsA("vtkUnstructuredGrid") and block.GetNumberOfPoints() > 0:
                        reader = block
                        print(f"选择块{i}作为网格")
                        break
            if reader is None:
                print("未找到有效的非结构网格块")
                exit()
        else:
            reader = output
        print("输出类型:", reader.GetClassName())
        print("点数:", reader.GetNumberOfPoints())
        print("单元数:", reader.GetNumberOfCells())
        # 检查网格有效性
        if not isinstance(reader, vtk.vtkUnstructuredGrid):
            print("错误:未能获取有效的非结构网格。")
            exit()
        # Extract Array/Field information
        dataset_arrays = []
        # 加载节点数据和声压数据
        fields = [
            (reader.GetPointData(), vtkDataObject.FIELD_ASSOCIATION_POINTS),
            (reader.GetCellData(), vtkDataObject.FIELD_ASSOCIATION_CELLS),
        ]

        for field in fields:
            field_arrays, association = field
            # reader.GetPointData()可能包含多组节点数据
            for i in range(field_arrays.GetNumberOfArrays()):
                array = field_arrays.GetArray(i)
                array_range = array.GetRange()
                dataset_arrays.append(
                    {
                        "text": array.GetName(),
                        "value": i,
                        "range": list(array_range),
                        "type": association,
                    }
                )
        default_array = dataset_arrays[2]
        self.default_min, self.default_max = default_array.get("range")
        self.reader=reader
        self.mesh_mapper.SetInputData(self.reader)
        self.mesh_actor.SetMapper(self.mesh_mapper)
        self.renderer.AddActor(self.mesh_actor)
        # Mesh: Setup default representation to surface
        self.mesh_actor.GetProperty().SetRepresentationToSurface()
        self.mesh_actor.GetProperty().SetPointSize(1)
        self.mesh_actor.GetProperty().EdgeVisibilityOn()

    def _build_ui(self):
        with SinglePageWithDrawerLayout(self.server) as layout:
            self.ui = layout

            layout.title.set_text("Acoustic Model")
            layout.icon.click = self.ctrl.view_reset_camera

            with layout.toolbar as toolbar:
                toolbar.density = "compact"
                vuetify3.VSpacer()
                vuetify3.VFileInput(
                    prepend_icon="mdi-vector-triangle",
                    v_model=("input_calculate_file", None),
                    label="input file",
                )
            with layout.content:
                # region widget
                with vtklocal.LocalView(
                    self.render_window,
                    throttle_rate=20,
                ) as view:
                    self.ctrl.view_update = view.update_throttle
                    self.ctrl.view_reset_camera = view.reset_camera
                # endregion widget

    @change("input_calculate_file")
    def input_calculate_file(self,input_calculate_file,**kwargs):
        if(input_calculate_file==None):
            return
        # cube actor
        cube_source = vtkCubeSource()
        cube_mapper = vtkPolyDataMapper()
        cube_mapper.SetInputConnection(cube_source.GetOutputPort())
        cube_actor = vtkActor()
        cube_actor.SetMapper(cube_mapper)
        r, g, b = random.random(), random.random(), random.random()
        x, y, z = random.uniform(-0.5, 0.5), random.uniform(-0.5, 0.5), random.uniform(-0.5, 0.5)
        cube_actor.GetProperty().SetColor(r, g, b)
        cube_actor.SetPosition(x, y, z)
        self.renderer.AddActor(cube_actor)
        self.ctrl.view_update()
        self.ctrl.view_reset_camera()
        #add another actor
        #self.add_my_file()

    def add_my_file(self):
        # add another actor(afiled)
        reader = vtk.vtkTecplotReader()
        reader.SetFileName("Mine_Res-20.000000hz-21840mesh-23218node.plt")
        reader.Update()
        output = reader.GetOutput()
        # 处理多块数据集
        if output.IsA("vtkMultiBlockDataSet"):
            print("多块数据集,块数:", output.GetNumberOfBlocks())
            reader = None
            for i in range(output.GetNumberOfBlocks()):
                block = output.GetBlock(i)
                if block:
                    print(f"块{i}类型:", block.GetClassName())
                    if block.IsA("vtkUnstructuredGrid") and block.GetNumberOfPoints() > 0:
                        reader = block
                        print(f"选择块{i}作为网格")
                        break
            if reader is None:
                print("未找到有效的非结构网格块")
                exit()
        else:
            reader = output
        print("输出类型:", reader.GetClassName())
        print("点数:", reader.GetNumberOfPoints())
        print("单元数:", reader.GetNumberOfCells())
        # 检查网格有效性
        if not isinstance(reader, vtk.vtkUnstructuredGrid):
            print("错误:未能获取有效的非结构网格。")
            exit()
        # Extract Array/Field information
        dataset_arrays = []
        # 加载节点数据和声压数据
        fields = [
            (reader.GetPointData(), vtkDataObject.FIELD_ASSOCIATION_POINTS),
            (reader.GetCellData(), vtkDataObject.FIELD_ASSOCIATION_CELLS),
        ]

        for field in fields:
            field_arrays, association = field
            # reader.GetPointData()可能包含多组节点数据
            for i in range(field_arrays.GetNumberOfArrays()):
                array = field_arrays.GetArray(i)
                array_range = array.GetRange()
                dataset_arrays.append(
                    {
                        "text": array.GetName(),
                        "value": i,
                        "range": list(array_range),
                        "type": association,
                    }
                )
        default_array = dataset_arrays[2]
        self.default_min, self.default_max = default_array.get("range")
        self.reader=reader
        self.mesh_mapper.SetInputData(self.reader)
        self.mesh_actor.SetMapper(self.mesh_mapper)
        self.renderer.AddActor(self.mesh_actor)
        # Mesh: Setup default representation to surface
        self.mesh_actor.GetProperty().SetRepresentationToSurface()
        self.mesh_actor.GetProperty().SetPointSize(1)
        self.mesh_actor.GetProperty().EdgeVisibilityOn()
        self.ctrl.view_update()
        self.ctrl.view_reset_camera()
def main():
    app = Cone()
    app.server.start(port=8088)

if __name__ == "__main__":
    main()

Failedl Code

from trame.app import TrameApp
from trame.decorators import change
from trame.ui.vuetify3 import SinglePageLayout,SinglePageWithDrawerLayout
from trame.widgets import vuetify3, vtklocal,trame
from trame.app import get_server
from trame.widgets import vtk as vtk_widgets
# Required for rendering initialization, not necessary for
# local rendering, but doesn't hurt to include it
import vtkmodules.vtkRenderingOpenGL2  # noqa
from trame_vtk.modules.vtk.serializers import configure_serializer
from vtkmodules.vtkCommonDataModel import vtkDataObject
from vtkmodules.vtkFiltersCore import vtkContourFilter
from vtkmodules.vtkFiltersSources import vtkConeSource, vtkCubeSource
import random
# Required for interactor initialization
import vtk
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch  # noqa
from vtkmodules.vtkIOXML import vtkXMLUnstructuredGridReader
from vtkmodules.vtkRenderingAnnotation import vtkCubeAxesActor
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkDataSetMapper,
    vtkPolyDataMapper,
    vtkRenderer,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
)

class Cone(TrameApp):
    def __init__(self, server=None):
        super().__init__(server)
        self._setup_vtk()
        self._build_ui()
        self.state.active_ui = None
        self.state.impot_success = False
        self.state.array_list = []
    def _setup_vtk(self):
        self.reader = None
        self.renderer = vtkRenderer()
        self.render_window = vtkRenderWindow()
        self.renderer.SetBackground(0.8, 0.8, 0.8)
        self.render_window.AddRenderer(self.renderer)
        self.renderWindowInteractor =vtkRenderWindowInteractor()
        self.renderWindowInteractor.SetRenderWindow(self.render_window)
        self.renderWindowInteractor.GetInteractorStyle().SetCurrentStyleToTrackballCamera()
        self.mesh_mapper = vtkDataSetMapper()
        self.mesh_actor = vtkActor()
        self.contour = vtkContourFilter()
        self.contour_mapper = vtkPolyDataMapper()
        self.contour_actor = vtkActor()
        self.contour_value = None
        self.default_max = 0
        self.default_min = 0
        self.cube_axes = vtkCubeAxesActor()
        self.dataset_arrays =[]

    def _build_ui(self):
        with SinglePageWithDrawerLayout(self.server) as layout:
            self.ui = layout

            layout.title.set_text("Acoustic Model")
            layout.icon.click = self.ctrl.view_reset_camera

            with layout.toolbar as toolbar:
                toolbar.density = "compact"
                vuetify3.VSpacer()
                vuetify3.VFileInput(
                    prepend_icon="mdi-vector-triangle",
                    v_model=("input_calculate_file", None),
                    label="input file",
                )
            with layout.content:
                # region widget
                with vtklocal.LocalView(
                    self.render_window,
                    throttle_rate=20,
                ) as view:
                    self.ctrl.view_update = view.update_throttle
                    self.ctrl.view_reset_camera = view.reset_camera
                # endregion widget

    @change("input_calculate_file")
    def input_calculate_file(self,input_calculate_file,**kwargs):
        if(input_calculate_file==None):
            return
        # cube actor
        cube_source = vtkCubeSource()
        cube_mapper = vtkPolyDataMapper()
        cube_mapper.SetInputConnection(cube_source.GetOutputPort())
        cube_actor = vtkActor()
        cube_actor.SetMapper(cube_mapper)
        r, g, b = random.random(), random.random(), random.random()
        x, y, z = random.uniform(-0.5, 0.5), random.uniform(-0.5, 0.5), random.uniform(-0.5, 0.5)
        cube_actor.GetProperty().SetColor(r, g, b)
        cube_actor.SetPosition(x, y, z)
        self.renderer.AddActor(cube_actor)
        self.ctrl.view_update()
        self.ctrl.view_reset_camera()
        #add another actor
        self.add_my_file()
        self.ctrl.view_update()
        self.ctrl.view_reset_camera()
    def add_my_file(self):
        # add another actor(afiled)
        reader = vtk.vtkTecplotReader()
        reader.SetFileName("Mine_Res-20.000000hz-21840mesh-23218node.plt")
        reader.Update()
        output = reader.GetOutput()
        # 处理多块数据集
        if output.IsA("vtkMultiBlockDataSet"):
            print("多块数据集,块数:", output.GetNumberOfBlocks())
            reader = None
            for i in range(output.GetNumberOfBlocks()):
                block = output.GetBlock(i)
                if block:
                    print(f"块{i}类型:", block.GetClassName())
                    if block.IsA("vtkUnstructuredGrid") and block.GetNumberOfPoints() > 0:
                        reader = block
                        print(f"选择块{i}作为网格")
                        break
            if reader is None:
                print("未找到有效的非结构网格块")
                exit()
        else:
            reader = output
        print("输出类型:", reader.GetClassName())
        print("点数:", reader.GetNumberOfPoints())
        print("单元数:", reader.GetNumberOfCells())
        # 检查网格有效性
        if not isinstance(reader, vtk.vtkUnstructuredGrid):
            print("错误:未能获取有效的非结构网格。")
            exit()
        # Extract Array/Field information
        dataset_arrays = []
        # 加载节点数据和声压数据
        fields = [
            (reader.GetPointData(), vtkDataObject.FIELD_ASSOCIATION_POINTS),
            (reader.GetCellData(), vtkDataObject.FIELD_ASSOCIATION_CELLS),
        ]

        for field in fields:
            field_arrays, association = field
            # reader.GetPointData()可能包含多组节点数据
            for i in range(field_arrays.GetNumberOfArrays()):
                array = field_arrays.GetArray(i)
                array_range = array.GetRange()
                dataset_arrays.append(
                    {
                        "text": array.GetName(),
                        "value": i,
                        "range": list(array_range),
                        "type": association,
                    }
                )
        default_array = dataset_arrays[2]
        self.default_min, self.default_max = default_array.get("range")
        self.reader=reader
        self.mesh_mapper.SetInputData(self.reader)
        self.mesh_actor.SetMapper(self.mesh_mapper)
        self.renderer.AddActor(self.mesh_actor)
        # Mesh: Setup default representation to surface
        self.mesh_actor.GetProperty().SetRepresentationToSurface()
        self.mesh_actor.GetProperty().SetPointSize(1)
        self.mesh_actor.GetProperty().EdgeVisibilityOn()
        self.ctrl.view_update()
        self.ctrl.view_reset_camera()
def main():
    app = Cone()
    app.server.start(port=8088)

if __name__ == "__main__":
    main()

Mine_Res-20.000000hz-21840mesh-23218node.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions