diff --git a/apps/dash-vehicle-geometry/app.py b/apps/dash-vehicle-geometry/app.py index 75aaca02d..d1869ca10 100644 --- a/apps/dash-vehicle-geometry/app.py +++ b/apps/dash-vehicle-geometry/app.py @@ -25,9 +25,20 @@ def _load_vtp(filepath, fieldname=None, point_arrays=[], cell_arrays=[]): reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(filepath) reader.Update() + return to_mesh_state(reader.GetOutput(), fieldname, point_arrays, cell_arrays) +def cache_mesh(filepath, di, fieldname=None, point_arrays=[], cell_arrays=[]): + reader = vtk.vtkXMLPolyDataReader() + reader.SetFileName(filepath) + reader.Update() + + # Cache mesh for future lookup + part_name = filepath.split("/")[-1].replace(".vtp", "") + di[part_name] = reader.GetOutput() + + # ----------------------------------------------------------------------------- # GUI setup # ----------------------------------------------------------------------------- @@ -48,7 +59,7 @@ def _load_vtp(filepath, fieldname=None, point_arrays=[], cell_arrays=[]): vehicle_mesh_ids = [] vehicle_meshes = [] -for filename in glob.glob(os.path.join(DATA_PATH, "vehicle") + "/*.vtp"): +for filename in glob.glob(os.path.join(DATA_PATH, "vehicle-vect") + "/*.vtp"): mesh = _load_vtp(filename, point_arrays=["U", "p"]) part_name = filename.split("/")[-1].replace(".vtp", "") child = dash_vtk.GeometryRepresentation( @@ -87,13 +98,20 @@ def _load_vtp(filepath, fieldname=None, point_arrays=[], cell_arrays=[]): isomesh_ids.append(f"{surf_name}-mesh") isosurfs_meshes.append(mesh) +# time to cache meshes +vtk_datasets = {} +for filename in glob.glob(os.path.join(DATA_PATH, "vehicle-vect") + "/*.vtp"): + cache_mesh(filename, vtk_datasets) + +for filename in glob.glob(os.path.join(DATA_PATH, "isosurfaces") + "/*.vtp"): + cache_mesh(filename, vtk_datasets) # ----------------------------------------------------------------------------- # 3D Viz # ----------------------------------------------------------------------------- # vtk_view = dash_vtk.View(id="vtk-view", children=vehicle_vtk + isosurfs_vtk) -vtk_view = dash_vtk.View(id="vtk-view") +# vtk_view = dash_vtk.View(id="vtk-view", pickingModes=['hover']) # ----------------------------------------------------------------------------- # Control UI @@ -173,23 +191,34 @@ def _load_vtp(filepath, fieldname=None, point_arrays=[], cell_arrays=[]): width=8, children=[ html.Div( - dbc.Spinner( - html.Div( - id="vtk-view-container", - style={ - "height": "calc(100vh - 230px)", - "width": "100%", - }, - ), - color="light", + children=html.Div( + dbc.Spinner(color="light"), + style={ + "background-color": "#334c66", + "height": "calc(100vh - 230px)", + "width": "100%", + "text-align": "center", + "padding-top": "calc(50vh - 105px)", + }, ), - style={"background-color": "#334c66"}, - ) + id="vtk-view-container", + style={"height": "calc(100vh - 230px)", "width": "100%",}, + ), ], ), ], style={"margin-top": "15px", "height": "calc(100vh - 230px)"}, ), + html.Pre( + id="tooltip", + style={ + "position": "absolute", + "bottom": "25px", + "left": "25px", + "zIndex": 1, + "color": "white", + }, + ), ], ) @@ -206,7 +235,16 @@ def initial_loading(geometry): if triggered: return dash.no_update - return dash_vtk.View(id="vtk-view", children=vehicle_vtk + isosurfs_vtk) + cone_pointer = dash_vtk.GeometryRepresentation( + property={"color": [1, 0, 0]}, + children=[dash_vtk.Algorithm(id="pointer", vtkClass="vtkConeSource")], + ) + + return dash_vtk.View( + id="vtk-view", + children=vehicle_vtk + isosurfs_vtk + [cone_pointer], + pickingModes=["hover"], + ) @app.callback( @@ -267,6 +305,60 @@ def update_scene(geometry, isosurfaces, surfcolor): return [random.random()] + surf_state + geo_viz + color_ranges + [iso_viz] +SCALE_P = 0.0001 +SCALE_U = 0.01 + + +@app.callback( + [Output("tooltip", "children"), Output("pointer", "state"),], + [Input("vtk-view", "hoverInfo"),], +) +def probe_data(info): + cone_state = {"resolution": 12} + if info: + if "representationId" not in info: + return dash.no_update, dash.no_update + ds_name = info["representationId"].replace("-rep", "") + mesh = vtk_datasets[ds_name] + if mesh: + xyx = info["worldPosition"] + idx = mesh.FindPoint(xyx) + if idx > -1: + cone_state["center"] = mesh.GetPoints().GetPoint(idx) + messages = [] + pd = mesh.GetPointData() + size = pd.GetNumberOfArrays() + for i in range(size): + array = pd.GetArray(i) + name = array.GetName() + nb_comp = array.GetNumberOfComponents() + value = array.GetValue(idx) + value_str = f"{array.GetValue(idx):.2f}" + norm_str = "" + if nb_comp == 3: + value = array.GetTuple3(idx) + norm = (value[0] ** 2 + value[1] ** 2 + value[2] ** 2) ** 0.5 + norm_str = f" norm({norm:.2f})" + value_str = ", ".join([f"{v:.2f}" for v in value]) + + cone_state["height"] = SCALE_U * norm + cone_state["direction"] = [v / norm for v in value] + + if name == "p": + cone_state["radius"] = array.GetValue(idx) * SCALE_P + + messages.append(f"{name}: {value_str} {norm_str}") + + if "height" in cone_state: + new_center = [v for v in cone_state["center"]] + for i in range(3): + new_center[i] -= 0.5 * cone_state["height"] * cone_state["direction"][i] + cone_state["center"] = new_center + + return ["\n".join(messages)], cone_state + return [""], cone_state + + # ----------------------------------------------------------------------------- if __name__ == "__main__": diff --git a/apps/dash-vehicle-geometry/data/vehicle-vect/body.vtp b/apps/dash-vehicle-geometry/data/vehicle-vect/body.vtp new file mode 100644 index 000000000..1de517266 Binary files /dev/null and b/apps/dash-vehicle-geometry/data/vehicle-vect/body.vtp differ diff --git a/apps/dash-vehicle-geometry/data/vehicle-vect/drive-train.vtp b/apps/dash-vehicle-geometry/data/vehicle-vect/drive-train.vtp new file mode 100644 index 000000000..4b965ab4f Binary files /dev/null and b/apps/dash-vehicle-geometry/data/vehicle-vect/drive-train.vtp differ diff --git a/apps/dash-vehicle-geometry/data/vehicle-vect/front-wing.vtp b/apps/dash-vehicle-geometry/data/vehicle-vect/front-wing.vtp new file mode 100644 index 000000000..71712dead Binary files /dev/null and b/apps/dash-vehicle-geometry/data/vehicle-vect/front-wing.vtp differ diff --git a/apps/dash-vehicle-geometry/data/vehicle-vect/rear-wing.vtp b/apps/dash-vehicle-geometry/data/vehicle-vect/rear-wing.vtp new file mode 100644 index 000000000..c0e9d52db Binary files /dev/null and b/apps/dash-vehicle-geometry/data/vehicle-vect/rear-wing.vtp differ diff --git a/apps/dash-vehicle-geometry/requirements-real.txt b/apps/dash-vehicle-geometry/requirements-real.txt index 2eb1303c8..4620c3c69 100644 --- a/apps/dash-vehicle-geometry/requirements-real.txt +++ b/apps/dash-vehicle-geometry/requirements-real.txt @@ -2,7 +2,7 @@ appdirs==1.4.4 Brotli==1.0.9 click==7.1.2 dash==1.19.0 -dash-bootstrap-components==0.12.0 +dash-bootstrap-components==0.12.1 dash-core-components==1.15.0 dash-html-components==1.1.2 dash-renderer==1.9.0