RemoteView

Live example

# RemoteView

The RemoteView can be used with either the VTK-Web or ParaView-Web servers.
The current example will not work until you start one of the servers below on
your local machine.

Using VTK as server

vtk_server.py
r"""
This module is a VTK Web server application.
The following command line illustrates how to use it::

$ vtkpython .../vtk_server.py

Any VTK Web executable script comes with a set of standard arguments that
can be overriden if need be::
--host localhost
Interface on which the HTTP server will listen.

--port 8080
Port number on which the HTTP server will listen.

--content /path-to-web-content/
Directory that you want to serve as static web content.
By default, this variable is empty which means that we rely on another server
to deliver the static content and the current process only focuses on the
WebSocket connectivity of clients.

--authKey wslink-secret
Secret key that should be provided by the client to allow it to make any
WebSocket communication. The client will assume if none is given that the
server expects "wslink-secret" as the secret key.
"""

# import to process args
import sys
import os

# import vtk modules.
import vtk
from vtk.web import protocols
from vtk.web import wslink as vtk_wslink
from wslink import server

import argparse

# =============================================================================
# Create custom ServerProtocol class to handle clients requests
# =============================================================================


class _WebCone(vtk_wslink.ServerProtocol):

# Application configuration
view = None
authKey = "wslink-secret"

def initialize(self):
global renderer, renderWindow, renderWindowInteractor, cone, mapper, actor

# Bring used components
self.registerVtkWebProtocol(protocols.vtkWebMouseHandler())
self.registerVtkWebProtocol(protocols.vtkWebViewPort())
self.registerVtkWebProtocol(protocols.vtkWebPublishImageDelivery(decode=False))
self.registerVtkWebProtocol(protocols.vtkWebViewPortGeometryDelivery())

# Update authentication key to use
self.updateSecret(_WebCone.authKey)

# tell the C++ web app to use no encoding.
# ParaViewWebPublishImageDelivery must be set to decode=False to match.
self.getApplication().SetImageEncoding(0)

# Create default pipeline (Only once for all the session)
if not _WebCone.view:
# VTK specific code
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)

renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
renderWindowInteractor.GetInteractorStyle().SetCurrentStyleToTrackballCamera()

cone = vtk.vtkConeSource()
mapper = vtk.vtkPolyDataMapper()
actor = vtk.vtkActor()

mapper.SetInputConnection(cone.GetOutputPort())
actor.SetMapper(mapper)

renderer.AddActor(actor)
renderer.ResetCamera()
renderWindow.Render()

# VTK Web application specific
_WebCone.view = renderWindow
self.getApplication().GetObjectIdMap().SetActiveObject("VIEW", renderWindow)

# =============================================================================
# Main: Parse args and start server
# =============================================================================


if __name__ == "__main__":
# Create argument parser
parser = argparse.ArgumentParser(
description="VTK/Web Cone web-application")

# Add default arguments
server.add_arguments(parser)

# Extract arguments
args = parser.parse_args()

# Configure our current application
_WebCone.authKey = args.authKey

# Start server
server.start_webserver(options=args, protocol=_WebCone)

And run it via the following command line:

vtkpython vtk_server.py --port 1234

Using ParaView as server

pv_server.py
# import to process args
import os

# import paraview modules.
from paraview.web import pv_wslink
from paraview.web import protocols as pv_protocols

from paraview import simple
from wslink import server

import argparse

# =============================================================================
# Create custom PVServerProtocol class to handle clients requests
# =============================================================================


class _DemoServer(pv_wslink.PVServerProtocol):
authKey = "wslink-secret"

def initialize(self):
# Bring used components
self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPort())
self.registerVtkWebProtocol(
pv_protocols.ParaViewWebPublishImageDelivery(decode=False))
self.updateSecret(_DemoServer.authKey)

# tell the C++ web app to use no encoding.
# ParaViewWebPublishImageDelivery must be set to decode=False to match.
self.getApplication().SetImageEncoding(0)

# Disable interactor-based render calls
simple.GetRenderView().EnableRenderOnInteraction = 0
simple.GetRenderView().Background = [0, 0, 0]
cone = simple.Cone()
simple.Show(cone)
simple.Render()

# Update interaction mode
pxm = simple.servermanager.ProxyManager()
interactionProxy = pxm.GetProxy(
'settings', 'RenderViewInteractionSettings')
interactionProxy.Camera3DManipulators = [
'Rotate', 'Pan', 'Zoom', 'Pan', 'Roll', 'Pan', 'Zoom', 'Rotate', 'Zoom']

# =============================================================================
# Main: Parse args and start server
# =============================================================================


if __name__ == "__main__":
# Create argument parser
parser = argparse.ArgumentParser(description="ParaViewWeb Demo")

# Add default arguments
server.add_arguments(parser)

# Extract arguments
args = parser.parse_args()

# Start server
server.start_webserver(options=args, protocol=_DemoServer)

In order to run the server, you will need a ParaView (5.6+) binary and run the following command line where the Python file provided as argument is available here

/.../pvpython ./pv-server.py --port 1234

Caution: For ParaView 5.13 the web dependencies have been removed in favor of using your own venv along ParaView pvpython. In order to make that example for with ParaView 5.13, you will need to do the following.

python3.10 -m venv .pv-venv
source ./.pv-venv/bin/activate
pip install wslink

/.../pvpython --venv .pv-venv ./pv-server.py --port 1234

Source

import vtkWSLinkClient from '@kitware/vtk.js/IO/Core/WSLinkClient';
import SmartConnect from 'wslink/src/SmartConnect';
import vtkRemoteView from '@kitware/vtk.js/Rendering/Misc/RemoteView';

vtkWSLinkClient.setSmartConnectClass(SmartConnect);

document.body.style.padding = '0';
document.body.style.margin = '0';

const divRenderer = document.createElement('div');
document.body.appendChild(divRenderer);

divRenderer.style.position = 'relative';
divRenderer.style.width = '100vw';
divRenderer.style.height = '100vh';
divRenderer.style.overflow = 'hidden';

const clientToConnect = vtkWSLinkClient.newInstance();

// Error
clientToConnect.onConnectionError((httpReq) => {
const message =
(httpReq && httpReq.response && httpReq.response.error) ||
`Connection error`;
console.error(message);
console.log(httpReq);
});

// Close
clientToConnect.onConnectionClose((httpReq) => {
const message =
(httpReq && httpReq.response && httpReq.response.error) ||
`Connection close`;
console.error(message);
console.log(httpReq);
});

// hint: if you use the launcher.py and ws-proxy just leave out sessionURL
// (it will be provided by the launcher)
const config = {
application: 'cone',
sessionURL: 'ws://localhost:1234/ws',
};

// Connect
clientToConnect
.connect(config)
.then((validClient) => {
const viewStream = clientToConnect.getImageStream().createViewStream('-1');

const view = vtkRemoteView.newInstance({
rpcWheelEvent: 'viewport.mouse.zoom.wheel',
viewStream,
});
const session = validClient.getConnection().getSession();
view.setSession(session);
view.setContainer(divRenderer);
view.setInteractiveRatio(0.7); // the scaled image compared to the clients view resolution
view.setInteractiveQuality(50); // jpeg quality

window.addEventListener('resize', view.resize);
})
.catch((error) => {
console.error(error);
});