Export a plotter's rendering window to the VTKjs format.

def export_plotter_vtkjs(plotter, filename, compress_arrays=False):
    """Export a plotter's rendering window to the VTKjs format.
    """
    sceneName = os.path.split(filename)[1]
    doCompressArrays = compress_arrays

    # Generate timestamp and use it to make subdirectory within the top level output dir
    timeStamp = time.strftime("%a-%d-%b-%Y-%H-%M-%S")
    root_output_directory = os.path.split(filename)[0]
    output_dir = os.path.join(root_output_directory, timeStamp)
    mkdir_p(output_dir)

    renderers = plotter.ren_win.GetRenderers()

    scDirs = []
    sceneComponents = []
    textureToSave = {}

    for rIdx in range(renderers.GetNumberOfItems()):
        renderer = renderers.GetItemAsObject(rIdx)
        renProps = renderer.GetViewProps()
        for rpIdx in range(renProps.GetNumberOfItems()):
            renProp = renProps.GetItemAsObject(rpIdx)
            if not renProp.GetVisibility():
                continue
            if hasattr(renProp, 'GetMapper') and renProp.GetMapper() is not None:
                mapper = renProp.GetMapper()
                dataObject = mapper.GetInputDataObject(0, 0)
                dataset = None
                if dataObject is None:
                    continue
                if dataObject.IsA('vtkCompositeDataSet'):
                    if dataObject.GetNumberOfBlocks() == 1:
                        dataset = dataObject.GetBlock(0)
                    else:
                        gf = vtk.vtkCompositeDataGeometryFilter()
                        gf.SetInputData(dataObject)
                        gf.Update()
                        dataset = gf.GetOutput()
                else:
                    dataset = mapper.GetInput()

                if dataset and not isinstance(dataset, (vtk.vtkPolyData, vtk.vtkImageData)):
                    # All data must be PolyData surfaces
                    gf = vtk.vtkGeometryFilter()
                    gf.SetInputData(dataset)
                    gf.Update()
                    dataset = gf.GetOutputDataObject(0)


                if dataset:# and dataset.GetPoints(): # NOTE: vtkImageData does not have points
                    componentName = 'data_%d_%d' % (
                        rIdx, rpIdx)  # getComponentName(renProp)
                    scalarVisibility = mapper.GetScalarVisibility()
                    #arrayAccessMode = mapper.GetArrayAccessMode()
                    #colorArrayName = mapper.GetArrayName() #TODO: if arrayAccessMode == 1 else mapper.GetArrayId()
                    colorMode = mapper.GetColorMode()
                    scalarMode = mapper.GetScalarMode()
                    lookupTable = mapper.GetLookupTable()

                    dsAttrs = None
                    arrayLocation = ''

                    if scalarVisibility:
                        if scalarMode == 3 or scalarMode == 1:  # VTK_SCALAR_MODE_USE_POINT_FIELD_DATA or VTK_SCALAR_MODE_USE_POINT_DATA
                            dsAttrs = dataset.GetPointData()
                            arrayLocation = 'pointData'
                        # VTK_SCALAR_MODE_USE_CELL_FIELD_DATA or VTK_SCALAR_MODE_USE_CELL_DATA
                        elif scalarMode == 4 or scalarMode == 2:
                            dsAttrs = dataset.GetCellData()
                            arrayLocation = 'cellData'

                    colorArray = None
                    dataArray = None

                    if dsAttrs:
                        dataArray = dsAttrs.GetArray(0) # Force getting the active array

                    if dataArray:
                        # component = -1 => let specific instance get scalar from vector before mapping
                        colorArray = lookupTable.MapScalars(
                            dataArray, colorMode, -1)
                        colorArrayName = '__CustomRGBColorArray__'
                        colorArray.SetName(colorArrayName)
                        colorMode = 0
                    else:
                        colorArrayName = ''

                    color_array_info = {
                        'colorArray': colorArray,
                        'location': arrayLocation
                    }

                    scDirs.append(write_data_set('', dataset, output_dir, color_array_info,
                                               new_name=componentName, compress=doCompressArrays))

                    # Handle texture if any
                    textureName = None
                    if renProp.GetTexture() and renProp.GetTexture().GetInput():
                        textureData = renProp.GetTexture().GetInput()
                        textureName = 'texture_%d' % get_object_id(textureData)
                        textureToSave[textureName] = textureData

                    representation = renProp.GetProperty().GetRepresentation(
                    ) if hasattr(renProp, 'GetProperty') else 2
                    colorToUse = renProp.GetProperty().GetDiffuseColor(
                    ) if hasattr(renProp, 'GetProperty') else [1, 1, 1]
                    if representation == 1:
                        colorToUse = renProp.GetProperty().GetColor() if hasattr(
                            renProp, 'GetProperty') else [1, 1, 1]
                    pointSize = renProp.GetProperty().GetPointSize(
                    ) if hasattr(renProp, 'GetProperty') else 1.0
                    opacity = renProp.GetProperty().GetOpacity() if hasattr(
                        renProp, 'GetProperty') else 1.0
                    edgeVisibility = renProp.GetProperty().GetEdgeVisibility(
                    ) if hasattr(renProp, 'GetProperty') else false

                    p3dPosition = renProp.GetPosition() if renProp.IsA(
                        'vtkProp3D') else [0, 0, 0]
                    p3dScale = renProp.GetScale() if renProp.IsA(
                        'vtkProp3D') else [1, 1, 1]
                    p3dOrigin = renProp.GetOrigin() if renProp.IsA(
                        'vtkProp3D') else [0, 0, 0]
                    p3dRotateWXYZ = renProp.GetOrientationWXYZ(
                    ) if renProp.IsA('vtkProp3D') else [0, 0, 0, 0]

                    sceneComponents.append({
                        "name": componentName,
                        "type": "httpDataSetReader",
                        "httpDataSetReader": {
                            "url": componentName
                        },
                        "actor": {
                            "origin": p3dOrigin,
                            "scale": p3dScale,
                            "position": p3dPosition,
                        },
                        "actorRotation": p3dRotateWXYZ,
                        "mapper": {
                            "colorByArrayName": colorArrayName,
                            "colorMode": colorMode,
                            "scalarMode": scalarMode
                        },
                        "property": {
                            "representation": representation,
                            "edgeVisibility": edgeVisibility,
                            "diffuseColor": colorToUse,
                            "pointSize": pointSize,
                            "opacity": opacity
                        },
                        "lookupTable": {
                            "tableRange": lookupTable.GetRange(),
                            "hueRange": lookupTable.GetHueRange() if hasattr(lookupTable, 'GetHueRange') else [0.5, 0]
                        }
                    })

                    if textureName:
                        sceneComponents[-1]['texture'] = textureName

    # Save texture data if any
    for key, val in textureToSave.items():
        write_data_set('', val, output_dir, None, new_name=key,
                     compress=doCompressArrays)

    cameraClippingRange = plotter.camera.GetClippingRange()

    sceneDescription = {
      "fetchGzip": doCompressArrays,
      "background": plotter.background_color,
      "camera": {
        "focalPoint": plotter.camera.GetFocalPoint(),
        "position": plotter.camera.GetPosition(),
        "viewUp": plotter.camera.GetViewUp(),
        "clippingRange": [ elt for elt in cameraClippingRange ]
      },
      "centerOfRotation": plotter.camera.GetFocalPoint(),
      "scene": sceneComponents
    }

    indexFilePath = os.path.join(output_dir, 'index.json')
    with open(indexFilePath, 'w') as outfile:
      json.dump(sceneDescription, outfile, indent=4)

# -----------------------------------------------------------------------------

    # Now zip up the results and get rid of the temp directory
    sceneFileName = os.path.join(
        root_output_directory, '%s%s' % (sceneName, FILENAME_EXTENSION))

    try:
        import zlib
        compression = zipfile.ZIP_DEFLATED
    except:
        compression = zipfile.ZIP_STORED

    zf = zipfile.ZipFile(sceneFileName, mode='w')

    try:
        for dirName, subdirList, fileList in os.walk(output_dir):
            for fname in fileList:
                fullPath = os.path.join(dirName, fname)
                relPath = '%s/%s' % (sceneName,
                                     os.path.relpath(fullPath, output_dir))
                zf.write(fullPath, arcname=relPath, compress_type=compression)
    finally:
        zf.close()

    shutil.rmtree(output_dir)

    print('Finished exporting dataset to: ', sceneFileName)