# Other Dash VTK Components

## Mesh

This element is a helper on top of vtk_polydata which has a helper function that goes with it which will help you map a vtkDataSet into a single property of the __vtk_mesh element.

    function vtk_mesh(; kwargs...)
        return vtk_polydata(
            kwargs.state["mesh"],
            children=[
                getproperty(DashVtk, Symbol(kwargs.state["field"]["location"]))([vtk_dataarray(kwargs["state"]["field"])])
            ]
        )
    end

Note that we assume that `state.field` exists when we use `kwargs.state["field"]["location"])` in the snippet above. However, `state.field` is optional, so when it's not available the `children` is not created, and `kwargs.state["field"]["location"]` would not be needed.

The vtk_mesh element expects a single state property that is internally split into 2 elements to represent the geometry and the field that you want to optionally attach to your mesh. The structure could be defined as follows:

- state
  - mesh: (Contains the properties of vtk_polydata)
    - points = []
    - verts = []
    - lines = []
    - polys = []
    - strips = []
    - connectivity = 'manual' # manual, points, triangles, strips
  - field: (Contains the properties of vtk_dataarray)
    - location: "PointData" / "CellData"
    - name: Name of the field (optional)
    - values: Array of values for the field
    - numberOfComponents: Number of components per point/cell
    - type: Name of TypedArray to use (Uint8Array, Int8Array, Float32Array, Float64Array...)

## Volume

This element is a helper on top of vtk_imagedata which has a Python helper function that goes with it which will help you map a vtkImageData into a single property of the __vtk_volume element.

    function Volume(; kwargs...):
        return vtk_imagedata(
            kwargs.state["image"],
            children=[
                vtk_pointdata([
                    vtk_dataarray(
                      kwargs.state["field"],
                    )
                ])
            ]
        )
    end

The vtk_volume element expects a single state__ property that is internally split into 2 elements to represent the geometry and the field that you want to optionally attach to your mesh. The structure could be defined as follows:

- state
  - image: (Contains the properties of ImageData)
    - dimensions
    - spacing
    - origin
  - field: (Contains the properties of DataArray)
    - values: Array of values for the field
    - numberOfComponents: Number of components per point/cell
    - type: Name of TypedArray to use (Uint8Array, Int8Array, Float32Array, Float64Array...)

## Algorithm

This element allows you to create and configure a vtk.js class. This element expect only 2 properties:

- vtkClass: The name of the vtkClass to instantiate.
- state: The set of properties to apply on the given vtkClass.

The current list of classes available to instantiate are:

- vtkClass:
  - vtkConcentricCylinderSource
  - vtkConeSource
  - vtkCubeSource
  - vtkCylinderSource
  - vtkLineSource
  - vtkPlaneSource
  - vtkPointSource
  - vtkSphereSource
  - vtkWarpScalar
- state: See the references above for the properties available for each vtkClass.

The following example uses a vtk source in vtk.js to generate a mesh

    using Dash, DashHtmlComponents, DashVtk

    content = vtk_view([
        vtk_geometryrepresentation(
            mapper=Dict(
                "colorByArrayName" => "layer",
                "scalarMode" => 4,
                "interpolateScalarsBeforeMapping" => false,
            ),
            colorMapPreset="jet",
            colorDataRange=[0.2, 0.9],
            children=[
              vtk_algorithm(
                  vtkClass="vtkConcentricCylinderSource",
                  state=Dict(
                      "height" => 0.25,
                      "radius" => [0.2, 0.3, 0.4, 0.6, 0.7, 0.8, 0.9, 1],
                      "cellFields" => [0, 0.2, 0.4, 0.6, 0.7, 0.8, 0.9, 1],
                      "mask" => [1, 0, 1, 0, 1, 0, 1, 1],
                      "resolution" => 60,
                      "skipInnerFaces" => true,
                      "startTheta" => 45,
                      "endTheta" => 315,
                      "center" => [0, 0, 0.5],
                  ),
              ),
            ]
        ),
    ])

    # Dash setup
    app = dash()

    app.layout = html_div(
        style=Dict("width" => "100%", "height" => "400px"),
        children=[content],
    )

    run_server(app, "0.0.0.0", debug = true)

## Reader

This element is similar to the vtk_algorithm except that it focuses on vtk.js readers by allowing you to leverage their custom API. Like vtk_algorithm, a reader expects a vtkClass among those listed below:

- vtkClass
  - vtkPLYReader
  - vtkSTLReader
  - vtkElevationReader
  - vtkOBJReader
  - vtkPDBReader
  - vtkXMLImageDataReader
  - vtkXMLPolyDataReader

Then use one of the properties below to feed the reader some data:

- url: set of url to fetch data from (on the JS side)
- parseAsText: set the text content to process
- parseAsArrayBuffer: set binary data to process from base64 string

Since the data loading is going to be asynchronous, we've enabled some automatic callbacks to either trigger a render or a resetCamera once the data became available. To enable these callbacks, set the following properties to your liking:

- renderOnUpdate: true (default)
- resetCameraOnUpdate: true (default)

    # no-exec-file

    using Dash, DashHtmlComponents, DashVtk

    filepath = download("https://github.com/plotly/dash-vtk/blob/master/demos/data/cow-nonormals.obj");
    txt_content = read(filepath, String);

    content = vtk_view([
        vtk_geometryrepresentation([
            vtk_reader(
                vtkClass="vtkOBJReader",
                parseAsText=txt_content,
            ),
        ]),
    ]);

    # Dash setup
    app = dash()

    app.layout = html_div(
        style=Dict("width" => "100%", "height" => "400px"),
        children=[content],
    );

    run_server(app, "0.0.0.0", debug = true)

## ShareDataSet

This element does not affect the dataset, but it allows the JavaScript side to reuse an existing vtkDataSet for another Representation or filter.

The only property expected in a vtk_sharedataset is a name to properly reference it elsewhere. A name is provided dy default, so in the case of only one dataset, you would not need to specify this property.

The following example shows how to create a view with one vtk_volume and four representations of it.

View full code

    using Dash, DashHtmlComponents, DashVtk, PyCall
    vtkutils = pyimport("dash_vtk.utils")

    try
        # VTK 9+
        global imagingcore = pyimport("vtkmodules.vtkImagingCore")
    catch
        # VTK =< 8
        global imagingcore = pyimport("vtk.vtkImagingCore")
    end

    # Use VTK to get some data
    data_source = imagingcore.vtkRTAnalyticSource();
    data_source.Update()  # <= Execute source to produce an output
    dataset = data_source.GetOutput()

    # Use helper to get a volume structure that can be passed as-is to a Volume
    volume_state = vtkutils.to_volume_state(dataset);  # No need to select field

    content = vtk_view([
        vtk_volumerepresentation([
            # GUI to control Volume Rendering
            # + Setup good default at startup
            vtk_volumecontroller(),
            # Actual volume
            vtk_sharedataset([
                vtk_volume(state=volume_state),
            ]),
        ]),
        vtk_slicerepresentation(
            iSlice=10,
            children=[
                vtk_sharedataset(),
            ]
        ),
        vtk_slicerepresentation(
            jSlice=10,
            children=[
                vtk_sharedataset(),
            ]
        ),
        vtk_slicerepresentation(
            kSlice=10,
            children=[
                vtk_sharedataset(),
            ]
        ),
    ]);

    # Dash setup
    app = dash()

    app.layout = html_div(
        style=Dict("width" => "100%", "height" => "400px"),
        children=[content],
    );

    run_server(app, "0.0.0.0", debug = true)