PiecewiseFunctionProxy

Methods

Source

Constants.js
const Defaults = {
Gaussians: [{ position: 0.5, height: 1, width: 0.5, xBias: 0.5, yBias: 0.5 }],
Points: [
[0, 0],
[1, 1],
],
Nodes: [
{ x: 0, y: 0, midpoint: 0.5, sharpness: 0 },
{ x: 1, y: 1, midpoint: 0.5, sharpness: 0 },
],
};

const Mode = {
Gaussians: 0,
Points: 1,
Nodes: 2,
};

export default {
Defaults,
Mode,
};
index.d.ts
import vtkLookupTableProxy from '../LookupTableProxy';
import vtkPiecewiseFunction from '../../../Common/DataModel/PiecewiseFunction';
import { VtkProxy } from '../../../macros';

// [x, r/h, g/s, b/v, m=0.5, s=0.0]
export interface PiecewiseGaussian {
position: number;
height: number;
width: number;
xBias: number;
yBias: number;
}

export interface PiecewiseNode {
x: number;
y: number;
midpoint: number;
sharpness: number;
}

export enum IPiecewiseFunctionProxyMode {
Gaussians = 0,
Points = 1,
Nodes = 2,
}

export interface IPiecewiseFunctionProxyDefaults {
Gaussians: PiecewiseGaussian[];
Points: number[][];
Nodes: PiecewiseNode[];
}

export interface vtkPiecewiseFunctionProxy extends VtkProxy {
setGaussians(gaussians: PiecewiseGaussian[]): void;
getGaussians(): PiecewiseGaussian[];
setPoints(points: number[][]): void;
getPoints(): number[][];
setNodes(nodes: PiecewiseNode[]): void;
getNodes(): PiecewiseNode[];
setMode(mode: number): void;
getMode(): number;
applyMode(): void;
getLookupTableProxy(): vtkLookupTableProxy;
setDataRange(min: number, max: number): void;
getDataRange(): [number, number];
getPiecewiseFunction(): vtkPiecewiseFunction;
}

export interface IPiecewiseFunctionProxyInitialValues {
piecewiseFunction?: vtkPiecewiseFunction;
}

export function newInstance(
initialValues?: IPiecewiseFunctionProxyInitialValues
): vtkPiecewiseFunctionProxy;

export declare const vtkPiecewiseFunctionProxy: {
newInstance: typeof newInstance;
Mode: typeof IPiecewiseFunctionProxyMode;
Defaults: IPiecewiseFunctionProxyDefaults;
};
export default vtkPiecewiseFunctionProxy;
index.js
import macro from 'vtk.js/Sources/macros';

import vtkPiecewiseFunction from 'vtk.js/Sources/Common/DataModel/PiecewiseFunction';
import vtkPiecewiseGaussianWidget from 'vtk.js/Sources/Interaction/Widgets/PiecewiseGaussianWidget';

import Constants from './Constants';

const { Mode, Defaults } = Constants;

// ----------------------------------------------------------------------------

function applyPointsToPiecewiseFunction(points, range, pwf) {
const width = range[1] - range[0];
const rescaled = points.map(([x, y]) => [x * width + range[0], y]);

pwf.removeAllPoints();
rescaled.forEach(([x, y]) => pwf.addPoint(x, y));
}

// ----------------------------------------------------------------------------

function applyNodesToPiecewiseFunction(nodes, range, pwf) {
const width = range[1] - range[0];
const rescaled = nodes.map((n) => ({ ...n, x: n.x * width + range[0] }));

pwf.setNodes(rescaled);
}

// ----------------------------------------------------------------------------

function copyGaussians(gaussians) {
// gaussians is assumed to be an array of gaussian objects
return gaussians.map((g) => ({ ...g }));
}

// ----------------------------------------------------------------------------
// vtkPiecewiseFunctionProxy methods
// ----------------------------------------------------------------------------

function vtkPiecewiseFunctionProxy(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkPiecewiseFunctionProxy');

model.piecewiseFunction =
model.piecewiseFunction || vtkPiecewiseFunction.newInstance();

// Takes an array of gaussians
publicAPI.setGaussians = (gaussians) => {
model.gaussians = copyGaussians(gaussians || []);
if (model.gaussians.length === 0) {
model.gaussians = copyGaussians(Defaults.Gaussians);
}
publicAPI.applyMode();
};

// Takes an array of points [x, y]
publicAPI.setPoints = (points) => {
model.points = (points || []).slice();
if (model.points.length === 0) {
model.points = Defaults.Points.slice();
}
publicAPI.applyMode();
};

// Takes an array of PiecewiseFunction nodes
publicAPI.setNodes = (nodes) => {
model.nodes = (nodes || []).slice();
if (model.nodes.length === 0) {
model.nodes = Defaults.Nodes.slice();
}
publicAPI.applyMode();
};

publicAPI.setMode = (mode) => {
if (model.mode === mode) {
return;
}
model.mode = mode;
publicAPI.applyMode();
};

publicAPI.applyMode = () => {
switch (model.mode) {
case Mode.Gaussians:
vtkPiecewiseGaussianWidget.applyGaussianToPiecewiseFunction(
model.gaussians,
255,
model.dataRange,
model.piecewiseFunction
);

publicAPI.modified();
break;

case Mode.Points:
applyPointsToPiecewiseFunction(
model.points,
model.dataRange,
model.piecewiseFunction
);

publicAPI.modified();
break;

case Mode.Nodes:
applyNodesToPiecewiseFunction(
model.nodes,
model.dataRange,
model.piecewiseFunction
);

publicAPI.modified();
break;

default:
// noop
}
};

publicAPI.getLookupTableProxy = () =>
model.proxyManager.getLookupTable(model.arrayName);

publicAPI.setDataRange = (min, max) => {
if (model.dataRange[0] !== min || model.dataRange[1] !== max) {
model.dataRange[0] = min;
model.dataRange[1] = max;
publicAPI.applyMode();
}
};

// Initialization ------------------------------------------------------------

publicAPI.applyMode();
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
mode: Mode.Gaussians,
gaussians: Defaults.Gaussians,
points: Defaults.Points,
nodes: Defaults.Nodes,
arrayName: 'No array associated',
arrayLocation: 'pointData',
dataRange: [0, 1],
};

// ----------------------------------------------------------------------------

function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);

macro.obj(publicAPI, model);
macro.setGet(publicAPI, model, ['arrayName']);
macro.get(publicAPI, model, [
'piecewiseFunction',
'gaussians',
'nodes',
'points',
'mode',
'dataRange',
]);

// Object specific methods
vtkPiecewiseFunctionProxy(publicAPI, model);

// Proxy handling
macro.proxy(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(
extend,
'vtkPiecewiseFunctionProxy'
);

// ----------------------------------------------------------------------------

export default { newInstance, extend, Mode, Defaults };