Skip to content

Commit

Permalink
Add VTK example to gallery
Browse files Browse the repository at this point in the history
  • Loading branch information
xavArtley committed Oct 29, 2019
1 parent d451a4b commit ae82510
Show file tree
Hide file tree
Showing 4 changed files with 351 additions and 16 deletions.
327 changes: 327 additions & 0 deletions examples/gallery/external/panel_gallery_vtk.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import panel as pn\n",
"import pyvista as pv\n",
"from pyvista import examples\n",
"pn.extension('vtk')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m = examples.download_st_helens().warp_by_scalar()\n",
"\n",
"cpos = [(567000.9232163235, 5119147.423216323, 6460.423216322832),\n",
" (562835.0, 5114981.5, 2294.5),\n",
" (-0.4082482904638299, -0.40824829046381844, 0.8164965809277649)]\n",
"\n",
"#pyvista plotter\n",
"pl = pv.Plotter(notebook=True);\n",
"actor = pl.add_mesh(m, smooth_shading=True, lighting=True)\n",
"pl.camera_position = cpos\n",
"actor_ref = [\"None\", actor.__this__]\n",
"actor_names = [\"None\", 'St Helen']\n",
"actor_opts = {k:v for k,v in zip(actor_names, actor_ref)}\n",
"\n",
"renderer = list(pl.ren_win.GetRenderers())[0]\n",
"\n",
"#get initial camera properties\n",
"initial_camera = renderer.GetActiveCamera()\n",
"initial_camera_pos = {\"focalPoint\": initial_camera.GetFocalPoint(),\n",
" \"position\": initial_camera.GetPosition(),\n",
" \"viewUp\": initial_camera.GetViewUp()}\n",
"\n",
"orientation_widget = True\n",
"enable_keybindings = True\n",
"\n",
"vtkpan = pn.panel(pl.ren_win, sizing_mode='stretch_both', orientation_widget=orientation_widget, enable_keybindings=enable_keybindings, height=600)\n",
"\n",
"#general\n",
"cbars = vtkpan.construct_colorbars()\n",
"cbars.width = 300\n",
"cbar_view = pn.panel(cbars)\n",
"options = {}\n",
"actor_selection = pn.widgets.Select(value=None, options = actor_opts , name=\"Actor Selection\")\n",
"global_info = pn.Column(cbar_view,actor_selection)\n",
"\n",
"#layout Scene\n",
"scene_props = pn.WidgetBox()\n",
"bind_and_orient = pn.widgets.CheckBoxGroup(value=['Orientation Widget', 'Key Bindings'], options=['Orientation Widget', 'Key Bindings']) #initialisation => coherence with panel params\n",
"reset_camera = pn.widgets.Button(name='Reset Camera')\n",
"background_color = pn.widgets.ColorPicker(value=''.join(['#'] + ['{:02x}'.format(int(v*255)) for v in pl.background_color]),\n",
" name='Background Color')\n",
"[scene_props.append(w) for w in [bind_and_orient, reset_camera, background_color]]\n",
"\n",
"light_props = pn.WidgetBox()\n",
"light_box_title = pn.widgets.StaticText(value='Light properties')\n",
"light_type = pn.widgets.Select(value='HeadLight', options=['HeadLight','SceneLight','CameraLight'])\n",
"light_intensity = pn.widgets.FloatSlider(start=0, end=1, value=1, name=\"Intensity\")\n",
"\n",
"light_type.jslink(vtkpan, code={'value':\"\"\"\n",
"const light = target.renderer_el.getRenderer().getLights()[0]\n",
"if (source.value == 'HeadLight')\n",
" light.setLightTypeToHeadLight()\n",
"else if (source.value == 'CameraLight')\n",
" light.setLightTypeToCameraLight()\n",
"else if (source.value == 'SceneLight')\n",
" light.setLightTypeToSceneLight()\n",
"target.renderer_el.getRenderWindow().render()\n",
"\"\"\"})\n",
"\n",
"light_intensity.jslink(vtkpan, code={'value':\"\"\"\n",
"const light = target.renderer_el.getRenderer().getLights()[0]\n",
"light.setIntensity(source.value)\n",
"target.renderer_el.getRenderWindow().render()\n",
"\"\"\"})\n",
"\n",
"\n",
"[light_props.append(w) for w in [light_box_title, light_type, light_intensity]]\n",
"\n",
"#layout actor props\n",
"actor_props = pn.WidgetBox()\n",
"opacity = pn.widgets.FloatSlider(value=1, start=0, end=1, name='Opacity', disabled=True)\n",
"lighting = pn.widgets.Toggle(value=True, name='Lighting', disabled=True)\n",
"interpolation = pn.widgets.Select(value='Phong', options=['Flat','Phong'], name='Interpolation', disabled=True)\n",
"edges = pn.widgets.Toggle(value=False, name='Show Edges', disabled=True)\n",
"edges_color = pn.widgets.ColorPicker(value='#ffffff', name='Edges Color', disabled=True)\n",
"representation = pn.widgets.Select(value='Surface', options=['Points','Wireframe','Surface'], name='Representation', disabled=True)\n",
"frontface_culling = pn.widgets.Toggle(value=False, name='Frontface Culling', disabled=True)\n",
"backface_culling = pn.widgets.Toggle(value=False, name='Backface Culling', disabled=True)\n",
"ambient = pn.widgets.FloatSlider(value=0, start=-1, end=1, name='Ambient', disabled=True)\n",
"diffuse = pn.widgets.FloatSlider(value=1, start=0, end=2, name='Diffuse', disabled=True)\n",
"specular = pn.widgets.FloatSlider(value=0, start=0, end=10, name='Specular', disabled=True)\n",
"specular_power = pn.widgets.FloatSlider(value=100, start=0, end=100, name='Specular Power', disabled=True)\n",
"[actor_props.append(w) for w in [opacity, lighting, interpolation, edges, edges_color,\n",
" representation,frontface_culling,backface_culling, ambient,\n",
" diffuse, specular, specular_power]]\n",
"\n",
"#linking\n",
"bind_and_orient.jslink(vtkpan, code = {'active':\"\"\"\n",
"target.orientation_widget = source.active.includes(0)\n",
"target.enable_keybindings = source.active.includes(1)\n",
"\"\"\"});\n",
"\n",
"reset_camera.jscallback(args={'target': vtkpan, 'initial_camera':initial_camera_pos},\n",
" clicks = \"target.camera = initial_camera\");\n",
"\n",
"background_color.jslink(vtkpan, code={'value':\"\"\"\n",
"const hextoarr = (color) => {return [parseInt(color.slice(1,3),16)/255, parseInt(color.slice(3,5),16)/255, parseInt(color.slice(5,7),16)/255]}\n",
"target.renderer_el.getRenderer().setBackground(hextoarr(source.color))\n",
"target.renderer_el.getRenderWindow().render()\n",
"\"\"\"});\n",
"\n",
"opacity.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setOpacity(source.value)\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"lighting.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setLighting(source.active)\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"edges.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setEdgeVisibility(source.active)\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"interpolation.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" if(source.value==\"Flat\"){\n",
" actor.getProperty().setInterpolationToFlat()\n",
" }else{\n",
" actor.getProperty().setInterpolationToPhong()\n",
" }\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"edges_color.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const hextoarr = (color) => {return [parseInt(color.slice(1,3),16)/255, parseInt(color.slice(3,5),16)/255, parseInt(color.slice(5,7),16)/255]}\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setEdgeColor(hextoarr(source.color))\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"representation.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" if(source.value==\"Points\"){\n",
" actor.getProperty().setRepresentationToPoints()\n",
" }else if(source.value==\"Wireframe\"){\n",
" actor.getProperty().setRepresentationToWireframe()\n",
" }else if(source.value==\"Surface\"){\n",
" actor.getProperty().setRepresentationToSurface()\n",
" }\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"frontface_culling.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setFrontfaceCulling(source.active)\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"backface_culling.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setBackfaceCulling(source.active)\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"ambient.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setAmbient(source.value)\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"diffuse.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setDiffuse(source.value)\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"specular.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setSpecular(source.value)\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"specular_power.jscallback(args={\"target\":vtkpan, \"actor_selection\":actor_selection}, value=\"\"\"\n",
"if (actor_selection.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==actor_selection.value})[0]\n",
" actor.getProperty().setSpecularPower(source.value)\n",
" target.renderer_el.getRenderWindow().render()\n",
"}\n",
"\"\"\")\n",
"\n",
"actor_selection.jslink(target=vtkpan, code = {'value' : \"\"\"\n",
"if (source.value!=\"None\"){\n",
" const actor = target.getActors().filter((a)=>{ return a.get('id')['id']==source.value})[0]\n",
" target.outline.setInputConnection(actor.getMapper().getInputConnection())\n",
" target.renderer_el.getRenderer().addActor(target.outline_actor)\n",
" \n",
" //synchronize actor props and widgets values\n",
" properties = actor.getProperty()\n",
" opacity.setv({value: properties.getOpacity()}, {silent: true})\n",
" lighting.setv({active: !!properties.getLighting()}, {silent: true})\n",
" edges.active = !!properties.getEdgeVisibility()\n",
" actor_color = \"#\" + properties.getEdgeColor().map((c) => (\"0\" + Math.round(255*c).toString(16,2)).slice(-2)).join('')\n",
" edges_color.setv({color: actor_color}, {silent: true})\n",
" interp_string = properties.getInterpolationAsString()\n",
" interpolation.setv({value: interp_string[0] + interp_string.slice(1).toLocaleLowerCase()}, {silent: true})\n",
" repr_string = properties.getRepresentationAsString()\n",
" representation.setv({value: repr_string[0] + repr_string.slice(1).toLocaleLowerCase()}, {silent: true})\n",
" frontface_culling.setv({active: !!properties.getFrontfaceCulling()}, {silent: true})\n",
" backface_culling.setv({active: !!properties.getBackfaceCulling()}, {silent: true})\n",
" ambient.setv({value: properties.getAmbient()}, {silent: true})\n",
" diffuse.setv({value: properties.getDiffuse()}, {silent: true})\n",
" specular.setv({value: properties.getSpecular()}, {silent: true})\n",
" specular_power.setv({value: properties.getSpecularPower()}, {silent: true})\n",
" //enable widgets modifications\n",
" opacity.disabled = false\n",
" lighting.disabled = false\n",
" interpolation.disabled = false\n",
" edges.disabled = false\n",
" edges_color.disabled = false\n",
" representation.disabled = false\n",
" frontface_culling.disabled = false\n",
" backface_culling.disabled = false\n",
" ambient.disabled = false\n",
" diffuse.disabled = false\n",
" specular.disabled = false\n",
" specular_power.disabled = false\n",
"} else {\n",
" target.renderer_el.getRenderer().removeActor(target.outline_actor)\n",
" opacity.disabled = true\n",
" lighting.disabled = true\n",
" interpolation.disabled = true\n",
" edges.disabled = true\n",
" edges_color.disabled = true\n",
" representation.disabled = true\n",
" frontface_culling.disabled = true\n",
" backface_culling.disabled = true\n",
" ambient.disabled = true\n",
" diffuse.disabled = true\n",
" specular.disabled = true\n",
" specular_power.disabled = true\n",
"}\n",
"target.renderer_el.getRenderWindow().render()\n",
"\n",
"\"\"\"}, args={\"opacity\":opacity, \"lighting\":lighting, \"interpolation\": interpolation, \"edges\": edges, \"edges_color\": edges_color,\n",
" \"representation\": representation, \"frontface_culling\": frontface_culling, \"backface_culling\": backface_culling,\n",
" \"ambient\": ambient, \"diffuse\": diffuse, \"specular\": specular, \"specular_power\": specular_power})\n",
"\n",
"debug_button = pn.widgets.Button(name='JavaScript Debugger')\n",
"debug_button.jslink(vtkpan, code={\"clicks\": \"\"\"\n",
"const renderer = target.renderer_el.getRenderer()\n",
"const actors = renderer.getActors()\n",
"const renderWindow = target.renderer_el.getRenderWindow()\n",
"debugger\n",
"renderWindow.render()\n",
"\"\"\"})\n",
"#display\n",
"pn.Row(vtkpan,pn.Column(global_info,pn.Tabs(('Scene controller', pn.Column(scene_props, light_props)), ('Actor properties',actor_props)), debug_button), sizing_mode=\"stretch_both\").servable()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
27 changes: 19 additions & 8 deletions panel/models/vtk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ function majorAxis(vec3: number[], idxA: number, idxB: number): number[] {
return axis
}



export class VTKPlotView extends HTMLBoxView {
model: VTKPlot
protected _container: HTMLDivElement
Expand Down Expand Up @@ -115,9 +117,9 @@ export class VTKPlotView extends HTMLBoxView {
this._camera.onModified(() => this._get_camera_state())
this._remove_default_key_binding()
this.model.renderer_el = this._rendererEl
/*this._interactor.onRightButtonPress((_callData: any) => {
console.log('Not Implemented')
})*/
// this._interactor.onRightButtonPress((_callData: any) => {
// console.log('Not Implemented')
// })
}
super.after_layout()
}
Expand Down Expand Up @@ -206,9 +208,7 @@ export class VTKPlotView extends HTMLBoxView {
const fn = vtk.macro.debounce(() => {
if (this._orientationWidget == null)
this._create_orientation_widget()

this._renderer.resetCamera()
this._rendererEl.getRenderWindow().render()
this._set_camera_state()
}, 100)
sceneImporter.setUrl('index.json')
sceneImporter.onReady(fn)
Expand All @@ -228,17 +228,29 @@ export namespace VTKPlot {
camera: p.Property<any>
enable_keybindings: p.Property<boolean>
orientation_widget: p.Property<boolean>
renderer_el: p.Property<any>
}
}

export interface VTKPlot extends VTKPlot.Attrs {}

export class VTKPlot extends HTMLBox {
properties: VTKPlot.Props
renderer_el: any
outline: any
outline_actor: any

constructor(attrs?: Partial<VTKPlot.Attrs>) {
super(attrs)
this.renderer_el = null
this.outline = vtk.Filters.General.vtkOutlineFilter.newInstance() //use to display bouding box of a selected actor
const mapper = vtk.Rendering.Core.vtkMapper.newInstance()
mapper.setInputConnection(this.outline.getOutputPort())
this.outline_actor = vtk.Rendering.Core.vtkActor.newInstance()
this.outline_actor.setMapper(mapper)
}

getActors() : [any] {
return this.renderer_el.getRenderer().getActors()
}

static __module__ = "panel.models.vtk"
Expand All @@ -251,7 +263,6 @@ export class VTKPlot extends HTMLBox {
camera: [ p.Any ],
enable_keybindings: [ p.Boolean, false ],
orientation_widget: [ p.Boolean, false ],
renderer_el: [ p.Any ]
})

this.override({
Expand Down
Loading

0 comments on commit ae82510

Please sign in to comment.