Skip to content

Commit f1a7026

Browse files
committed
Merge branch 'fix-scaling-and-add-global-COS' into 'main'
Fix scaling problems and add global coordinate system See merge request cschmidt/4c-webviewer!6
2 parents d79f29e + e67243d commit f1a7026

File tree

2 files changed

+111
-77
lines changed

2 files changed

+111
-77
lines changed

src/fourc_webviewer/run_webserver.py

Lines changed: 26 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434

3535
# create server object and the state, control variables
3636
SERVER = get_server()
37-
STATE, CTRL = SERVER.state, SERVER.controller
38-
# STATE contains all the state variables, CTRL contains all the control functions / elements, UI
37+
STATE, CTRL, CTXT = SERVER.state, SERVER.controller, SERVER.context
38+
# STATE contains all the state variables to be shared between server and client, CTRL contains all the control functions / elements, CTXT is a server-only state object which can be utilized to collect global server variables
3939

4040

4141
def run_webviewer(dat_file=None):
@@ -84,11 +84,18 @@ def run_webviewer(dat_file=None):
8484
vtu_threshold_condition_points = vtu.create_vtu_threshold_points(reader, STATE)
8585
vtu_sphere = vtu.create_vtu_sphere(reader)
8686

87+
# create global coordinate system
88+
vtu_global_cos = vtu.create_vtu_global_cos(reader)
89+
8790
STATE.TEMP_DIR = temp_dir
88-
STATE.READER = reader
89-
STATE.VTU_THRESHOLD_MAT = vtu_threshold_mat
90-
STATE.VTU_THRESHOLD_CONDITION_POINTS = vtu_threshold_condition_points
91-
STATE.VTU_SPHERE = vtu_sphere
91+
92+
# we put the non-serializable objects into CTXT instead of STATE
93+
# -> no errors anymore, and functionality is preserved, because these variables are only required on the server side
94+
CTXT.READER = reader
95+
CTXT.VTU_THRESHOLD_MAT = vtu_threshold_mat
96+
CTXT.VTU_THRESHOLD_CONDITION_POINTS = vtu_threshold_condition_points
97+
CTXT.VTU_SPHERE = vtu_sphere
98+
CTXT.VTU_GLOBAL_COS = vtu_global_cos
9299

93100
# append functions to CTRL
94101
CTRL.CLICK_INFO_BUTTON = click_info_button
@@ -98,7 +105,7 @@ def run_webviewer(dat_file=None):
98105

99106
# create vtu render window
100107
render_window = vtu.create_vtu_render_window(
101-
reader, vtu_threshold_condition_points, vtu_threshold_mat, vtu_sphere
108+
reader, vtu_threshold_condition_points, vtu_threshold_mat, vtu_sphere, vtu_global_cos
102109
)
103110

104111
gui.create_gui(SERVER, render_window)
@@ -371,22 +378,9 @@ def STATE_initialization(temp_dir, dat_file_name, dat_file_lines, dat_file_size,
371378
STATE.COND_TYPE_LIST = dat_file_content["cond_type_list"]
372379

373380
# GET THE RESULT DESCRIPTION
374-
# STATE.RESULT_DESCRIPTION = STATE.CATEGORY_ITEMS[
375-
# STATE.CATEGORIES.index("RESULT DESCRIPTION")
376-
# ]
377-
STATE.RESULT_DESCRIPTION = [
378-
[1, 2, 3, 4, 5, 6, 7, 8],
379-
[
380-
"STRUCTURE DIS structure NODE 4 QUANTITY dispy VALUE -1.31962249833408790e-01 TOLERANCE 9.1e-10",
381-
"STRUCTURE DIS structure NODE 5 QUANTITY dispx VALUE -1.31962249833408513e-01 TOLERANCE 9.1e-10",
382-
"STRUCTURE DIS structure NODE 8 QUANTITY dispx VALUE -9.06271329067036280e-02 TOLERANCE 9.1e-10",
383-
"STRUCTURE DIS structure NODE 8 QUANTITY dispy VALUE -9.06271329067068060e-02 TOLERANCE 9.1e-10",
384-
"STRUCTURE DIS structure NODE 8 QUANTITY dispz VALUE 2.84025416687741394e-01 TOLERANCE 2.8e-09",
385-
"STRUCTURE DIS structure NODE 6 QUANTITY dispx VALUE -9.06271329067021153e-02 TOLERANCE 9.1e-10",
386-
"STRUCTURE DIS structure NODE 4 QUANTITY stress_zz VALUE 1.83879098311578976e-01 TOLERANCE 1.8e-07",
387-
"STRUCTURE DIS structure NODE 8 QUANTITY stress_zz VALUE 1.83879098311589884e-01 TOLERANCE 1.8e-07",
388-
],
389-
]
381+
STATE.RESULT_DESCRIPTION = STATE.CATEGORY_ITEMS[
382+
STATE.CATEGORIES.index("RESULT DESCRIPTION")
383+
]
390384

391385
# GET THE GEOMETRY LINES
392386
STATE.GEOMETRY_LINES = dat_file_content["geometry_lines"]
@@ -570,8 +564,8 @@ def change_selected_cmm_line(SELECTED_CMM_LINE, **kwargs):
570564
)
571565

572566
# set threshold of the material of the vtk local view
573-
STATE.VTU_THRESHOLD_MAT.SetLowerThreshold(STATE.SELECTED_CMM_LINE_INDEX + 1)
574-
STATE.VTU_THRESHOLD_MAT.SetUpperThreshold(STATE.SELECTED_CMM_LINE_INDEX + 1)
567+
CTXT.VTU_THRESHOLD_MAT.SetLowerThreshold(STATE.SELECTED_CMM_LINE_INDEX + 1)
568+
CTXT.VTU_THRESHOLD_MAT.SetUpperThreshold(STATE.SELECTED_CMM_LINE_INDEX + 1)
575569
# update the vtk local view
576570
CTRL.VIEW_UPDATE()
577571

@@ -611,7 +605,7 @@ def change_selected_cond_general_type(SELECTED_COND_GENERAL_TYPE, **kwargs):
611605
STATE.SELECTED_COND_GENERAL_TYPE_INDEX
612606
][0]
613607
# set thresholdPoints of the condition of the vtk figure
614-
STATE.VTU_THRESHOLD_CONDITION_POINTS.SetInputArrayToProcess(
608+
CTXT.VTU_THRESHOLD_CONDITION_POINTS.SetInputArrayToProcess(
615609
0,
616610
0,
617611
0,
@@ -633,7 +627,7 @@ def change_selected_cond_entity(SELECTED_COND_ENTITY, **kwargs):
633627
].index(SELECTED_COND_ENTITY)
634628

635629
# set thresholdPoints of the condition of the vtk figure
636-
STATE.VTU_THRESHOLD_CONDITION_POINTS.SetInputArrayToProcess(
630+
CTXT.VTU_THRESHOLD_CONDITION_POINTS.SetInputArrayToProcess(
637631
0,
638632
0,
639633
0,
@@ -656,19 +650,7 @@ def change_selected_result_descr_index(SELECTED_RESULT_DESCR_INDEX, **kwargs):
656650
# after selecting a result description from the list: item change
657651
@STATE.change("SELECTED_RESULT_DESCR")
658652
def change_selected_result_descr(SELECTED_RESULT_DESCR, **kwargs):
659-
# check if the line contains the marker "NODE"
660-
if len(re.findall("NODE", STATE.SELECTED_RESULT_DESCR)) > 0:
661-
# get the specified node
662-
result_descr_components = STATE.SELECTED_RESULT_DESCR.split(" ")
663-
node_index = (
664-
int(result_descr_components[result_descr_components.index("NODE") + 1]) - 1
665-
)
666-
667-
# update graphic representation
668-
node_coords = STATE.READER.GetOutput().GetPoints().GetPoint(node_index)
669-
STATE.VTU_SPHERE.SetCenter(node_coords[0], node_coords[1], node_coords[2])
670-
# update the vtk figure
671-
CTRL.VIEW_UPDATE()
653+
vtu.update_vtu_render_window(CTXT.READER, CTXT.VTU_SPHERE, CTXT.VTU_GLOBAL_COS, SERVER)
672654

673655

674656
# changing the values for t_max, x, y or z for the function plots
@@ -738,7 +720,7 @@ def click_convert_button():
738720
vtu_path = convert_to_vtu(temp_dat_file, STATE.TEMP_DIR)
739721

740722
# update reader to read the current vtu file
741-
vtu.update_vtu_reader(STATE.READER, vtu_path)
723+
vtu.update_vtu_reader(CTXT.READER, vtu_path)
742724

743725
# read dat file content
744726
dat_file_content = read_dat_file(STATE.DAT_NAME, STATE.DAT_LINES)
@@ -754,10 +736,9 @@ def click_convert_button():
754736
# flush state: force push server changes
755737
STATE.flush()
756738

757-
# it is not required to update the actor_cond point size
758-
STATE.VTU_SPHERE.SetRadius(
759-
vtu.get_length_scale_rendered_object(STATE.READER) / 50.0
760-
)
739+
740+
# update render window (manual scaling of various elements)
741+
vtu.update_vtu_render_window(CTXT.READER, CTXT.VTU_SPHERE, CTXT.VTU_GLOBAL_COS, SERVER)
761742

762743
CTRL.VIEW_RESET_CAMERA()
763744
CTRL.VIEW_UPDATE()

src/fourc_webviewer/vturender.py

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
## VTK
1+
"""Import modules"""
22
# import of vtk modules for the vtk pipelines
33
from vtkmodules.vtkCommonDataModel import vtkDataObject
44
from vtkmodules.vtkCommonCore import vtkLookupTable
55
from vtkmodules.vtkFiltersSources import vtkSphereSource
66
from vtkmodules.vtkIOXML import vtkXMLUnstructuredGridReader
7-
from vtkmodules.vtkRenderingAnnotation import vtkCubeAxesActor
7+
from vtkmodules.vtkRenderingAnnotation import vtkAxesActor
88
from vtkmodules.vtkFiltersCore import (
99
vtkThreshold,
1010
vtkThresholdPoints,
@@ -17,7 +17,6 @@
1717
vtkRenderWindowInteractor,
1818
)
1919

20-
2120
# import required modules for interactor
2221
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa
2322

@@ -26,7 +25,16 @@
2625
# import colors for vtk visualization
2726
from vtkmodules.vtkCommonColor import vtkNamedColors
2827

28+
import re
29+
import math
30+
31+
"""Global variables"""
32+
vtu_global_cos_frac_scale_ = 1.0 / 5.0 # factor which scales the coordinate system axes with respect to the problem length scale
33+
vtu_sphere_frac_scale_ = 1.0 / 50.0 # factor which scales the nodal result description with respect to the problem length scale
34+
vtu_cond_marker_frac_scale_ = 50.0 # factor which scales the condition markers on points, lines, ... with respect to the problem length scale
35+
2936

37+
"""VTU objects"""
3038
def create_vtu_reader():
3139
return vtkXMLUnstructuredGridReader()
3240

@@ -61,13 +69,25 @@ def create_vtu_threshold_points(reader, server_state):
6169

6270
def create_vtu_sphere(reader):
6371
vtu_sphere = vtkSphereSource()
64-
vtu_sphere.SetRadius(get_length_scale_rendered_object(reader) / 50.0)
72+
73+
# scale using problem length scale
74+
vtu_sphere.SetRadius(get_length_scale_rendered_object(reader) * vtu_sphere_frac_scale_)
6575

6676
return vtu_sphere
6777

78+
def create_vtu_global_cos(reader):
79+
vtu_global_cos = vtkAxesActor()
80+
vtu_global_cos.SetPosition(0,0,0)
81+
82+
# scale using problem length scale
83+
scale_fac = get_length_scale_rendered_object(reader) * vtu_global_cos_frac_scale_
84+
vtu_global_cos.SetTotalLength(scale_fac, scale_fac, scale_fac)
85+
86+
return vtu_global_cos
87+
6888

6989
def create_vtu_render_window(
70-
reader, vtu_threshold_condition_points, vtu_threshold_mat, vtu_sphere
90+
reader, vtu_threshold_condition_points, vtu_threshold_mat, vtu_sphere, vtu_global_cos
7191
):
7292

7393
# create renderer
@@ -104,7 +124,7 @@ def create_vtu_render_window(
104124
actor_cond.SetMapper(mapper_cond)
105125
actor_cond.GetProperty().SetColor(vtkNamedColors().GetColor3d("LimeGreen"))
106126
actor_cond.GetProperty().SetPointSize(
107-
get_length_scale_rendered_object(reader) * 50.0
127+
get_length_scale_rendered_object(reader) * vtu_cond_marker_frac_scale_
108128
)
109129
actor_cond.GetProperty().SetOpacity(1.0)
110130

@@ -120,41 +140,74 @@ def create_vtu_render_window(
120140
renderer.AddActor(actor_mat)
121141
renderer.AddActor(actor_cond)
122142
renderer.AddActor(actor_res_descr)
143+
renderer.AddActor(vtu_global_cos)
123144
renderer.SetBackground(vtkNamedColors().GetColor3d("White"))
124145
renderer.ResetCamera()
125146

126147
return renderWindow
127148

128-
149+
"""Update functions"""
129150
def update_vtu_reader(vtu_reader, vtu_file_path):
130151
# This function updates a given vtu reader with the corresponding vtu file path
131152
vtu_reader.SetFileName(vtu_file_path)
132153
vtu_reader.Update()
133154

155+
def update_vtu_render_window(reader, sphere, global_cos, server):
156+
"""Perform manual scaling of several render window objects.
157+
158+
This is required, since some of the independent components, such as the vtkSphereSource,
159+
do not scale directly with our problem size.
160+
161+
Args:
162+
reader (vtkXMLUnstructuredGridReader): grid reader
163+
sphere (vtkSphereSource): sphere used for the depiction of nodes with prescribed results
164+
global_cos (vtkAxesActor): global coordinate system
165+
server (trame server): server object of the application
166+
167+
Returns:
168+
None
169+
"""
170+
171+
172+
### we need to update the vtkSphere, since it does not scale automatically with the new view
173+
# check if the line contains the marker "NODE"
174+
if len(re.findall("NODE", server.state.SELECTED_RESULT_DESCR)) > 0:
175+
# get the specified node
176+
result_descr_components = server.state.SELECTED_RESULT_DESCR.split(" ")
177+
node_index = (
178+
int(result_descr_components[result_descr_components.index("NODE") + 1]) - 1
179+
)
180+
181+
# update graphic representation
182+
node_coords = reader.GetOutput().GetPoints().GetPoint(node_index)
183+
sphere.SetCenter(node_coords[0], node_coords[1], node_coords[2])
184+
# it is not required to update the actor_cond point size
185+
sphere.SetRadius(
186+
get_length_scale_rendered_object(reader) * vtu_sphere_frac_scale_
187+
)
188+
189+
# update the vtk figure
190+
server.controller.VIEW_UPDATE()
191+
192+
### we also need to update the axes lengths of the global COS
193+
scale_fac = get_length_scale_rendered_object(reader) * vtu_global_cos_frac_scale_
194+
global_cos.SetTotalLength(scale_fac, scale_fac, scale_fac)
195+
196+
134197

135198
def get_length_scale_rendered_object(reader):
136-
# The function is used to extract a geometric length scale for the problem, which is used in the rendering process (e.g. to define the radius of the sphere source object representing the nodes in the "RESULT DESCRIPTION" section)
137-
# Output:
138-
# length_scale: maximum of the domain bound deltas [max_x-min_x, max_y-min_y, max_z-min_z]
139-
140-
all_point_coords = [
141-
[
142-
reader.GetOutput().GetPoints().GetPoint(point_index)[0]
143-
for point_index in range(reader.GetOutput().GetPoints().GetNumberOfPoints())
144-
],
145-
[
146-
reader.GetOutput().GetPoints().GetPoint(point_index)[1]
147-
for point_index in range(reader.GetOutput().GetPoints().GetNumberOfPoints())
148-
],
149-
[
150-
reader.GetOutput().GetPoints().GetPoint(point_index)[2]
151-
for point_index in range(reader.GetOutput().GetPoints().GetNumberOfPoints())
152-
],
153-
]
154-
return max(
155-
[
156-
max(all_point_coords[0]) - min(all_point_coords[0]),
157-
max(all_point_coords[1]) - min(all_point_coords[1]),
158-
max(all_point_coords[2]) - min(all_point_coords[2]),
159-
]
160-
)
199+
"""Compute problem length scale from the bounds of the considered object.
200+
201+
Args:
202+
reader (vtkXMLUnstructuredGridReader): grid reader
203+
Returns:
204+
float: maximum coordinate bound difference in 3-dimensions
205+
206+
"""
207+
208+
# get object bounds
209+
bounds = reader.GetOutput().GetBounds()
210+
211+
# get maximum bound difference as the problem length scale
212+
return max(bounds[1]-bounds[0], bounds[3]-bounds[2], bounds[5]-bounds[4])
213+

0 commit comments

Comments
 (0)