ViewNode

Introduction

a node within a VTK scene graph

This is the superclass for all nodes within a VTK scene graph. It contains
the API for a node. It supports the essential operations such as graph
creation, state storage and traversal. Child classes adapt this to VTK’s
major rendering classes. Grandchild classes adapt those to for APIs of
different rendering libraries.

Methods

addMissingNode

Argument Type Required Description
dobj Yes

addMissingNodes

Argument Type Required Description
dataObjs Yes

apply

Argument Type Required Description
renderPass vtkRenderPass Yes
prepass Yes

build

Builds myself.

Argument Type Required Description
prepass Yes

createViewNode

Argument Type Required Description
dataObj Yes

extend

Method used to decorate a given object (publicAPI+model) with vtkViewNode characteristics.

Argument Type Required Description
publicAPI Yes object on which methods will be bounds (public)
model Yes object on which data structure will be bounds (protected)
initialValues IViewNodeInitialValues No (default: {})

getChildren

getChildrenByReference

getFirstAncestorOfType

Find the first parent/grandparent of the desired type

Argument Type Required Description
type Yes

getMyFactory

getParent

getRenderable

Get The data object (thing to be rendered).

getViewNodeFor

Returns the view node that corresponding to the provided object
Will return NULL if a match is not found in self or descendents

Argument Type Required Description
dataObject Yes

getVisited

newInstance

Method used to create a new instance of vtkViewNode.

Argument Type Required Description
initialValues IViewNodeInitialValues No for pre-setting some of its content

prepareNodes

removeUnusedNodes

render

Makes calls to make self visible.

Argument Type Required Description
prepass Yes

setMyFactory

Argument Type Required Description
myFactory Yes

setParent

Argument Type Required Description
parent Yes

setRenderable

Argument Type Required Description
renderable Yes

setVisited

Argument Type Required Description
val Yes

traverse

Traverse this node with the specified pass. If you want to traverse your
children in a specific order or way override this method

Argument Type Required Description
renderPass vtkRenderPass Yes

Source

index.d.ts
import { vtkObject } from "../../../interfaces";
import vtkRenderPass from "../RenderPass";

export enum PASS_TYPES {
'Build',
'Render'
}

/**
*
*/
export interface IViewNodeInitialValues {
parent?: null,
renderable?: null,
myFactory?: null,
children?: Array<any>;
visited?: boolean;
}

export interface vtkViewNode extends vtkObject {

/**
*
* @param dobj
*/
addMissingNode(dobj: any): void;

/**
*
* @param dataObjs
*/
addMissingNodes(dataObjs: any): void;

/**
*
* @param {vtkRenderPass} renderPass
* @param prepass
*/
apply(renderPass: vtkRenderPass, prepass: boolean): void;

/**
* Builds myself.
* @param prepass
*/
build(prepass: any): void;

/**
*
* @param dataObj
*/
createViewNode(dataObj: any): void;

/**
*
*/
getChildren(): any;

/**
*
*/
getChildrenByReference(): any;

/**
* Find the first parent/grandparent of the desired type
* @param type
*/
getFirstAncestorOfType(type: any): void;

/**
*
*/
getMyFactory(): any;

/**
*
*/
getParent(): any;

/**
* Get The data object (thing to be rendered).
*/
getRenderable(): any;

/**
* Returns the view node that corresponding to the provided object
* Will return NULL if a match is not found in self or descendents
* @param dataObject
*/
getViewNodeFor(dataObject: any): any;

/**
*
*/
getVisited(): boolean;


//invokeEvent
//onEvent(callback: (instance: vtkObject) => any): vtkSubscription;

/**
*
*/
prepareNodes(): void;

/**
*
*/
removeUnusedNodes(): void;

/**
* Makes calls to make self visible.
* @param prepass
*/
render(prepass: any): void;

/**
*
* @param myFactory
*/
setMyFactory(myFactory: any): boolean;

/**
*
* @param parent
*/
setParent(parent: any): boolean;

/**
*
* @param renderable
*/
setRenderable(renderable: any): boolean;

/**
*
* @param val
*/
setVisited(val: boolean): void;

/**
* Traverse this node with the specified pass. If you want to traverse your
* children in a specific order or way override this method
* @param {vtkRenderPass} renderPass
*/
traverse(renderPass: vtkRenderPass): void;
}

/**
* Method used to decorate a given object (publicAPI+model) with vtkViewNode characteristics.
*
* @param publicAPI object on which methods will be bounds (public)
* @param model object on which data structure will be bounds (protected)
* @param {IViewNodeInitialValues} [initialValues] (default: {})
*/
export function extend(publicAPI: object, model: object, initialValues?: IViewNodeInitialValues): void;

/**
* Method used to create a new instance of vtkViewNode.
* @param {IViewNodeInitialValues} [initialValues] for pre-setting some of its content
*/
export function newInstance(initialValues?: IViewNodeInitialValues): vtkViewNode;

/**
* a node within a VTK scene graph
*
* This is the superclass for all nodes within a VTK scene graph. It contains
* the API for a node. It supports the essential operations such as graph
* creation, state storage and traversal. Child classes adapt this to VTK's
* major rendering classes. Grandchild classes adapt those to for APIs of
* different rendering libraries.
*/
export declare const vtkViewNode: {
newInstance: typeof newInstance,
extend: typeof extend,
};
export default vtkViewNode;
index.js
import macro from 'vtk.js/Sources/macros';

const { vtkErrorMacro } = macro;

const PASS_TYPES = ['Build', 'Render'];

// ----------------------------------------------------------------------------
// vtkViewNode methods
// ----------------------------------------------------------------------------

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

// Builds myself.
publicAPI.build = (prepass) => {};

// Renders myself
publicAPI.render = (prepass) => {};

publicAPI.traverse = (renderPass) => {
// we can choose to do special
// traversal here based on pass
const passTraversal = renderPass.getTraverseOperation();
const fn = publicAPI[passTraversal];
if (fn) {
fn(renderPass);
return;
}

// default traversal
publicAPI.apply(renderPass, true);

for (let index = 0; index < model.children.length; index++) {
model.children[index].traverse(renderPass);
}

publicAPI.apply(renderPass, false);
};

publicAPI.apply = (renderPass, prepass) => {
const customRenderPass = publicAPI[renderPass.getOperation()];
if (customRenderPass) {
customRenderPass(prepass, renderPass);
}
};

publicAPI.getViewNodeFor = (dataObject) => {
if (model.renderable === dataObject) {
return publicAPI;
}

for (let index = 0; index < model.children.length; ++index) {
const child = model.children[index];
const vn = child.getViewNodeFor(dataObject);
if (vn) {
return vn;
}
}
return undefined;
};

publicAPI.getFirstAncestorOfType = (type) => {
if (!model._parent) {
return null;
}
if (model._parent.isA(type)) {
return model._parent;
}
return model._parent.getFirstAncestorOfType(type);
};

// add a missing node/child for the passed in renderables. This should
// be called only in between prepareNodes and removeUnusedNodes
publicAPI.addMissingNode = (dobj) => {
if (!dobj) {
return;
}
const result = model._renderableChildMap.get(dobj);
// if found just mark as visited
if (result !== undefined) {
result.setVisited(true);
} else {
// otherwise create a node
const newNode = publicAPI.createViewNode(dobj);
if (newNode) {
newNode.setParent(publicAPI);
newNode.setVisited(true);
model._renderableChildMap.set(dobj, newNode);
model.children.push(newNode);
}
}
};

// add missing nodes/children for the passed in renderables. This should
// be called only in between prepareNodes and removeUnusedNodes
publicAPI.addMissingNodes = (dataObjs) => {
if (!dataObjs || !dataObjs.length) {
return;
}

for (let index = 0; index < dataObjs.length; ++index) {
const dobj = dataObjs[index];
const result = model._renderableChildMap.get(dobj);
// if found just mark as visited
if (result !== undefined) {
result.setVisited(true);
} else {
// otherwise create a node
const newNode = publicAPI.createViewNode(dobj);
if (newNode) {
newNode.setParent(publicAPI);
newNode.setVisited(true);
model._renderableChildMap.set(dobj, newNode);
model.children.push(newNode);
}
}
}
};

// ability to add children that have no renderable use in the same manner
// as addMissingNodes This case is when a normal viewnode wants to
// delegate passes to a helper or child that doeasn't map to a clear
// renderable or any renderable
publicAPI.addMissingChildren = (children) => {
if (!children || !children.length) {
return;
}

for (let index = 0; index < children.length; ++index) {
const child = children[index];
const cindex = model.children.indexOf(child);
if (cindex === -1) {
child.setParent(publicAPI);
model.children.push(child);
}
child.setVisited(true);
}
};

publicAPI.prepareNodes = () => {
for (let index = 0; index < model.children.length; ++index) {
model.children[index].setVisited(false);
}
};

publicAPI.setVisited = (val) => {
model.visited = val;
};

publicAPI.removeUnusedNodes = () => {
let visitedCount = 0;
for (let index = 0; index < model.children.length; ++index) {
const child = model.children[index];
const visited = child.getVisited();
if (visited) {
model.children[visitedCount++] = child;
child.setVisited(false);
} else {
const renderable = child.getRenderable();
if (renderable) {
model._renderableChildMap.delete(renderable);
}
child.delete();
}
}

model.children.length = visitedCount;
};

publicAPI.createViewNode = (dataObj) => {
if (!model.myFactory) {
vtkErrorMacro('Cannot create view nodes without my own factory');
return null;
}
const ret = model.myFactory.createNode(dataObj);
if (ret) {
ret.setRenderable(dataObj);
}
return ret;
};

const parentDelete = publicAPI.delete;
publicAPI.delete = () => {
for (let i = 0; i < model.children.length; i++) {
model.children[i].delete();
}
parentDelete();
};
}

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

const DEFAULT_VALUES = {
// _parent: null,
renderable: null,
myFactory: null,
children: [],
visited: false,
};

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

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

// Build VTK API
macro.obj(publicAPI, model);
macro.event(publicAPI, model, 'event');

model._renderableChildMap = new Map();

macro.get(publicAPI, model, ['visited']);
macro.setGet(publicAPI, model, ['_parent', 'renderable', 'myFactory']);
macro.getArray(publicAPI, model, ['children']);
macro.moveToProtected(publicAPI, model, ['parent']);

// Object methods
vtkViewNode(publicAPI, model);
}

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

const newInstance = macro.newInstance(extend, 'vtkViewNode');

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

export default { newInstance, extend, PASS_TYPES };