Skip to content

Add picking support #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 7, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions R/vtkGeometryRepresentation.R
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# AUTO GENERATED FILE - DO NOT EDIT

vtkGeometryRepresentation <- function(children=NULL, id=NULL, actor=NULL, mapper=NULL, property=NULL, colorMapPreset=NULL, colorDataRange=NULL) {
vtkGeometryRepresentation <- function(children=NULL, id=NULL, actor=NULL, mapper=NULL, property=NULL, colorMapPreset=NULL, colorDataRange=NULL, showCubeAxes=NULL, cubeAxesStyle=NULL) {

props <- list(children=children, id=id, actor=actor, mapper=mapper, property=property, colorMapPreset=colorMapPreset, colorDataRange=colorDataRange)
props <- list(children=children, id=id, actor=actor, mapper=mapper, property=property, colorMapPreset=colorMapPreset, colorDataRange=colorDataRange, showCubeAxes=showCubeAxes, cubeAxesStyle=cubeAxesStyle)
if (length(props) > 0) {
props <- props[!vapply(props, is.null, logical(1))]
}
component <- list(
props = props,
type = 'GeometryRepresentation',
namespace = 'dash_vtk',
propNames = c('children', 'id', 'actor', 'mapper', 'property', 'colorMapPreset', 'colorDataRange'),
propNames = c('children', 'id', 'actor', 'mapper', 'property', 'colorMapPreset', 'colorDataRange', 'showCubeAxes', 'cubeAxesStyle'),
package = 'dashVtk'
)

Expand Down
6 changes: 3 additions & 3 deletions R/vtkView.R
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# AUTO GENERATED FILE - DO NOT EDIT

vtkView <- function(children=NULL, id=NULL, style=NULL, className=NULL, background=NULL, interactorSettings=NULL, cameraPosition=NULL, cameraViewUp=NULL, cameraParallelProjection=NULL, triggerRender=NULL, triggerResetCamera=NULL) {
vtkView <- function(children=NULL, id=NULL, style=NULL, className=NULL, background=NULL, interactorSettings=NULL, cameraPosition=NULL, cameraViewUp=NULL, cameraParallelProjection=NULL, triggerRender=NULL, triggerResetCamera=NULL, pickingModes=NULL, clickInfo=NULL, hoverInfo=NULL) {

props <- list(children=children, id=id, style=style, className=className, background=background, interactorSettings=interactorSettings, cameraPosition=cameraPosition, cameraViewUp=cameraViewUp, cameraParallelProjection=cameraParallelProjection, triggerRender=triggerRender, triggerResetCamera=triggerResetCamera)
props <- list(children=children, id=id, style=style, className=className, background=background, interactorSettings=interactorSettings, cameraPosition=cameraPosition, cameraViewUp=cameraViewUp, cameraParallelProjection=cameraParallelProjection, triggerRender=triggerRender, triggerResetCamera=triggerResetCamera, pickingModes=pickingModes, clickInfo=clickInfo, hoverInfo=hoverInfo)
if (length(props) > 0) {
props <- props[!vapply(props, is.null, logical(1))]
}
component <- list(
props = props,
type = 'View',
namespace = 'dash_vtk',
propNames = c('children', 'id', 'style', 'className', 'background', 'interactorSettings', 'cameraPosition', 'cameraViewUp', 'cameraParallelProjection', 'triggerRender', 'triggerResetCamera'),
propNames = c('children', 'id', 'style', 'className', 'background', 'interactorSettings', 'cameraPosition', 'cameraViewUp', 'cameraParallelProjection', 'triggerRender', 'triggerResetCamera', 'pickingModes', 'clickInfo', 'hoverInfo'),
package = 'dashVtk'
)

Expand Down
11 changes: 7 additions & 4 deletions dash_vtk/GeometryRepresentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@ class GeometryRepresentation(Component):
- mapper (dict; optional): Properties to set to the actor
- property (dict; optional): Properties to set to the actor.property
- colorMapPreset (string; default 'erdc_rainbow_bright'): Preset name for the lookup table color map
- colorDataRange (list of numbers; default [0, 1]): Data range use for the colorMap"""
- colorDataRange (list of numbers; default [0, 1]): Data range use for the colorMap
- showCubeAxes (boolean; optional): Show/Hide Cube Axes for the given representation
- cubeAxesStyle (dict; optional): Configure cube Axes style by overriding the set of properties defined
https://github.com/Kitware/vtk-js/blob/HEAD/Sources/Rendering/Core/CubeAxesActor/index.js#L703-L719"""
@_explicitize_args
def __init__(self, children=None, id=Component.UNDEFINED, actor=Component.UNDEFINED, mapper=Component.UNDEFINED, property=Component.UNDEFINED, colorMapPreset=Component.UNDEFINED, colorDataRange=Component.UNDEFINED, **kwargs):
self._prop_names = ['children', 'id', 'actor', 'mapper', 'property', 'colorMapPreset', 'colorDataRange']
def __init__(self, children=None, id=Component.UNDEFINED, actor=Component.UNDEFINED, mapper=Component.UNDEFINED, property=Component.UNDEFINED, colorMapPreset=Component.UNDEFINED, colorDataRange=Component.UNDEFINED, showCubeAxes=Component.UNDEFINED, cubeAxesStyle=Component.UNDEFINED, **kwargs):
self._prop_names = ['children', 'id', 'actor', 'mapper', 'property', 'colorMapPreset', 'colorDataRange', 'showCubeAxes', 'cubeAxesStyle']
self._type = 'GeometryRepresentation'
self._namespace = 'dash_vtk'
self._valid_wildcard_attributes = []
self.available_properties = ['children', 'id', 'actor', 'mapper', 'property', 'colorMapPreset', 'colorDataRange']
self.available_properties = ['children', 'id', 'actor', 'mapper', 'property', 'colorMapPreset', 'colorDataRange', 'showCubeAxes', 'cubeAxesStyle']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
Expand Down
15 changes: 11 additions & 4 deletions dash_vtk/View.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,21 @@ class View(Component):
- cameraViewUp (list; default [0, 1, 0]): Initial camera position from an object in [0,0,0]
- cameraParallelProjection (boolean; default False): Use parallel projection (default: false)
- triggerRender (number; default 0): Property use to trigger a render when changing.
- triggerResetCamera (number; default 0): Property use to trigger a resetCamera when changing."""
- triggerResetCamera (number; default 0): Property use to trigger a resetCamera when changing.
- pickingModes (list of strings; optional): List of picking listeners to bind. The supported values are `click` and `hover`. By default it is disabled (empty array).
- clickInfo (dict; optional): Read-only prop. To use this, make sure that `pickingModes` contains `click`.
This prop is updated when an element in the map is clicked. This contains
the picking info describing the object being clicked on.
- hoverInfo (dict; optional): Read-only prop. To use this, make sure that `pickingModes` contains `hover`.
This prop is updated when an element in the map is hovered. This contains
the picking info describing the object being hovered."""
@_explicitize_args
def __init__(self, children=None, id=Component.UNDEFINED, style=Component.UNDEFINED, className=Component.UNDEFINED, background=Component.UNDEFINED, interactorSettings=Component.UNDEFINED, cameraPosition=Component.UNDEFINED, cameraViewUp=Component.UNDEFINED, cameraParallelProjection=Component.UNDEFINED, triggerRender=Component.UNDEFINED, triggerResetCamera=Component.UNDEFINED, **kwargs):
self._prop_names = ['children', 'id', 'style', 'className', 'background', 'interactorSettings', 'cameraPosition', 'cameraViewUp', 'cameraParallelProjection', 'triggerRender', 'triggerResetCamera']
def __init__(self, children=None, id=Component.UNDEFINED, style=Component.UNDEFINED, className=Component.UNDEFINED, background=Component.UNDEFINED, interactorSettings=Component.UNDEFINED, cameraPosition=Component.UNDEFINED, cameraViewUp=Component.UNDEFINED, cameraParallelProjection=Component.UNDEFINED, triggerRender=Component.UNDEFINED, triggerResetCamera=Component.UNDEFINED, pickingModes=Component.UNDEFINED, clickInfo=Component.UNDEFINED, hoverInfo=Component.UNDEFINED, **kwargs):
self._prop_names = ['children', 'id', 'style', 'className', 'background', 'interactorSettings', 'cameraPosition', 'cameraViewUp', 'cameraParallelProjection', 'triggerRender', 'triggerResetCamera', 'pickingModes', 'clickInfo', 'hoverInfo']
self._type = 'View'
self._namespace = 'dash_vtk'
self._valid_wildcard_attributes = []
self.available_properties = ['children', 'id', 'style', 'className', 'background', 'interactorSettings', 'cameraPosition', 'cameraViewUp', 'cameraParallelProjection', 'triggerRender', 'triggerResetCamera']
self.available_properties = ['children', 'id', 'style', 'className', 'background', 'interactorSettings', 'cameraPosition', 'cameraViewUp', 'cameraParallelProjection', 'triggerRender', 'triggerResetCamera', 'pickingModes', 'clickInfo', 'hoverInfo']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
Expand Down
14 changes: 7 additions & 7 deletions dash_vtk/dash_vtk.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dash_vtk/dash_vtk.min.js.map

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions dash_vtk/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,20 @@
"computed": false
}
},
"showCubeAxes": {
"type": {
"name": "bool"
},
"required": false,
"description": "Show/Hide Cube Axes for the given representation"
},
"cubeAxesStyle": {
"type": {
"name": "object"
},
"required": false,
"description": "Configure cube Axes style by overriding the set of properties defined\nhttps://github.com/Kitware/vtk-js/blob/HEAD/Sources/Rendering/Core/CubeAxesActor/index.js#L703-L719"
},
"children": {
"type": {
"name": "union",
Expand Down Expand Up @@ -1169,6 +1183,30 @@
"computed": false
}
},
"pickingModes": {
"type": {
"name": "arrayOf",
"value": {
"name": "string"
}
},
"required": false,
"description": "List of picking listeners to bind. The supported values are `click` and `hover`. By default it is disabled (empty array)."
},
"clickInfo": {
"type": {
"name": "object"
},
"required": false,
"description": "Read-only prop. To use this, make sure that `pickingModes` contains `click`.\nThis prop is updated when an element in the map is clicked. This contains\nthe picking info describing the object being clicked on."
},
"hoverInfo": {
"type": {
"name": "object"
},
"required": false,
"description": "Read-only prop. To use this, make sure that `pickingModes` contains `hover`.\nThis prop is updated when an element in the map is hovered. This contains\nthe picking info describing the object being hovered."
},
"children": {
"type": {
"name": "union",
Expand Down
2 changes: 1 addition & 1 deletion dash_vtk/package-info.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"license": "MIT",
"dependencies": {
"ramda": "^0.26.1",
"react-vtk-js": "1.1.4"
"react-vtk-js": "1.2.1"
},
"devDependencies": {
"@babel/core": "^7.5.4",
Expand Down
48 changes: 47 additions & 1 deletion dash_vtk/utils/vtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@
}


def to_mesh_state(dataset, field_to_keep=None):
def to_mesh_state(dataset, field_to_keep=None, point_arrays=None, cell_arrays=None):
'''Expect any dataset and extract its surface into a dash_vtk.Mesh state property'''
if dataset is None:
return None

if point_arrays is None:
point_arrays = []
if cell_arrays is None:
cell_arrays = []

# Make sure we have a polydata to export
polydata = None
if dataset.IsA('vtkPolyData'):
Expand Down Expand Up @@ -77,6 +82,42 @@ def to_mesh_state(dataset, field_to_keep=None):
js_types = to_js_type[str(values.dtype)]
location = 'PointData'

# other arrays (points)
point_data = []
for name in point_arrays:
array = polydata.GetPointData().GetArray(name)
if array:
dataRange = array.GetRange(-1)
nb_comp = array.GetNumberOfComponents()
values = vtk_to_numpy(array).ravel()
js_types = to_js_type[str(values.dtype)]
point_data.append({
'name': name,
'values': values,
'numberOfComponents': nb_comp,
'type': js_types,
'location': 'PointData',
'dataRange': dataRange,
})

# other arrays (cells)
cell_data = []
for name in point_arrays:
array = polydata.GetCellData().GetArray(name)
if array:
dataRange = array.GetRange(-1)
nb_comp = array.GetNumberOfComponents()
values = vtk_to_numpy(array).ravel()
js_types = to_js_type[str(values.dtype)]
cell_data.append({
'name': name,
'values': values,
'numberOfComponents': nb_comp,
'type': js_types,
'location': 'CellData',
'dataRange': dataRange,
})

state = {
'mesh': {
'points': points,
Expand All @@ -103,6 +144,11 @@ def to_mesh_state(dataset, field_to_keep=None):
},
})

if len(point_data):
state.update({ 'pointArrays': point_data })
if len(cell_data):
state.update({ 'cellArrays': cell_data })

return state


Expand Down
78 changes: 73 additions & 5 deletions demos/pyvista-terrain-following-mesh/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from dash.dependencies import Input, Output, State

import random
import json
import numpy as np
import pyvista as pv
from pyvista import examples
Expand Down Expand Up @@ -44,6 +45,7 @@ def updateWarp(factor=1):

vtk_view = dash_vtk.View(
id="vtk-view",
pickingModes=["hover"],
children=[
dash_vtk.GeometryRepresentation(
id="vtk-representation",
Expand All @@ -68,8 +70,19 @@ def updateWarp(factor=1):
],
colorMapPreset="erdc_blue2green_muted",
colorDataRange=color_range,
property={"edgeVisibility": True,},
)
property={"edgeVisibility": True},
showCubeAxes=True,
cubeAxesStyle={"axisLabels": ["", "", "Altitude"]},
),
dash_vtk.GeometryRepresentation(
id="pick-rep",
actor={"visibility": False},
children=[
dash_vtk.Algorithm(
id="pick-sphere", vtkClass="vtkSphereSource", state={"radius": 100},
)
],
),
],
)

Expand All @@ -96,31 +109,86 @@ def updateWarp(factor=1):
value="erdc_rainbow_bright",
),
),
dbc.Col(
children=dcc.Checklist(
id="toggle-cube-axes",
options=[{"label": " Show axis grid", "value": "grid"},],
value=[],
labelStyle={"display": "inline-block"},
),
),
],
style={"height": "12%", "align-items": "center"},
),
html.Div(
html.Div(vtk_view, style={"height": "100%", "width": "100%"}),
style={"height": "88%"},
),
html.Pre(
id="tooltip",
style={
"position": "absolute",
"bottom": "25px",
"left": "25px",
"zIndex": 1,
"color": "white",
},
),
],
)


@app.callback(
[
Output("vtk-representation", "showCubeAxes"),
Output("vtk-representation", "colorMapPreset"),
Output("vtk-representation", "colorDataRange"),
Output("vtk-polydata", "points"),
Output("vtk-polydata", "polys"),
Output("vtk-array", "values"),
Output("vtk-view", "triggerResetCamera"),
],
[Input("dropdown-preset", "value"), Input("scale-factor", "value")],
[
Input("dropdown-preset", "value"),
Input("scale-factor", "value"),
Input("toggle-cube-axes", "value"),
],
)
def updatePresetName(name, scale_factor):
def updatePresetName(name, scale_factor, cubeAxes):
points, polys, elevation, color_range = updateWarp(scale_factor)
return [name, color_range, points, polys, elevation, random.random()]
return [
"grid" in cubeAxes,
name,
color_range,
points,
polys,
elevation,
random.random(),
]


@app.callback(
[
Output("tooltip", "children"),
Output("pick-sphere", "state"),
Output("pick-rep", "actor"),
],
[Input("vtk-view", "clickInfo"), Input("vtk-view", "hoverInfo"),],
)
def onInfo(clickData, hoverData):
info = hoverData if hoverData else clickData
if info:
if (
"representationId" in info
and info["representationId"] == "vtk-representation"
):
return (
[json.dumps(info, indent=2)],
{"center": info["worldPosition"]},
{"visibility": True},
)
return dash.no_update, dash.no_update, dash.no_update
return [""], {}, {"visibility": False}


if __name__ == "__main__":
Expand Down
14 changes: 7 additions & 7 deletions deps/dash_vtk.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion deps/dash_vtk.min.js.map

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ dash_vtk.View(
cameraParallelProjection=False, # Perspective or flat
triggerRender=0, # Timestamp meant to trigger a render when different
triggerResetCamera=0, # Timestamp meant to trigger a reset camera when different
pickingModes=['click'], # Listen for click and/or hover event. (Options: hover, click)
# clickInfo, # Read-only property to retreive picked representation id and picking information
# hoverInfo, # Read-only property to retreive picked representation id and picking information
)
```

Expand Down Expand Up @@ -349,6 +352,7 @@ The list below show you the default values used for each argument:

On top of those previous settings we provide additional properties to configure a lookup table using one of our available [__colorMapPreset__](https://github.com/Kitware/vtk-js/blob/master/Sources/Rendering/Core/ColorTransferFunction/ColorMaps.json) and a convinient __colorDataRange__ to rescale to color map to your area of focus.

With the GeometryRepresentation you also have the option to turn on the CubeAxes using the `showCubeAxes=True` along with additional configuration parameters that can be provided via `cubeAxesStyle` property. The content of the object for __cubeAxesStyle__ can be found in the source code of vtk.js from the [default section here](https://github.com/Kitware/vtk-js/blob/HEAD/Sources/Rendering/Core/CubeAxesActor/index.js#L703-L719).
### GlyphRepresentation

GlyphRepresentation let you use a source as a Glyph which will then be cloned and position at every points of another source. The properties available on the __GlyphRepresentation__ let you tune the way you want to render your geometry.
Expand Down
14 changes: 7 additions & 7 deletions inst/deps/dash_vtk.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/deps/dash_vtk.min.js.map

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion man/vtkGeometryRepresentation.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ GeometryRepresentation is responsible to convert a vtkPolyData into rendering It

\usage{
vtkGeometryRepresentation(children=NULL, id=NULL, actor=NULL, mapper=NULL,
property=NULL, colorMapPreset=NULL, colorDataRange=NULL)
property=NULL, colorMapPreset=NULL, colorDataRange=NULL,
showCubeAxes=NULL, cubeAxesStyle=NULL)
}

\arguments{
Expand All @@ -28,6 +29,11 @@ property=NULL, colorMapPreset=NULL, colorDataRange=NULL)
\item{colorMapPreset}{Character. Preset name for the lookup table color map}

\item{colorDataRange}{List of numerics. Data range use for the colorMap}

\item{showCubeAxes}{Logical. Show/Hide Cube Axes for the given representation}

\item{cubeAxesStyle}{Named list. Configure cube Axes style by overriding the set of properties defined
https://github.com/Kitware/vtk-js/blob/HEAD/Sources/Rendering/Core/CubeAxesActor/index.js#L703-L719}
}

\value{named list of JSON elements corresponding to React.js properties and their values}
Expand Down
Loading