首页 新闻 会员 周边 捐助

trame实现网页上传vtu文件并进行渲染问题

0
悬赏园豆:100 [已解决问题] 解决于 2025-07-01 20:41

我在使用trame实现网页上传vtu文件并进行渲染时遇到了问题。使用内置路径第一次渲染时没有问题,但我上传另外一个vtu文件进行渲染时,前端还是之前第一个文件。这个问题困扰我好久了,十分感谢!
第一文件运行截图

第二个文件上传后出现问题

import os
from trame.decorators import TrameApp
from trame.app import get_server
from trame.ui.vuetify import SinglePageWithDrawerLayout
from trame.widgets import vtk, vuetify, trame
from pathlib import Path
from trame_vtk.modules.vtk.serializers import configure_serializer
 
from vtkmodules.vtkCommonDataModel import vtkDataObject
from vtkmodules.vtkFiltersCore import vtkContourFilter
from vtkmodules.vtkIOXML import vtkXMLUnstructuredGridReader
from vtkmodules.vtkRenderingAnnotation import vtkCubeAxesActor
from trame.widgets import vuetify
from trame.app.file_upload import ClientFile
from trame.widgets import html
 
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkDataSetMapper,
    vtkRenderer,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
)
 
# Required for interactor initialization
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch  # noqa
 
# Required for rendering initialization, not necessary for
# local rendering, but doesn't hurt to include it
import vtkmodules.vtkRenderingOpenGL2  # noqa
 
import rendering
 
CURRENT_DIRECTORY = os.path.abspath(os.path.dirname(__file__))
 
# Configure scene encoder
configure_serializer(encode_lut=True, skip_light=True)
 
# -----------------------------------------------------------------------------
# Constants
# -----------------------------------------------------------------------------
 
 
class Representation:
    Points = 0
    Wireframe = 1
    Surface = 2
    SurfaceWithEdges = 3
 
 
class LookupTable:
    Rainbow = 0
    Inverted_Rainbow = 1
    Greyscale = 2
    Inverted_Greyscale = 3
 
 
# -----------------------------------------------------------------------------
# VTK pipeline
# -----------------------------------------------------------------------------
reader = vtkXMLUnstructuredGridReader()
mesh_mapper = vtkDataSetMapper()
contour_mapper = vtkDataSetMapper()
mesh_actor = vtkActor()
contour_actor = vtkActor()
contour = vtkContourFilter()
renderer = vtkRenderer()
renderWindow = vtkRenderWindow()
 
def create_vtk_pipeline(file_name):
 
 
    renderer = vtkRenderer()
    renderWindow = vtkRenderWindow()
    renderWindow.AddRenderer(renderer)
 
    renderWindowInteractor = vtkRenderWindowInteractor()
    renderWindowInteractor.SetRenderWindow(renderWindow)
    renderWindowInteractor.GetInteractorStyle().SetCurrentStyleToTrackballCamera()
 
 
    # Read Data
    reader = vtkXMLUnstructuredGridReader()
    reader.SetFileName(file_name)
    reader.Update()
 
    data = reader.GetOutput()
 
    # Extract Array/Field information
    dataset_arrays = []
    fields = [
        (reader.GetOutput().GetPointData(), vtkDataObject.FIELD_ASSOCIATION_POINTS),
        (reader.GetOutput().GetCellData(), vtkDataObject.FIELD_ASSOCIATION_CELLS),
    ]
    for field in fields:
        field_arrays, association = field
        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[0]
    default_min, default_max = default_array.get("range")
 
    # Mesh
    mesh_mapper = vtkDataSetMapper()
    mesh_mapper.SetInputConnection(reader.GetOutputPort())
    mesh_actor = vtkActor()
    mesh_actor.SetMapper(mesh_mapper)
    renderer.AddActor(mesh_actor)
    # Mesh: Setup default representation to surface
    mesh_actor.GetProperty().SetRepresentationToSurface()
    mesh_actor.GetProperty().SetPointSize(1)
    mesh_actor.GetProperty().EdgeVisibilityOff()
 
    # Mesh: Apply rainbow color map
    mesh_lut = mesh_mapper.GetLookupTable()
    mesh_lut.SetHueRange(0.666, 0.0)
    mesh_lut.SetSaturationRange(1.0, 1.0)
    mesh_lut.SetValueRange(1.0, 1.0)
    mesh_lut.Build()
 
    # Mesh: Color by default array
    mesh_mapper.SelectColorArray(default_array.get("text"))
    mesh_mapper.GetLookupTable().SetRange(default_min, default_max)
    if default_array.get("type") == vtkDataObject.FIELD_ASSOCIATION_POINTS:
        mesh_mapper.SetScalarModeToUsePointFieldData()
    else:
        mesh_mapper.SetScalarModeToUseCellFieldData()
    mesh_mapper.SetScalarVisibility(True)
    mesh_mapper.SetUseLookupTableScalarRange(True)
 
    mesh_mapper.Update()    ###
 
    # Contour
    contour = vtkContourFilter()
    contour.SetInputConnection(reader.GetOutputPort())
    contour_mapper = vtkDataSetMapper()
    contour_mapper.SetInputConnection(contour.GetOutputPort())
    contour_actor = vtkActor()
    contour_actor.SetMapper(contour_mapper)
    renderer.AddActor(contour_actor)
 
    # Contour: ContourBy default array
    contour_value = 0.5 * (default_max + default_min)
    contour.SetInputArrayToProcess(
        0, 0, 0, default_array.get("type"), default_array.get("text")
    )
    contour.SetValue(0, contour_value)
    # Contour: Setup default representation to surface
    contour_actor.GetProperty().SetRepresentationToSurface()
    contour_actor.GetProperty().SetPointSize(1)
    contour_actor.GetProperty().EdgeVisibilityOff()
 
    # Contour: Apply rainbow color map
    contour_lut = contour_mapper.GetLookupTable()
    contour_lut.SetHueRange(0.666, 0.0)
    contour_lut.SetSaturationRange(1.0, 1.0)
    contour_lut.SetValueRange(1.0, 1.0)
    contour_lut.Build()
 
    # Contour: Color by default array
    contour_mapper.SelectColorArray(default_array.get("text"))
    contour_mapper.GetLookupTable().SetRange(default_min, default_max)
    if default_array.get("type") == vtkDataObject.FIELD_ASSOCIATION_POINTS:
        contour_mapper.SetScalarModeToUsePointFieldData()
    else:
        contour_mapper.SetScalarModeToUseCellFieldData()
    contour_mapper.SetScalarVisibility(True)
    contour_mapper.SetUseLookupTableScalarRange(True)
 
    # Cube Axes
    cube_axes = vtkCubeAxesActor()
    renderer.AddActor(cube_axes)
 
    # Cube Axes: Boundaries, camera, and styling
    cube_axes.SetBounds(mesh_actor.GetBounds())
    cube_axes.SetCamera(renderer.GetActiveCamera())
    cube_axes.SetXLabelFormat("%6.1f")
    cube_axes.SetYLabelFormat("%6.1f")
    cube_axes.SetZLabelFormat("%6.1f")
    cube_axes.SetFlyModeToOuterEdges()
 
    renderer.ResetCamera()
    renderer.ResetCameraClippingRange()
    renderWindow.Render()
 
 
    return renderWindow, cube_axes, mesh_actor, contour_actor, mesh_mapper, dataset_arrays, contour, contour_value, default_min, default_max, renderer
 
 
 
@TrameApp()
class MyApp:
    def __init__(self, server=None):
        self.server = get_server(client_type="vue2")
        self.state = self.server.state
        self.ctrl = self.server.controller
        self.state.setdefault("active_ui", None)
        file_name = "../data/disk_out_ref.vtu"
 
 
        self.renderWindow, self.cube_axes, self.mesh_actor, self.contour_actor, self.mesh_mapper, self.dataset_arrays, self.contour, self.contour_value, self.default_min, self.default_max, self.renderer= create_vtk_pipeline(
            file_name)
        self.server.state.update(dict(mem_blob=0, mem_vtk=0))
        self.html_view = None
        self.ui =self._ui()
        # print(self.ui)
        self.state.change("cube_axes_visibility")(self.update_cube_axes_visibility)
        self.state.change("mesh_representation")(self.update_mesh_representation)
        self.state.change("contour_representation")(self.update_contour_representation)
        self.state.change("mesh_color_array_idx")(self.update_mesh_color_by_name)
        self.state.change("contour_color_array_idx")(self.update_contour_color_by_name)
        self.state.change("mesh_color_preset")(self.update_mesh_color_preset)
        self.state.change("contour_color_preset")(self.update_contour_color_preset)####
        self.state.change("mesh_opacity")(self.update_mesh_opacity)
        self.state.change("contour_opacity")(self.update_contour_opacity)
        self.state.change("contour_by_array_idx")(self.update_contour_by)
        self.state.change("contour_value")(self.update_contour_value)
 
 
 
    def update_cube_axes_visibility(self, cube_axes_visibility, **kwargs):
        self.cube_axes.SetVisibility(cube_axes_visibility)
        self.ctrl.view_update()
    # Selection Change
    def actives_change(self, ids):
        _id = ids[0]
        if _id == "1":  # Mesh
            self.state.active_ui = "mesh"
        elif _id == "2":  # Contour
            self.state.active_ui = "contour"
        else:
            self.state.active_ui = "nothing"
    # Visibility Change
    def visibility_change(self, event):
        _id = event["id"]
        _visibility = event["visible"]
        if _id == "1":  # Mesh
            self.mesh_actor.SetVisibility(_visibility)
        elif _id == "2":  # Contour
            self.contour_actor.SetVisibility(_visibility)
        self.ctrl.view_update()
    # Representation Callbacks
    def update_representation(self, actor, mode):
        property = actor.GetProperty()
        if mode == Representation.Points:
            property.SetRepresentationToPoints()
            property.SetPointSize(5)
            property.EdgeVisibilityOff()
        elif mode == Representation.Wireframe:
            property.SetRepresentationToWireframe()
            property.SetPointSize(1)
            property.EdgeVisibilityOff()
        elif mode == Representation.Surface:
            property.SetRepresentationToSurface()
            property.SetPointSize(1)
            property.EdgeVisibilityOff()
        elif mode == Representation.SurfaceWithEdges:
            property.SetRepresentationToSurface()
            property.SetPointSize(1)
            property.EdgeVisibilityOn()
 
    def update_mesh_representation(self, mesh_representation, **kwargs):
        self.update_representation(self.mesh_actor, mesh_representation)
        self.ctrl.view_update()
 
    def update_contour_representation(self, contour_representation, **kwargs):
        self.update_representation(self.contour_actor, contour_representation)
        self.ctrl.view_update()
    # Color By Callbacks
    def color_by_array(self, actor, array):
        _min, _max = array.get("range")
        mapper = actor.GetMapper()
        mapper.SelectColorArray(array.get("text"))
        mapper.GetLookupTable().SetRange(_min, _max)
        if array.get("type") == vtkDataObject.FIELD_ASSOCIATION_POINTS:
            self.mesh_mapper.SetScalarModeToUsePointFieldData()
        else:
            self.mesh_mapper.SetScalarModeToUseCellFieldData()
        mapper.SetScalarVisibility(True)
        mapper.SetUseLookupTableScalarRange(True)
 
    def update_mesh_color_by_name(self, mesh_color_array_idx, **kwargs):
        array = self.dataset_arrays[mesh_color_array_idx]
        self.color_by_array(self.mesh_actor, array)
        self.ctrl.view_update()
 
    def update_contour_color_by_name(self, contour_color_array_idx, **kwargs):
        array = self.dataset_arrays[contour_color_array_idx]
        self.color_by_array(self.contour_actor, array)
        self.ctrl.view_update()
    # Color Map Callbacks
    def use_preset(self, actor, preset):
        lut = actor.GetMapper().GetLookupTable()
        if preset == LookupTable.Rainbow:
            lut.SetHueRange(0.666, 0.0)
            lut.SetSaturationRange(1.0, 1.0)
            lut.SetValueRange(1.0, 1.0)
        elif preset == LookupTable.Inverted_Rainbow:
            lut.SetHueRange(0.0, 0.666)
            lut.SetSaturationRange(1.0, 1.0)
            lut.SetValueRange(1.0, 1.0)
        elif preset == LookupTable.Greyscale:
            lut.SetHueRange(0.0, 0.0)
            lut.SetSaturationRange(0.0, 0.0)
            lut.SetValueRange(0.0, 1.0)
        elif preset == LookupTable.Inverted_Greyscale:
            lut.SetHueRange(0.0, 0.666)
            lut.SetSaturationRange(0.0, 0.0)
            lut.SetValueRange(1.0, 0.0)
        lut.Build()
 
    def update_mesh_color_preset(self, mesh_color_preset, **kwargs):
        self.use_preset(self.mesh_actor, mesh_color_preset)
        self.ctrl.view_update()
 
    def update_contour_color_preset(self, contour_color_preset, **kwargs):
        self.use_preset(self.contour_actor, contour_color_preset)
        self.ctrl.view_update()
    # Opacity Callbacks
 
    def update_mesh_opacity(self, mesh_opacity, **kwargs):
        self.mesh_actor.GetProperty().SetOpacity(mesh_opacity)
        self.ctrl.view_update()
 
    def update_contour_opacity(self, contour_opacity, **kwargs):
        self.contour_actor.GetProperty().SetOpacity(contour_opacity)
        self.ctrl.view_update()
    # Contour Callbacks
 
    def update_contour_by(self, contour_by_array_idx, **kwargs):
        array = self.dataset_arrays[contour_by_array_idx]
        contour_min, contour_max = array.get("range")
        contour_step = 0.01 * (contour_max - contour_min)
        contour_value = 0.5 * (contour_max + contour_min)
        self.contour.SetInputArrayToProcess(0, 0, 0, array.get("type"), array.get("text"))
        self.contour.SetValue(0, contour_value)
        # Update UI
        self.state.contour_min = contour_min
        self.state.contour_max = contour_max
        self.state.contour_value = contour_value
        self.state.contour_step = contour_step
        # Update View
        self.ctrl.view_update()
 
    def update_contour_value(self, contour_value, **kwargs):
        self.contour.SetValue(0, float(contour_value))
        self.ctrl.view_update()
 
 
    def standard_buttons(self):
        vuetify.VCheckbox(
            v_model=("cube_axes_visibility", True),
            on_icon="mdi-cube-outline",
            off_icon="mdi-cube-off-outline",
            classes="mx-1",
            hide_details=True,
            dense=True,
        )
        vuetify.VCheckbox(
            v_model="$vuetify.theme.dark",
            on_icon="mdi-lightbulb-off-outline",
            off_icon="mdi-lightbulb-outline",
            classes="mx-1",
            hide_details=True,
            dense=True,
        )
        vuetify.VCheckbox(
            v_model=("viewMode", "local"),
            on_icon="mdi-lan-disconnect",
            off_icon="mdi-lan-connect",
            true_value="local",
            false_value="remote",
            classes="mx-1",
            hide_details=True,
            dense=True,
        )
        with vuetify.VBtn(icon=True, click="$refs.view.resetCamera()"):
            vuetify.VIcon("mdi-crop-free")
    def pipeline_widget(self):
        trame.GitTree(
            sources=(
                "pipeline",
                [
                    {"id": "1", "parent": "0", "visible": 1, "name": "Mesh"},
                    {"id": "2", "parent": "1", "visible": 1, "name": "Contour"},
                ],
            ),
            actives_change=(self.actives_change, "[$event]"),
            visibility_change=(self.visibility_change, "[$event]"),
        )
    def ui_card(self, title, ui_name):
        with vuetify.VCard(v_show=f"active_ui == '{ui_name}'"):
            vuetify.VCardTitle(
                title,
                classes="grey lighten-1 py-1 grey--text text--darken-3",
                style="user-select: none; cursor: pointer",
                hide_details=True,
                dense=True,
            )
            content = vuetify.VCardText(classes="py-2")
        return content
    def mesh_card(self):
        with self.ui_card(title="Mesh", ui_name="mesh"):
            vuetify.VSelect(
                # Representation
                v_model=("mesh_representation", Representation.Surface),
                items=(
                    "representations",
                    [
                        {"text": "Points", "value": 0},
                        {"text": "Wireframe", "value": 1},
                        {"text": "Surface", "value": 2},
                        {"text": "SurfaceWithEdges", "value": 3},
                    ],
                ),
                label="Representation",
                hide_details=True,
                dense=True,
                outlined=True,
                classes="pt-1",
            )
            with vuetify.VRow(classes="pt-2", dense=True):
                with vuetify.VCol(cols="6"):
                    vuetify.VSelect(
                        # Color By
                        label="Color by",
                        v_model=("mesh_color_array_idx", 0),
                        items=("array_list", self.dataset_arrays),
                        hide_details=True,
                        dense=True,
                        outlined=True,
                        classes="pt-1",
                    )
                with vuetify.VCol(cols="6"):
                    vuetify.VSelect(
                        # Color Map
                        label="Colormap",
                        v_model=("mesh_color_preset", LookupTable.Rainbow),
                        items=(
                            "colormaps",
                            [
                                {"text": "Rainbow", "value": 0},
                                {"text": "Inv Rainbow", "value": 1},
                                {"text": "Greyscale", "value": 2},
                                {"text": "Inv Greyscale", "value": 3},
                            ],
                        ),
                        hide_details=True,
                        dense=True,
                        outlined=True,
                        classes="pt-1",
                    )
            vuetify.VSlider(
                # Opacity
                v_model=("mesh_opacity", 1.0),
                min=0,
                max=1,
                step=0.1,
                label="Opacity",
                classes="mt-1",
                hide_details=True,
                dense=True,
            )
    def contour_card(self):
        with self.ui_card(title="Contour", ui_name="contour"):
            vuetify.VSelect(
                # Contour By
                label="Contour by",
                v_model=("contour_by_array_idx", 0),
                items=("array_list", self.dataset_arrays),
                hide_details=True,
                dense=True,
                outlined=True,
                classes="pt-1",
            )
            vuetify.VSlider(
                # Contour Value
                v_model=("contour_value", self.contour_value),
                min=("contour_min", self.default_min),
                max=("contour_max", self.default_max),
                step=("contour_step", 0.01 * (self.default_max - self.default_min)),
                label="Value",
                classes="my-1",
                hide_details=True,
                dense=True,
            )
            vuetify.VSelect(
                # Representation
                v_model=("contour_representation", Representation.Surface),
                items=(
                    "representations",
                    [
                        {"text": "Points", "value": 0},
                        {"text": "Wireframe", "value": 1},
                        {"text": "Surface", "value": 2},
                        {"text": "SurfaceWithEdges", "value": 3},
                    ],
                ),
                label="Representation",
                hide_details=True,
                dense=True,
                outlined=True,
                classes="pt-1",
            )
            with vuetify.VRow(classes="pt-2", dense=True):
                with vuetify.VCol(cols="6"):
                    vuetify.VSelect(
                        # Color By
                        label="Color by",
                        v_model=("contour_color_array_idx", 0),
                        items=("array_list", self.dataset_arrays),
                        hide_details=True,
                        dense=True,
                        outlined=True,
                        classes="pt-1",
                    )
                with vuetify.VCol(cols="6"):
                    vuetify.VSelect(
                        # Color Map
                        label="Colormap",
                        v_model=("contour_color_preset", LookupTable.Rainbow),
                        items=(
                            "colormaps",
                            [
                                {"text": "Rainbow", "value": 0},
                                {"text": "Inv Rainbow", "value": 1},
                                {"text": "Greyscale", "value": 2},
                                {"text": "Inv Greyscale", "value": 3},
                            ],
                        ),
                        hide_details=True,
                        dense=True,
                        outlined=True,
                        classes="pt-1",
                    )
            vuetify.VSlider(
                # Opacity
                v_model=("contour_opacity", 1.0),
                min=0,
                max=1,
                step=0.1,
                label="Opacity",
                classes="mt-1",
                hide_details=True,
                dense=True,
            )
    def upload(self, files):
        for file in files:
            file_helper = ClientFile(file)
            file_name = file.get("name")
            file_content = file.get("content")
            print(file_helper.info)
            with open(f"../06/{file_name}", "wb") as f:
                f.write(file_content)
            print(f"成功上传 {len(files)} 个文件")
            # path = os.path.join("../06", file_name)
            path = Path("../06") / file_name
            print(path)
            # self.ctrl.view_update()
            self.renderWindow, self.cube_axes, self.mesh_actor, self.contour_actor, self.mesh_mapper, self.dataset_arrays, self.contour, self.contour_value, self.default_min, self.default_max, self.renderer = create_vtk_pipeline(
                file_name)
 
        self.ctrl.view_update = self.view.update
        self.ctrl.view_reset_camera = self.view.reset_camera
        self.ctrl.view_update()
 
 
 
    def _ui(self):
        with SinglePageWithDrawerLayout(self.server) as layout:
            layout.title.set_text("Viewer")
            with layout.toolbar:
                # toolbar components
                vuetify.VSpacer()
                vuetify.VDivider(vertical=True, classes="mx-2")
                self.standard_buttons()
                html.Input(
                    type="file",
                    multiple=True,
                    change=(self.upload, "[$event.target.files]"),
                    __events=["change"],
                    style="max-width: 200px; height: 30px;",
                )
            with layout.drawer as drawer:
                # drawer components
                drawer.width = 325
                self.pipeline_widget()
                vuetify.VDivider(classes="mb-2")
                self.mesh_card()
                self.contour_card()
            with layout.content:
                # content components
                with vuetify.VContainer(
                        fluid=True,
                        classes="pa-0 fill-height",
                ):
                    # view = vtk.VtkRemoteView(renderWindow, interactive_ratio=1)
                    # view = vtk.VtkLocalView(renderWindow)
                    self.view = vtk.VtkRemoteLocalView(
                        self.renderWindow, namespace="view", mode="local", interactive_ratio=1
                    )
                    self.ctrl.view_update = self.view.update
                    self.ctrl.view_reset_camera = self.view.reset_camera
 
        return layout
 
 
 
# -----------------------------------------------------------------------------
# Main
# -----------------------------------------------------------------------------
 
if __name__ == "__main__":
    app = MyApp()
    app.server.start()
问题补充:

似乎是后端渲染内容没有在前端更新

zoss的主页 zoss | 初学一级 | 园豆:114
提问于:2025-06-29 17:42
< >
分享
最佳答案
0

只能有一个renderWindow

zoss | 初学一级 |园豆:114 | 2025-07-01 20:40
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册