ImageSlice

Introduction

vtkImageSlice provides 2D image display support for vtk.
It can be associated with a vtkImageSlice prop and placed within a Renderer.

This class resolves coincident topology with the same methods as vtkMapper.

Methods

extend

Method use to decorate a given object (publicAPI+model) with vtkImageSlice 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 IImageSliceInitialValues No (default: {})

getActors

getBounds

Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].

getBoundsByReference

Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].

getBoundsForSlice

Get the bounds for a given slice as [xmin, xmax, ymin, ymax,zmin, zmax].

Argument Type Required Description
slice Number Yes The slice index. If undefined, the current slice is considered.
thickness Number No The slice thickness. If undefined, 0 is considered.

getImages

getIsOpaque

getMTime

Return the Modified Time which is a monotonic increasing integer
global for all vtkObjects.

This allow to solve a question such as:

  • Is that object created/modified after another one?
  • Do I need to re-execute this filter, or not? …

getMapper

getMaxXBound

Get the maximum X bound

getMaxYBound

Get the maximum Y bound

getMaxZBound

Get the maximum Z bound

getMinXBound

Get the minimum X bound

getMinYBound

Get the minimum Y bound

getMinZBound

Get the minimum Z bound

getProperty

getRedrawMTime

getSupportsSelection

hasTranslucentPolygonalGeometry

Always render during opaque pass, to keep the behavior
predictable and because depth-peeling kills alpha-blending.
In the future, the Renderer should render images in layers,
i.e. where each image will have a layer number assigned to it,
and the Renderer will do the images in their own pass.

makeProperty

Create a new property suitable for use with this type of Actor.

Argument Type Required Description
initialValues IImageSliceInitialValues No (default: {})

newInstance

Method use to create a new instance of vtkImageSlice

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

setForceOpaque

Argument Type Required Description
forceOpaque boolean Yes If true, render during opaque pass even if opacity value is below 1.0.

setForceTranslucent

Argument Type Required Description
forceTranslucent boolean Yes If true, render during translucent pass even if opacity value is 1.0.

setMapper

Argument Type Required Description
mapper vtkAbstractImageMapper Yes An instance that derives from vtkAbstractImageMapper.

setProperty

Argument Type Required Description
property vtkImageProperty Yes The vtkImageProperty instance.

Source

index.d.ts
import { Bounds } from '../../../types';
import vtkImageProperty, {
IImagePropertyInitialValues,
} from '../ImageProperty';
import vtkAbstractImageMapper from '../AbstractImageMapper';
import vtkProp3D, { IProp3DInitialValues } from '../Prop3D';

export interface IImageSliceInitialValues extends IProp3DInitialValues {
mapper?: vtkAbstractImageMapper;
property?: vtkImageProperty;
bounds?: Bounds;
}

export interface vtkImageSlice extends vtkProp3D {
/**
*
*/
getActors(): any;

/**
* Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].
* @return {Bounds} The bounds for the mapper.
*/
getBounds(): Bounds;

/**
* Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].
* @return {Bounds} The bounds for the mapper.
*/
getBoundsByReference(): Bounds;

/**
* Get the bounds for a given slice as [xmin, xmax, ymin, ymax,zmin, zmax].
* @param {Number} slice The slice index. If undefined, the current slice is considered.
* @param {Number} [thickness] The slice thickness. If undefined, 0 is considered.
* @return {Bounds} The bounds for a given slice.
*/
getBoundsForSlice(slice?: number, thickness?: number): Bounds;

/**
*
*/
getImages(): any;

/**
*
*/
getIsOpaque(): boolean;

/**
*
*/
getProperty(): vtkImageProperty;

/**
*
*/
getMapper(): vtkAbstractImageMapper;

/**
* Get the minimum X bound
*/
getMinXBound(): number;

/**
* Get the maximum X bound
*/
getMaxXBound(): number;

/**
* Get the minimum Y bound
*/
getMinYBound(): number;

/**
* Get the maximum Y bound
*/
getMaxYBound(): number;

/**
* Get the minimum Z bound
*/
getMinZBound(): number;

/**
* Get the maximum Z bound
*/
getMaxZBound(): number;

/**
* Return the `Modified Time` which is a monotonic increasing integer
* global for all vtkObjects.
*
* This allow to solve a question such as:
* - Is that object created/modified after another one?
* - Do I need to re-execute this filter, or not? ...
*
* @return {Number} the global modified time.
*/
getMTime(): number;

/**
*
*/
getRedrawMTime(): number;

/**
*
*/
getSupportsSelection(): boolean;

/**
* Always render during opaque pass, to keep the behavior
* predictable and because depth-peeling kills alpha-blending.
* In the future, the Renderer should render images in layers,
* i.e. where each image will have a layer number assigned to it,
* and the Renderer will do the images in their own pass.
*/
hasTranslucentPolygonalGeometry(): boolean;

/**
* Create a new property suitable for use with this type of Actor.
* @param {IImageSliceInitialValues} [initialValues] (default: {})
*/
makeProperty(initialValues?: IImagePropertyInitialValues): vtkImageProperty;

/**
*
* @param {vtkAbstractImageMapper} mapper An instance that derives from vtkAbstractImageMapper.
*/
setMapper(mapper: vtkAbstractImageMapper): boolean;

/**
*
* @param {vtkImageProperty} property The vtkImageProperty instance.
*/
setProperty(property: vtkImageProperty): boolean;

/**
*
* @param {boolean} forceOpaque If true, render during opaque pass even if opacity value is below 1.0.
*/
setForceOpaque(forceOpaque: boolean): boolean;

/**
*
* @param {boolean} forceTranslucent If true, render during translucent pass even if opacity value is 1.0.
*/
setForceTranslucent(forceTranslucent: boolean): boolean;
}

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

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

/**
* vtkImageSlice provides 2D image display support for vtk.
* It can be associated with a vtkImageSlice prop and placed within a Renderer.
*
* This class resolves coincident topology with the same methods as vtkMapper.
*/
export declare const vtkImageSlice: {
newInstance: typeof newInstance;
extend: typeof extend;
};
export default vtkImageSlice;
index.js
import { mat4 } from 'gl-matrix';
import macro from 'vtk.js/Sources/macros';
import vtkBoundingBox from 'vtk.js/Sources/Common/DataModel/BoundingBox';
import vtkProp3D from 'vtk.js/Sources/Rendering/Core/Prop3D';
import vtkImageProperty from 'vtk.js/Sources/Rendering/Core/ImageProperty';

const { vtkDebugMacro } = macro;

// ----------------------------------------------------------------------------
// vtkImageSlice methods
// ----------------------------------------------------------------------------

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

publicAPI.getActors = () => publicAPI;
publicAPI.getImages = () => publicAPI;

publicAPI.getIsOpaque = () => {
if (model.forceOpaque) {
return true;
}
if (model.forceTranslucent) {
return false;
}
// make sure we have a property
if (!model.property) {
// force creation of a property
publicAPI.getProperty();
}

let isOpaque = model.property.getOpacity() >= 1.0;

// are we using an opaque scalar array, if any?
isOpaque = isOpaque && (!model.mapper || model.mapper.getIsOpaque());

return isOpaque;
};

// Always render during opaque pass, to keep the behavior
// predictable and because depth-peeling kills alpha-blending.
// In the future, the Renderer should render images in layers,
// i.e. where each image will have a layer number assigned to it,
// and the Renderer will do the images in their own pass.
publicAPI.hasTranslucentPolygonalGeometry = () => false;

publicAPI.makeProperty = vtkImageProperty.newInstance;

publicAPI.getProperty = () => {
if (model.property === null) {
model.property = publicAPI.makeProperty();
}
return model.property;
};

publicAPI.getBounds = () => {
if (model.mapper === null) {
return model.bounds;
}

// Check for the special case when the mapper's bounds are unknown
const bds = model.mapper.getBounds();
if (!bds || bds.length !== 6) {
return bds;
}

// Check for the special case when the actor is empty.
if (bds[0] > bds[1]) {
model.mapperBounds = bds.concat(); // copy the mapper's bounds
model.bounds = [1, -1, 1, -1, 1, -1];
model.boundsMTime.modified();
return bds;
}

// Check if we have cached values for these bounds - we cache the
// values returned by model.mapper.getBounds() and we store the time
// of caching. If the values returned this time are different, or
// the modified time of this class is newer than the cached time,
// then we need to rebuild.
const zip = (rows) => rows[0].map((_, c) => rows.map((row) => row[c]));
if (
!model.mapperBounds ||
!zip([bds, model.mapperBounds]).reduce(
(a, b) => a && b[0] === b[1],
true
) ||
publicAPI.getMTime() > model.boundsMTime.getMTime()
) {
vtkDebugMacro('Recomputing bounds...');
model.mapperBounds = bds.map((x) => x);

publicAPI.computeMatrix();
const tmp4 = new Float64Array(16);
mat4.transpose(tmp4, model.matrix);

vtkBoundingBox.transformBounds(bds, tmp4, model.bounds);
model.boundsMTime.modified();
}
return model.bounds;
};

publicAPI.getBoundsForSlice = (slice, thickness) => {
// Check for the special case when the mapper's bounds are unknown
const bds = model.mapper.getBoundsForSlice(slice, thickness);
// Check for the special case when the actor is empty.
if (!vtkBoundingBox.isValid(bds)) {
return bds;
}

publicAPI.computeMatrix();
const tmp4 = new Float64Array(16);
mat4.transpose(tmp4, model.matrix);
const newBounds = vtkBoundingBox.transformBounds(bds, tmp4);
return newBounds;
};

//----------------------------------------------------------------------------
// Get the minimum X bound
publicAPI.getMinXBound = () => publicAPI.getBounds()[0];

// Get the maximum X bound
publicAPI.getMaxXBound = () => publicAPI.getBounds()[1];

// Get the minimum Y bound
publicAPI.getMinYBound = () => publicAPI.getBounds()[2];

// Get the maximum Y bound
publicAPI.getMaxYBound = () => publicAPI.getBounds()[3];

// Get the minimum Z bound
publicAPI.getMinZBound = () => publicAPI.getBounds()[4];

// Get the maximum Z bound
publicAPI.getMaxZBound = () => publicAPI.getBounds()[5];

publicAPI.getMTime = () => {
let mt = model.mtime;
if (model.property !== null) {
const time = model.property.getMTime();
mt = time > mt ? time : mt;
}

return mt;
};

publicAPI.getRedrawMTime = () => {
let mt = model.mtime;
if (model.mapper !== null) {
let time = model.mapper.getMTime();
mt = time > mt ? time : mt;
if (model.mapper.getInput() !== null) {
// FIXME !!! getInputAlgorithm / getInput
model.mapper.getInputAlgorithm().update();
time = model.mapper.getInput().getMTime();
mt = time > mt ? time : mt;
}
}
if (model.property !== null) {
let time = model.property.getMTime();
mt = time > mt ? time : mt;
if (model.property.getRGBTransferFunction() !== null) {
time = model.property.getRGBTransferFunction().getMTime();
mt = time > mt ? time : mt;
}
}
return mt;
};

publicAPI.getSupportsSelection = () =>
model.mapper ? model.mapper.getSupportsSelection() : false;
}

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

const DEFAULT_VALUES = {
mapper: null,
property: null,

forceOpaque: false,
forceTranslucent: false,

bounds: [...vtkBoundingBox.INIT_BOUNDS],
};

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

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

// Inheritance
vtkProp3D.extend(publicAPI, model, initialValues);

// vtkTimeStamp
model.boundsMTime = {};
macro.obj(model.boundsMTime);

// Build VTK API
macro.set(publicAPI, model, ['property']);
macro.setGet(publicAPI, model, ['mapper', 'forceOpaque', 'forceTranslucent']);

macro.getArray(publicAPI, model, ['bounds'], 6);

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

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

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

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

export default { newInstance, extend };