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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions