Prop3D

Introduction

vtkProp3D is an abstract class used to represent an entity in a rendering
scene (i.e., vtkProp3D is a vtkProp with an associated transformation
matrix). It handles functions related to the position, orientation and
scaling. It combines these instance variables into one 4x4 transformation
matrix as follows: [x y z 1] = [x y z 1] Translate(-origin) Scale(scale)
Rot(y) Rot(x) Rot (z) Trans(origin) Trans(position). Both vtkActor and
vtkVolume are specializations of class vtkProp. The constructor defaults
to: origin(0,0,0) position=(0,0,0) orientation=(0,0,0), no user defined
matrix or transform, and no texture map.

Methods

addPosition

Add the position of the Prop3D in world coordinates.

Argument Type Required Description
deltaXYZ Yes

computeMatrix

Generate the matrix based on internal model.

extend

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

getBounds

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

getCenter

Get the center of the bounding box in world coordinates.

getIsIdentity

Check if there was a modification or transformation.

getLength

Get the length of the diagonal of the bounding box.

getMatrix

Get a reference to the Prop3D’s 4x4 composite matrix.
Get the matrix from the position, origin, scale and orientation This
matrix is cached, so multiple GetMatrix() calls will be efficient.

getOrientation

The ordering in which these rotations must be done to generate the same
matrix is RotateZ, RotateX, and finally RotateY. See also SetOrientation.

getOrientationByReference

Get a reference of the orientation of the Prop3D as s vector of X, Y and Z
rotation.

getOrientationQuaternion

Get the orientation quaternion of the Prop3D.
out is optional and will be created if not supplied.

Argument Type Required Description
out quat Yes

getOrientationWXYZ

Get the WXYZ orientation of the Prop3D.

getOrientationWXYZ

Get the WXYZ orientation of the Prop3D.

getOrigin

Get the origin of the Prop3D. This is the point about which all rotations
take place.

getOriginByReference

Get a reference of the origin of the Prop3D. This is the point about
which all rotations take place.

getPosition

Get the position of the Prop3D in world coordinates.

getPositionByReference

Get a refrence of the position of the Prop3D in world coordinates.

getScale

Get the scale of the actor.

getScaleByReference

Get a refrence of the scale of the actor.

getUserMatrix

Get the transformation matrix set for your own use.

getXRange

Get the Prop3D’s x range in world coordinates.

getYRange

Get the Prop3D’s y range in world coordinates.

getZRange

Get the Prop3D’s z range in world coordinates.

newInstance

Method use to create a new instance of vtkProp3D

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

rotateQuaternion

Rotate the Prop3D by the provided orientation quaternion.
If the provided quaternion is identity (~epsilon), this function does nothing.
The quaternion should follow the gl-matrix convention: [x,y,z,w]

Argument Type Required Description
orientationQuaternion quat Yes The quaternion to rotate the prop by.

rotateWXYZ

Rotate the Prop3D in degrees about an arbitrary axis specified by
the last three arguments. The axis is specified in world
coordinates. To rotate an about its model axes, use RotateX,
RotateY, RotateZ.

Argument Type Required Description
degrees Number Yes The angle value.
x Number Yes The x coordinate.
y Number Yes The y coordinate.
z Number Yes The z coordinate.

rotateX

Rotate the Prop3D in degrees about the X axis using the right hand
rule. The axis is the Prop3D’s X axis, which can change as other
rotations are performed. To rotate about the world X axis use
RotateWXYZ (angle, 1, 0, 0). This rotation is applied before all
others in the current transformation matrix.

Argument Type Required Description
angle Number Yes The angle value.

rotateY

Rotate the Prop3D in degrees about the Y axis using the right hand
rule. The axis is the Prop3D’s Y axis, which can change as other
rotations are performed. To rotate about the world Y axis use
RotateWXYZ (angle, 0, 1, 0). This rotation is applied before all
others in the current transformation matrix.

Argument Type Required Description
angle Number Yes The angle value.

rotateZ

Rotate the Prop3D in degrees about the Z axis using the right hand
rule. The axis is the Prop3D’s Z axis, which can change as other
rotations are performed. To rotate about the world Z axis use
RotateWXYZ (angle, 0, 0, 1). This rotation is applied before all
others in the current transformation matrix.

Argument Type Required Description
angle Number Yes The angle value.

setOrientation

Orientation is specified as X, Y and Z rotations in that order,
but they are performed as RotateZ, RotateX, and finally RotateY.

Argument Type Required Description
x Number Yes The x coordinate.
y Number Yes The y coordinate.
z Number Yes The z coordinate.

setOrigin

Set the origin of the Prop3D. This is the point about which all rotations
take place.

Argument Type Required Description
origin Array. Yes

setOrigin

Set the origin of the Prop3D. This is the point about which all rotations take place.

Argument Type Required Description
x Number Yes The x coordinate.
y Number Yes The y coordinate.
z Number Yes The z coordinate.

setOriginFrom

Set the origin of the Prop3D. This is the point about which all rotations
take place.

Argument Type Required Description
origin Array. Yes

setPosition

Set the origin of the Prop3D.
This is the point about which all rotations take place.

Argument Type Required Description
x Number Yes The x coordinate.
y Number Yes The y coordinate.
z Number Yes The z coordinate.

setPositionFrom

Set the origin of the Prop3D.

Argument Type Required Description
position Vector3 Yes

setScale

Set the scale of the actor.
Scaling in performed independently on the X, Y and Z axis. A scale of zero is illegal and will be replaced with one.

Argument Type Required Description
x Number Yes The x coordinate.
y Number Yes The y coordinate.
z Number Yes The z coordinate.

setScaleFrom

Argument Type Required Description
scale Array. Yes

setUserMatrix

In addition to the instance variables such as position and orientation,
you can add an additional transformation matrix for your own use. This
matrix is concatenated with the actor’s internal matrix, which you
implicitly create through the use of setPosition(), setOrigin() and
setOrientation().

Argument Type Required Description
matrix mat4 Yes

Source

index.d.ts
import { mat4, quat } from "gl-matrix";
import { Bounds, Vector3, Range } from "../../../types";
import vtkProp, { IPropInitialValues } from "../Prop";

export interface IProp3DInitialValues extends IPropInitialValues {
origin?: number[];
position?: Vector3;
orientation?: number[];
scale?: number[];
bounds?: Bounds;
isIdentity?: boolean;
}

export interface vtkProp3D extends vtkProp {

/**
* Add the position of the Prop3D in world coordinates.
* @param deltaXYZ
*/
addPosition(deltaXYZ: number[]): void;

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

/**
* Check if there was a modification or transformation.
* @default null
* @return {Boolean} true if no modification/transformation have been set.
*/
getIsIdentity(): boolean;

/**
* The ordering in which these rotations must be done to generate the same
* matrix is RotateZ, RotateX, and finally RotateY. See also `SetOrientation`.
* @return {Number[]} the orientation of the Prop3D as s vector of X, Y and Z rotation.
*/
getOrientation(): number[];

/**
* Get a reference of the orientation of the Prop3D as s vector of X, Y and Z
* rotation.
* @return {Number[]} the orientation of the Prop3D as s vector of X, Y and Z rotation.
*/
getOrientationByReference(): number[];

/**
* Get the WXYZ orientation of the Prop3D.
*/
getOrientationWXYZ(): number[];

/**
* Get the origin of the Prop3D. This is the point about which all rotations
* take place.
*/
getOrigin(): number[];

/**
* Get a reference of the origin of the Prop3D. This is the point about
* which all rotations take place.
*/
getOriginByReference(): number[];

/**
* Get the position of the Prop3D in world coordinates.
*/
getPosition(): number[];

/**
* Get a refrence of the position of the Prop3D in world coordinates.
*/
getPositionByReference(): number[];

/**
* Get the scale of the actor.
*/
getScale(): number[];

/**
* Get a refrence of the scale of the actor.
*/
getScaleByReference(): number[];

/**
* Get the WXYZ orientation of the Prop3D.
*/
getOrientationWXYZ(): number[];

/**
* Get the orientation quaternion of the Prop3D.
* out is optional and will be created if not supplied.
* @param {quat | undefined} out
*/
getOrientationQuaternion(out?: quat): quat;

/**
* Get a reference to the Prop3D’s 4x4 composite matrix.
* Get the matrix from the position, origin, scale and orientation This
* matrix is cached, so multiple GetMatrix() calls will be efficient.
*/
getMatrix(): mat4;

/**
* Get the center of the bounding box in world coordinates.
*/
getCenter(): number[];

/**
* Get the length of the diagonal of the bounding box.
*/
getLength(): number;

/**
* Get the Prop3D's x range in world coordinates.
*/
getXRange(): Range;

/**
* Get the Prop3D's y range in world coordinates.
*/
getYRange(): Range;

/**
* Get the Prop3D's z range in world coordinates.
*/
getZRange(): Range;

/**
* Get the transformation matrix set for your own use.
*/
getUserMatrix(): mat4;

/**
* Rotate the Prop3D in degrees about the X axis using the right hand
* rule. The axis is the Prop3D’s X axis, which can change as other
* rotations are performed. To rotate about the world X axis use
* RotateWXYZ (angle, 1, 0, 0). This rotation is applied before all
* others in the current transformation matrix.
* @param {Number} angle The angle value.
*/
rotateX(angle: number): void;

/**
* Rotate the Prop3D in degrees about the Y axis using the right hand
* rule. The axis is the Prop3D’s Y axis, which can change as other
* rotations are performed. To rotate about the world Y axis use
* RotateWXYZ (angle, 0, 1, 0). This rotation is applied before all
* others in the current transformation matrix.
* @param {Number} angle The angle value.
*/
rotateY(angle: number): void;

/**
* Rotate the Prop3D in degrees about the Z axis using the right hand
* rule. The axis is the Prop3D’s Z axis, which can change as other
* rotations are performed. To rotate about the world Z axis use
* RotateWXYZ (angle, 0, 0, 1). This rotation is applied before all
* others in the current transformation matrix.
* @param {Number} angle The angle value.
*/
rotateZ(angle: number): void;

/**
* Rotate the Prop3D in degrees about an arbitrary axis specified by
* the last three arguments. The axis is specified in world
* coordinates. To rotate an about its model axes, use RotateX,
* RotateY, RotateZ.
* @param {Number} degrees The angle value.
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
*/
rotateWXYZ(degrees: number, x: number, y: number, z: number): void;

/**
* Rotate the Prop3D by the provided orientation quaternion.
* If the provided quaternion is identity (~epsilon), this function does nothing.
* The quaternion should follow the gl-matrix convention: [x,y,z,w]
* @param {quat} orientationQuaternion The quaternion to rotate the prop by.
*/
rotateQuaternion(orientationQuaternion: quat): void;

/**
* Orientation is specified as X, Y and Z rotations in that order,
* but they are performed as RotateZ, RotateX, and finally RotateY.
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
*/
setOrientation(x: number, y: number, z: number): boolean;

/**
* Set the origin of the Prop3D. This is the point about which all rotations take place.
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
*/
setOrigin(x: number, y: number, z: number): boolean;

/**
* Set the origin of the Prop3D. This is the point about which all rotations
* take place.
* @param {Number[]} origin
*/
setOrigin(origin: number[]): boolean;


/**
* Set the origin of the Prop3D. This is the point about which all rotations
* take place.
* @param {Number[]} origin
*/
setOriginFrom(origin: number[]): boolean;

/**
* Set the origin of the Prop3D.
* This is the point about which all rotations take place.
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
*/
setPosition(x: number, y: number, z: number): boolean;

/**
* Set the origin of the Prop3D.
* @param {Vector3} position
*/
setPositionFrom(position: Vector3): boolean;

/**
* Set the scale of the actor.
* Scaling in performed independently on the X, Y and Z axis. A scale of zero is illegal and will be replaced with one.
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
*/
setScale(x: number, y: number, z: number): boolean;

/**
*
* @param {Number[]} scale
*/
setScaleFrom(scale: number[]): boolean;

/**
* In addition to the instance variables such as position and orientation,
* you can add an additional transformation matrix for your own use. This
* matrix is concatenated with the actor's internal matrix, which you
* implicitly create through the use of setPosition(), setOrigin() and
* setOrientation().
* @param {mat4} matrix
*/
setUserMatrix(matrix: mat4): void;

/**
* Generate the matrix based on internal model.
*/
computeMatrix(): void;
}

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

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

/**
* vtkProp3D is an abstract class used to represent an entity in a rendering
* scene (i.e., vtkProp3D is a vtkProp with an associated transformation
* matrix). It handles functions related to the position, orientation and
* scaling. It combines these instance variables into one 4x4 transformation
* matrix as follows: [x y z 1] = [x y z 1] Translate(-origin) Scale(scale)
* Rot(y) Rot(x) Rot (z) Trans(origin) Trans(position). Both vtkActor and
* vtkVolume are specializations of class vtkProp. The constructor defaults
* to: origin(0,0,0) position=(0,0,0) orientation=(0,0,0), no user defined
* matrix or transform, and no texture map.
*/
export declare const vtkProp3D: {
newInstance: typeof newInstance,
extend: typeof extend,
};
export default vtkProp3D;
index.js
import { quat, mat4 } from 'gl-matrix';

import macro from 'vtk.js/Sources/macros';
import vtkBoundingBox from 'vtk.js/Sources/Common/DataModel/BoundingBox';
import * as vtkMath from 'vtk.js/Sources/Common/Core/Math';
import vtkProp from 'vtk.js/Sources/Rendering/Core/Prop';

const VTK_EPSILON = 1e-6;

// ----------------------------------------------------------------------------
// vtkProp3D methods
// ----------------------------------------------------------------------------

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

publicAPI.addPosition = (deltaXYZ) => {
model.position = model.position.map(
(value, index) => value + deltaXYZ[index]
);
publicAPI.modified();
};

publicAPI.getOrientationWXYZ = () => {
const q = quat.create();
mat4.getRotation(q, model.rotation);
const oaxis = new Float64Array(3);
const w = quat.getAxisAngle(oaxis, q);
return [vtkMath.degreesFromRadians(w), oaxis[0], oaxis[1], oaxis[2]];
};

publicAPI.getOrientationQuaternion = (out = []) =>
mat4.getRotation(out, model.rotation);

publicAPI.rotateX = (val) => {
if (val === 0.0) {
return;
}
mat4.rotateX(
model.rotation,
model.rotation,
vtkMath.radiansFromDegrees(val)
);
publicAPI.modified();
};

publicAPI.rotateY = (val) => {
if (val === 0.0) {
return;
}
mat4.rotateY(
model.rotation,
model.rotation,
vtkMath.radiansFromDegrees(val)
);
publicAPI.modified();
};

publicAPI.rotateZ = (val) => {
if (val === 0.0) {
return;
}
mat4.rotateZ(
model.rotation,
model.rotation,
vtkMath.radiansFromDegrees(val)
);
publicAPI.modified();
};

publicAPI.rotateWXYZ = (degrees, x, y, z) => {
if (degrees === 0.0 || (x === 0.0 && y === 0.0 && z === 0.0)) {
return;
}

// convert to radians
const angle = vtkMath.radiansFromDegrees(degrees);

const q = quat.create();
quat.setAxisAngle(q, [x, y, z], angle);

const quatMat = new Float64Array(16);
mat4.fromQuat(quatMat, q);
mat4.multiply(model.rotation, model.rotation, quatMat);
publicAPI.modified();
};

publicAPI.rotateQuaternion = (orientationQuaternion) => {
if (Math.abs(orientationQuaternion[3]) >= 1 - VTK_EPSILON) {
return;
}

const oriQuatMat = mat4.fromQuat(
new Float64Array(16),
orientationQuaternion
);
mat4.multiply(model.rotation, model.rotation, oriQuatMat);
publicAPI.modified();
};

publicAPI.setOrientation = (x, y, z) => {
if (
x === model.orientation[0] &&
y === model.orientation[1] &&
z === model.orientation[2]
) {
return false;
}
model.orientation = [x, y, z];
mat4.identity(model.rotation);
publicAPI.rotateZ(z);
publicAPI.rotateX(x);
publicAPI.rotateY(y);
publicAPI.modified();
return true;
};

publicAPI.setUserMatrix = (matrix) => {
if (vtkMath.areMatricesEqual(model.userMatrix, matrix)) {
return false;
}
mat4.copy(model.userMatrix, matrix);
publicAPI.modified();
return true;
};

publicAPI.getMatrix = () => {
publicAPI.computeMatrix();
return model.matrix;
};

publicAPI.computeMatrix = () => {
// check whether or not need to rebuild the matrix
if (publicAPI.getMTime() > model.matrixMTime.getMTime()) {
mat4.identity(model.matrix);
if (model.userMatrix) {
mat4.multiply(model.matrix, model.matrix, model.userMatrix);
}
mat4.translate(model.matrix, model.matrix, model.origin);
mat4.translate(model.matrix, model.matrix, model.position);
mat4.multiply(model.matrix, model.matrix, model.rotation);
mat4.scale(model.matrix, model.matrix, model.scale);
mat4.translate(model.matrix, model.matrix, [
-model.origin[0],
-model.origin[1],
-model.origin[2],
]);
mat4.transpose(model.matrix, model.matrix);

// check for identity
model.isIdentity = true;
for (let i = 0; i < 4; ++i) {
for (let j = 0; j < 4; ++j) {
if ((i === j ? 1.0 : 0.0) !== model.matrix[i + j * 4]) {
model.isIdentity = false;
}
}
}
model.matrixMTime.modified();
}
};

publicAPI.getCenter = () => vtkBoundingBox.getCenter(model.bounds);
publicAPI.getLength = () => vtkBoundingBox.getLength(model.bounds);
publicAPI.getXRange = () => vtkBoundingBox.getXRange(model.bounds);
publicAPI.getYRange = () => vtkBoundingBox.getYRange(model.bounds);
publicAPI.getZRange = () => vtkBoundingBox.getZRange(model.bounds);

publicAPI.getUserMatrix = () => model.userMatrix;

function updateIdentityFlag() {
publicAPI.computeMatrix();
}

publicAPI.onModified(updateIdentityFlag);
}

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

const DEFAULT_VALUES = {
origin: [0, 0, 0],
position: [0, 0, 0],
orientation: [0, 0, 0],
rotation: null,
scale: [1, 1, 1],
bounds: [1, -1, 1, -1, 1, -1],

userMatrix: null,
userMatrixMTime: null,

cachedProp3D: null,
isIdentity: true,
matrixMTime: null,
};

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

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

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

model.matrixMTime = {};
macro.obj(model.matrixMTime);

// Build VTK API
macro.get(publicAPI, model, ['bounds', 'isIdentity']);
macro.getArray(publicAPI, model, ['orientation']);
macro.setGetArray(publicAPI, model, ['origin', 'position', 'scale'], 3);

// Object internal instance
model.matrix = mat4.identity(new Float64Array(16));
model.rotation = mat4.identity(new Float64Array(16));
model.userMatrix = mat4.identity(new Float64Array(16));
model.transform = null; // FIXME

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

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

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

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

export default { newInstance, extend };