JavaScript: Visualization Toolkit 16 kann Multikomponenten von Bildern rendern

Das neue Major Release der freien Bibliothek zur Datenvisualisierung beherrscht weitere Arten der Bildmanipulation und unterstützt Webpack 5.

In Pocket speichern vorlesen Druckansicht

(Bild: agsandrew/Shutterstock.com)

Lesezeit: 3 Min.
Von
  • Silke Hahn
Inhaltsverzeichnis

Die JavaScript-Implementierung des Visualization Toolkit (VSK.js) liegt in der 16. Hauptversion vor. Die letzte Blogmeldung der Entwickler der quelloffenen Bibliothek für wissenschaftliches Visualisieren liegt schon etwas zurück: Zuletzt hatten sie 2019 Version 9 per Blogbeitrag angekündigt, die insgesamt sieben dazwischenliegenden Versionen dürften trotz semantischer Versionierung nur kleinere Updates erhalten haben.

Multikomponenten-Rendern von Bildern mit VTK.js 16

(Bild: Kitware.com)

VSK.js 16 unterstützt Webpack 5 und ist für das Testen zur Continuous Integration/Continuous Delivery (CI/CD)-Plattform GitHub Actions umgezogen. Ab der aktuellen Version sollen die Abhängigkeiten der Bibliothek raschere Aktualisierungen erfahren. Die Abhängigkeit von der kw-web-suite entfällt laut Blogmeldung, und ein neuer Release-Kanal ist hinzugekommen: Mit vtk.js@beta wollen die Entwickler Breaking Changes künftig vor dem Release testen.

Im Bereich der Visualisierung bietet die neue Version das Multikomponenten-Rendern von Bildern nach Schnitten und Umfang. Neu ist auch ein zweidimensionaler Convolution Filter für den Grafikprozessor. Ein externer Entwickler steuerte dem Release das Volume Clipping als Neuerung bei. Ein Highlight sind die Zeitreihen, die sich aus VTP-Dateien erstellen lassen – hierzu bietet das Kitware-Repository eine Live-Demo samt Quellcode:

import 'vtk.js/Sources/favicon';

import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
import vtkXMLPolyDataReader from 'vtk.js/Sources/IO/XML/XMLPolyDataReader';
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper';
import vtkHttpDataAccessHelper from 'vtk.js/Sources/IO/Core/DataAccessHelper/HttpDataAccessHelper';

import controlPanel from './controller.html';

const { fetchBinary } = vtkHttpDataAccessHelper;

// ----------------------------------------------------------------------------
// Standard rendering code setup
// ----------------------------------------------------------------------------

const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
  background: [0, 0, 0],
});
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();

const mapper = vtkMapper.newInstance();
mapper.setInputData(vtkPolyData.newInstance());

const actor = vtkActor.newInstance();
actor.setMapper(mapper);

renderer.addActor(actor);
renderer.resetCamera();
renderWindow.render();

// ----------------------------------------------------------------------------
// Example code
// ----------------------------------------------------------------------------
// Download a series of VTP files in a time series, sort them by time, and
// then display them in a playback series.
// ----------------------------------------------------------------------------

const BASE_URL = 'https://kitware.github.io/vtk-js-datasets/data/vtp/can/';

function downloadTimeSeries() {
  const files = [
    'can_0.vtp',
    'can_5.vtp',
    'can_10.vtp',
    'can_15.vtp',
    'can_20.vtp',
    'can_25.vtp',
    'can_30.vtp',
    'can_35.vtp',
    'can_40.vtp',
  ];
  return Promise.all(
    files.map((filename) =>
      fetchBinary(`${BASE_URL}/${filename}`).then((binary) => {
        const reader = vtkXMLPolyDataReader.newInstance();
        reader.parseAsArrayBuffer(binary);
        return reader.getOutputData(0);
      })
    )
  );
}

function getDataTimeStep(vtkObj) {
  const arr = vtkObj.getFieldData().getArrayByName('TimeValue');
  if (arr) {
    return arr.getData()[0];
  }
  return null;
}

function setVisibleDataset(ds) {
  mapper.setInputData(ds);
  renderer.resetCamera();
  renderWindow.render();
}

// -----------------------------------------------------------
// UI control handling
// -----------------------------------------------------------

function uiUpdateSlider(max) {
  const timeslider = document.querySelector('#timeslider');
  timeslider.min = 0;
  timeslider.max = max - 1;
  timeslider.step = 1;
}

fullScreenRenderer.addController(controlPanel);

// -----------------------------------------------------------
// example code logic
// -----------------------------------------------------------

let timeSeriesData = [];

const timeslider = document.querySelector('#timeslider');
const timevalue = document.querySelector('#timevalue');

timeslider.addEventListener('input', (e) => {
  const activeDataset = timeSeriesData[Number(e.target.value)];
  if (activeDataset) {
    setVisibleDataset(activeDataset);
    timevalue.innerText = getDataTimeStep(activeDataset);
  }
});

downloadTimeSeries().then((downloadedData) => {
  timeSeriesData = downloadedData.filter((ds) => getDataTimeStep(ds) !== null);
  timeSeriesData.sort((a, b) => getDataTimeStep(a) - getDataTimeStep(b));

  uiUpdateSlider(timeSeriesData.length);
  timeslider.value = 0;

  // set up camera
  renderer.getActiveCamera().setPosition(0, 55, -22);
  renderer.getActiveCamera().setViewUp(0, 0, -1);

  setVisibleDataset(timeSeriesData[0]);
  timevalue.innerText = getDataTimeStep(timeSeriesData[0]);
});

// -----------------------------------------------------------
// Make some variables global so that you can inspect and
// modify objects in your browser's developer console:
// -----------------------------------------------------------

global.mapper = mapper;
global.actor = actor;
global.renderer = renderer;
global.renderWindow = renderWindow;

Aus Zeitreihen lassen sich ab VTK.js 16 Visualisierungen erstellen.

(Bild: Kitware.com)

Einige weitere Neuerungen betreffen die Kameramanipulation, so verfügt das Toolkit nun über eine Kameraansicht aus der Ich-Perspektive und eine Rotationsmöglichkeit der Kamera-Achse mittels Mausbewegungen (MouseCameraAxisRotateManipulator). Im Bereich Input/Output (I/O) ist ein STLWriter hinzugekommen, mit dem sich die Größe geometrischer Formen über das Mausrad skalieren lässt – auf GitHub lässt sich eine Live-Demo einsehen.

Das Exportieren von Szenen mit ParaView soll besser unterstützt werden als bislang, geht aus einem separaten Blogeintrag hervor. VTK.js 16 umfasst neue Reader wie Draco und PLY, verbesserte ITK-Intergration und es unterstützt Felddaten aus dem XML-Poly-Datenleser. Neben der Zufallstopologie unterstützen die Widgets nun SVG-Layer und das Skalieren der Pixel der Widget-Steuerungselemente (das Kitware-Repository hält ein Beispiel zur Veranschaulichung bereit).

PolyLineWidget: Pixelskalierung der Steuerungs-Handle eines Widgets

(Bild: Kitware.com)

Einige Funktionalitäten befinden sich noch in der Planungs- und Entwicklungsphase, ihr Einzug in die Visualisierungsbibliothek ist seitens VTK-Team geplant: Künftig sollen Modul-Builds der JavaScript-ES6-Klassenbibliothek zur Verfügung stehen. Statt Nutzern abzuverlangen, dass sie Libraries zum Verarbeiten von Assets in den Bundler ihrer Wahl wie Webpack einbinden, soll der ESM-Build von VTK.js Anwendern das Preprocessing von Assets abnehmen. Im Beta-Kanal vtk.js@beta ist diese Funktionalität laut Herausgebern schon verfügbar und sie soll bald auch im Standard-Releasekanal landen.

Die VTK.js-Entwickler haben auch eine React-Library in der Pipeline (react-vtk-js), mit der Nutzer Visualisierungsszenen deklarativ erstellen können. Die Bibliothek soll über das dash-vtk von Plotly erhältlich sein. Damit soll sich laut Blogeintrag das auf dem VTK.js basierende Visualisieren von einem Python-Server aus über die von Plotly entwickelte Infrastruktur rationalisieren lassen.

Mehr Informationen zum neuen Release lassen sich der Blogankündigung bei Kitware entnehmen. Im GitHub-Repository der VTK-Entwickler finden Interessierte den dazugehörigen Quellcode und Beispielvideos. Als Beispiel einer mit VTK.js gebauten App lässt sich ParaView Glance besichtigen.

(sih)