Cursor3D

Introduction

vtkCursor3D is an object that generates a 3D representation of a cursor. The
cursor consists of a wireframe bounding box, three intersecting axes lines
that meet at the cursor focus, and “shadows” or projections of the axes
against the sides of the bounding box. Each of these components can be turned
on/off.

Usage

import vtkCursor3D from '@kitware/vtk.js/Filters/Sources/vtkCursor3D';

const cursor = vtkCursor3D.newInstance({focalPoint: [0, 0, 0], modelBounds: [-100, 100, -100, 100, -100, 100]});
const polyData = cursor.getOutputData();

Methods

allOff

Turn every part of the 3D cursor off.

allOn

Turn every part of the 3D cursor on.

extend

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

getAxes

getFocalPoint

Get the position of cursor focus.

getFocalPointByReference

getFocus

getModelBounds

Set the boundary of the 3D cursor.

getModelBoundsByReference

getOutline

getTranslationMode

Get the translation mode.

getWrap

Get the state of the cursor wrapping.

getXShadows

Get the state of the wireframe x-shadows.

getYShadows

Get the state of the wireframe y-shadows.

getZShadows

Get the state of the wireframe z-shadows.

newInstance

Method used to create a new instance of vtkCursor3D.

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

requestData

Expose methods

Argument Type Required Description
inData Yes
outData Yes

setAll

Argument Type Required Description
flag Boolean Yes

setAxes

Turn on/off the wireframe axes.

Argument Type Required Description
axes Boolean Yes

setFocalPoint

Set the position of cursor focus.
If translation mode is on, then the entire cursor (including bounding
box, cursor, and shadows) is translated. Otherwise, the focal point will
either be clamped to the bounding box, or wrapped, if Wrap is on. (Note:
this behavior requires that the bounding box is set prior to the focal
point.)

Argument Type Required Description
points Vector3 Yes

setModelBounds

Set the boundary of the 3D cursor.

Argument Type Required Description
bounds Bounds Yes The bounds of the 3D cursor.

setTranslationMode

Enable/disable the translation mode.
If on, changes in cursor position cause the entire widget to translate
along with the cursor.

Argument Type Required Description
translationMode Boolean Yes

setWrap

Turn on/off cursor wrapping.
If the cursor focus moves outside the specified bounds,
the cursor will either be restrained against the nearest “wall” (Wrap=off),
or it will wrap around (Wrap=on).

Argument Type Required Description
wrap Number Yes

setXShadows

Turn on/off the wireframe x-shadows.

Argument Type Required Description
xLength Number Yes

setYShadows

Turn on/off the wireframe y-shadows.

Argument Type Required Description
yLength Number Yes

setZShadows

Turn on/off the wireframe z-shadows.

Argument Type Required Description
zLength Number Yes

Source

index.d.ts
import { vtkAlgorithm, vtkObject } from '../../../interfaces';
import vtkPolyData from '../../../Common/DataModel/PolyData';
import { Bounds, Vector3 } from '../../../types';

/**
*
*/
export interface ICursor3DInitialValues {
modelBounds?: Bounds;
focalPoint?: Vector3;
outline?: boolean;
axes?: boolean;
xShadows?: boolean;
yShadows?: boolean;
zShadows?: boolean;
wrap?: boolean;
translationMode?: boolean;
}

type vtkCursor3DBase = vtkObject &
Omit<
vtkAlgorithm,
| 'getInputData'
| 'setInputData'
| 'setInputConnection'
| 'getInputConnection'
| 'addInputConnection'
| 'addInputData'
>;

export interface vtkCursor3D extends vtkCursor3DBase {
/**
* Turn every part of the 3D cursor off.
*/
allOff(): void;

/**
* Turn every part of the 3D cursor on.
*/
allOn(): void;

/**
*
*/
getAxes(): boolean;

/**
* Get the position of cursor focus.
*/
getFocalPoint(): Vector3;

/**
*
*/
getFocalPointByReference(): Vector3;

/**
*
* @default null
*/
getFocus(): null | vtkPolyData;

/**
* Set the boundary of the 3D cursor.
* @default [-1.0, 1.0, -1.0, 1.0, -1.0, 1.0]
*/
getModelBounds(): Bounds;

/**
*
* @default [-1.0, 1.0, -1.0, 1.0, -1.0, 1.0]
*/
getModelBoundsByReference(): Bounds;

/**
*
* @default true
*/
getOutline(): boolean;

/**
* Get the translation mode.
* @default false
*/
getTranslationMode(): boolean;

/**
* Get the state of the cursor wrapping.
* @default false
*/
getWrap(): boolean;

/**
* Get the state of the wireframe x-shadows.
* @default true
*/
getXShadows(): boolean;

/**
* Get the state of the wireframe y-shadows.
* @default true
*/
getYShadows(): boolean;

/**
* Get the state of the wireframe z-shadows.
* @default true
*/
getZShadows(): boolean;

/**
* Expose methods
* @param inData
* @param outData
*/
requestData(inData: any, outData: any): void;
/**
*
* @param {Boolean} flag
*/
setAll(flag: boolean): void;

/**
* Turn on/off the wireframe axes.
* @param {Boolean} axes
*/
setAxes(axes: boolean): boolean;

/**
* Set the position of cursor focus.
* If translation mode is on, then the entire cursor (including bounding
* box, cursor, and shadows) is translated. Otherwise, the focal point will
* either be clamped to the bounding box, or wrapped, if Wrap is on. (Note:
* this behavior requires that the bounding box is set prior to the focal
* point.)
* @param {Vector3} points
*/
setFocalPoint(points: Vector3): boolean;

/**
* Set the boundary of the 3D cursor.
* @param {Bounds} bounds The bounds of the 3D cursor.
*/
setModelBounds(bounds: Bounds): boolean;

/**
* Enable/disable the translation mode.
* If on, changes in cursor position cause the entire widget to translate
* along with the cursor.
* @param {Boolean} translationMode
*/
setTranslationMode(translationMode: boolean): boolean;

/**
* Turn on/off cursor wrapping.
* If the cursor focus moves outside the specified bounds,
* the cursor will either be restrained against the nearest "wall" (Wrap=off),
* or it will wrap around (Wrap=on).
* @param {Number} wrap
*/
setWrap(wrap: number): boolean;

/**
* Turn on/off the wireframe x-shadows.

* @param {Number} xLength
*/
setXShadows(xLength: number): boolean;

/**
* Turn on/off the wireframe y-shadows.

* @param {Number} yLength
*/
setYShadows(yLength: number): boolean;

/**
* Turn on/off the wireframe z-shadows.
* @param {Number} zLength
*/
setZShadows(zLength: number): boolean;
}

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

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

/**
* vtkCursor3D is an object that generates a 3D representation of a cursor. The
* cursor consists of a wireframe bounding box, three intersecting axes lines
* that meet at the cursor focus, and "shadows" or projections of the axes
* against the sides of the bounding box. Each of these components can be turned
* on/off.
*
* @example
* ```js
* import vtkCursor3D from '@kitware/vtk.js/Filters/Sources/vtkCursor3D';
*
* const cursor = vtkCursor3D.newInstance({focalPoint: [0, 0, 0], modelBounds: [-100, 100, -100, 100, -100, 100]});
* const polyData = cursor.getOutputData();
* ```
*/
export declare const vtkCursor3D: {
newInstance: typeof newInstance;
extend: typeof extend;
};
export default vtkCursor3D;
index.js
import macro from 'vtk.js/Sources/macros';
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
import vtkCellArray from 'vtk.js/Sources/Common/Core/CellArray';
import vtkPoints from 'vtk.js/Sources/Common/Core/Points';
// ----------------------------------------------------------------------------
// vtkCursor3D methods
// ----------------------------------------------------------------------------

function vtkCursor3D(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkCursor3D');
// Public API methods
publicAPI.setModelBounds = (bounds) => {
if (!Array.isArray(bounds) || bounds.length < 6) {
return;
}
if (
model.modelBounds[0] === bounds[0] &&
model.modelBounds[1] === bounds[1] &&
model.modelBounds[2] === bounds[2] &&
model.modelBounds[3] === bounds[3] &&
model.modelBounds[4] === bounds[4] &&
model.modelBounds[5] === bounds[5]
) {
return;
}
publicAPI.modified();
// Doing type convert, make sure it is a number array.
// Without correct coversion, the array may contains string which cause
// the wrapping and clampping works incorrectly.
model.modelBounds = bounds.map((v) => Number(v));
for (let i = 0; i < 3; ++i) {
model.modelBounds[2 * i] = Math.min(
model.modelBounds[2 * i],
model.modelBounds[2 * i + 1]
);
}
};

publicAPI.setFocalPoint = (points) => {
if (!Array.isArray(points) || points.length < 3) {
return;
}
if (
points[0] === model.focalPoint[0] &&
points[1] === model.focalPoint[1] &&
points[2] === model.focalPoint[2]
) {
return;
}
publicAPI.modified();
const v = [];
for (let i = 0; i < 3; i++) {
v[i] = points[i] - model.focalPoint[i];
model.focalPoint[i] = Number(points[i]);

if (model.translationMode) {
model.modelBounds[2 * i] += v[i];
model.modelBounds[2 * i + 1] += v[i];
}
// wrap
else if (model.wrap) {
model.focalPoint[i] =
model.modelBounds[2 * i] +
(((model.focalPoint[i] - model.modelBounds[2 * i]) * 1.0) %
((model.modelBounds[2 * i + 1] - model.modelBounds[2 * i]) * 1.0));
}
// clamp
else {
if (points[i] < model.modelBounds[2 * i]) {
model.focalPoint[i] = model.modelBounds[2 * i];
}
if (points[i] > model.modelBounds[2 * i + 1]) {
model.focalPoint[i] = model.modelBounds[2 * i + 1];
}
}
}
};

publicAPI.setAll = (flag) => {
publicAPI.setOutline(flag);
publicAPI.setAxes(flag);
publicAPI.setXShadows(flag);
publicAPI.setYShadows(flag);
publicAPI.setZShadows(flag);
};

publicAPI.allOn = () => {
publicAPI.setAll(true);
};

publicAPI.allOff = () => {
publicAPI.setAll(false);
};

publicAPI.requestData = (inData, outData) => {
if (model.deleted) {
return;
}
let numPts = 0;
let numLines = 0;
// Check bounding box and origin
if (model.wrap) {
for (let i = 0; i < model.focalPoint.length; ++i) {
model.focalPoint[i] =
model.modelBounds[2 * i] +
(((model.focalPoint[i] - model.modelBounds[2 * i]) * 1.0) %
(model.modelBounds[2 * i + 1] - model.modelBounds[2 * i]));
}
} else {
for (let i = 0; i < model.focalPoint.length; ++i) {
model.focalPoint[i] = Math.max(
model.focalPoint[i],
model.modelBounds[2 * i]
);
model.focalPoint[i] = Math.min(
model.focalPoint[i],
model.modelBounds[2 * i + 1]
);
}
}
// allocate storage
if (model.axes) {
numPts += 6;
numLines += 3;
}

if (model.outline) {
numPts += 8;
numLines += 12;
}

if (model.xShadows) {
numPts += 8;
numLines += 4;
}

if (model.yShadows) {
numPts += 8;
numLines += 4;
}

if (model.zShadows) {
numPts += 8;
numLines += 4;
}

if (numPts === 0) {
return;
}
const polyData = vtkPolyData.newInstance();
const newPts = vtkPoints.newInstance({ size: numPts * 3 });
// vtkCellArray is a supporting object that explicitly represents cell
// connectivity. The cell array structure is a raw integer list
// of the form: (n,id1,id2,...,idn, n,id1,id2,...,idn, ...)
// where n is the number of points in the cell, and id is a zero-offset index
// into an associated point list.
const newLines = vtkCellArray.newInstance({ size: numLines * (2 + 1) });
let pid = 0;
let cid = 0;
// Create axes
if (model.axes) {
newPts.getData()[pid * 3 + 0] = model.modelBounds[0];
newPts.getData()[pid * 3 + 1] = model.focalPoint[1];
newPts.getData()[pid * 3 + 2] = model.focalPoint[2];
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[1];
newPts.getData()[pid * 3 + 1] = model.focalPoint[1];
newPts.getData()[pid * 3 + 2] = model.focalPoint[2];
++pid;
newLines.getData()[cid * 3 + 0] = 2;
newLines.getData()[cid * 3 + 1] = pid - 2;
newLines.getData()[cid * 3 + 2] = pid - 1;
++cid;
newPts.getData()[pid * 3 + 0] = model.focalPoint[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[2];
newPts.getData()[pid * 3 + 2] = model.focalPoint[2];
++pid;
newPts.getData()[pid * 3 + 0] = model.focalPoint[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[3];
newPts.getData()[pid * 3 + 2] = model.focalPoint[2];
++pid;
newLines.getData()[cid * 3 + 0] = 2;
newLines.getData()[cid * 3 + 1] = pid - 2;
newLines.getData()[cid * 3 + 2] = pid - 1;
++cid;
newPts.getData()[pid * 3 + 0] = model.focalPoint[0];
newPts.getData()[pid * 3 + 1] = model.focalPoint[1];
newPts.getData()[pid * 3 + 2] = model.modelBounds[4];
++pid;
newPts.getData()[pid * 3 + 0] = model.focalPoint[0];
newPts.getData()[pid * 3 + 1] = model.focalPoint[1];
newPts.getData()[pid * 3 + 2] = model.modelBounds[5];
++pid;
newLines.getData()[cid * 3 + 0] = 2;
newLines.getData()[cid * 3 + 1] = pid - 2;
newLines.getData()[cid * 3 + 2] = pid - 1;
++cid;
}
// create outline
if (model.outline) {
// first traid
newPts.getData()[pid * 3 + 0] = model.modelBounds[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[2];
newPts.getData()[pid * 3 + 2] = model.modelBounds[4];
const corner024 = pid;
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[1];
newPts.getData()[pid * 3 + 1] = model.modelBounds[2];
newPts.getData()[pid * 3 + 2] = model.modelBounds[4];
const corner124 = pid;
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[3];
newPts.getData()[pid * 3 + 2] = model.modelBounds[4];
const corner034 = pid;
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[2];
newPts.getData()[pid * 3 + 2] = model.modelBounds[5];
const corner025 = pid;
++pid;
newLines.getData()[(cid + 0) * 3 + 0] = 2;
newLines.getData()[(cid + 0) * 3 + 1] = corner024;
newLines.getData()[(cid + 0) * 3 + 2] = corner124;
newLines.getData()[(cid + 1) * 3 + 0] = 2;
newLines.getData()[(cid + 1) * 3 + 1] = corner024;
newLines.getData()[(cid + 1) * 3 + 2] = corner034;
newLines.getData()[(cid + 2) * 3 + 0] = 2;
newLines.getData()[(cid + 2) * 3 + 1] = corner024;
newLines.getData()[(cid + 2) * 3 + 2] = corner025;
cid += 3;
// second triad
newPts.getData()[pid * 3 + 0] = model.modelBounds[1];
newPts.getData()[pid * 3 + 1] = model.modelBounds[3];
newPts.getData()[pid * 3 + 2] = model.modelBounds[5];
const corner135 = pid;
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[3];
newPts.getData()[pid * 3 + 2] = model.modelBounds[5];
const corner035 = pid;
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[1];
newPts.getData()[pid * 3 + 1] = model.modelBounds[2];
newPts.getData()[pid * 3 + 2] = model.modelBounds[5];
const corner125 = pid;
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[1];
newPts.getData()[pid * 3 + 1] = model.modelBounds[3];
newPts.getData()[pid * 3 + 2] = model.modelBounds[4];
const corner134 = pid;
++pid;
newLines.getData()[(cid + 0) * 3 + 0] = 2;
newLines.getData()[(cid + 0) * 3 + 1] = corner135;
newLines.getData()[(cid + 0) * 3 + 2] = corner035;
newLines.getData()[(cid + 1) * 3 + 0] = 2;
newLines.getData()[(cid + 1) * 3 + 1] = corner135;
newLines.getData()[(cid + 1) * 3 + 2] = corner125;
newLines.getData()[(cid + 2) * 3 + 0] = 2;
newLines.getData()[(cid + 2) * 3 + 1] = corner135;
newLines.getData()[(cid + 2) * 3 + 2] = corner134;
cid += 3;
// Fill in remaining lines
// vtk.js do not support checking repeating insertion
newLines.getData()[(cid + 0) * 3 + 0] = 2;
newLines.getData()[(cid + 0) * 3 + 1] = corner124;
newLines.getData()[(cid + 0) * 3 + 2] = corner134;
newLines.getData()[(cid + 1) * 3 + 0] = 2;
newLines.getData()[(cid + 1) * 3 + 1] = corner124;
newLines.getData()[(cid + 1) * 3 + 2] = corner125;
cid += 2;
newLines.getData()[(cid + 0) * 3 + 0] = 2;
newLines.getData()[(cid + 0) * 3 + 1] = corner034;
newLines.getData()[(cid + 0) * 3 + 2] = corner134;
newLines.getData()[(cid + 1) * 3 + 0] = 2;
newLines.getData()[(cid + 1) * 3 + 1] = corner034;
newLines.getData()[(cid + 1) * 3 + 2] = corner035;
cid += 2;
newLines.getData()[(cid + 0) * 3 + 0] = 2;
newLines.getData()[(cid + 0) * 3 + 1] = corner025;
newLines.getData()[(cid + 0) * 3 + 2] = corner125;
newLines.getData()[(cid + 1) * 3 + 0] = 2;
newLines.getData()[(cid + 1) * 3 + 1] = corner025;
newLines.getData()[(cid + 1) * 3 + 2] = corner035;
cid += 2;
}
// create x-shadows
if (model.xShadows) {
for (let i = 0; i < 2; ++i) {
newPts.getData()[pid * 3 + 0] = model.modelBounds[i];
newPts.getData()[pid * 3 + 1] = model.modelBounds[2];
newPts.getData()[pid * 3 + 2] = model.focalPoint[2];
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[i];
newPts.getData()[pid * 3 + 1] = model.modelBounds[3];
newPts.getData()[pid * 3 + 2] = model.focalPoint[2];
++pid;
newLines.getData()[cid * 3 + 0] = 2;
newLines.getData()[cid * 3 + 1] = pid - 2;
newLines.getData()[cid * 3 + 2] = pid - 1;
++cid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[i];
newPts.getData()[pid * 3 + 1] = model.focalPoint[1];
newPts.getData()[pid * 3 + 2] = model.modelBounds[4];
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[i];
newPts.getData()[pid * 3 + 1] = model.focalPoint[1];
newPts.getData()[pid * 3 + 2] = model.modelBounds[5];
++pid;
newLines.getData()[cid * 3 + 0] = 2;
newLines.getData()[cid * 3 + 1] = pid - 2;
newLines.getData()[cid * 3 + 2] = pid - 1;
++cid;
}
}

// create y-shadows
if (model.yShadows) {
for (let i = 0; i < 2; ++i) {
newPts.getData()[pid * 3 + 0] = model.modelBounds[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[i + 2];
newPts.getData()[pid * 3 + 2] = model.focalPoint[2];
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[1];
newPts.getData()[pid * 3 + 1] = model.modelBounds[i + 2];
newPts.getData()[pid * 3 + 2] = model.focalPoint[2];
++pid;
newLines.getData()[cid * 3 + 0] = 2;
newLines.getData()[cid * 3 + 1] = pid - 2;
newLines.getData()[cid * 3 + 2] = pid - 1;
++cid;
newPts.getData()[pid * 3 + 0] = model.focalPoint[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[i + 2];
newPts.getData()[pid * 3 + 2] = model.modelBounds[4];
++pid;
newPts.getData()[pid * 3 + 0] = model.focalPoint[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[i + 2];
newPts.getData()[pid * 3 + 2] = model.modelBounds[5];
++pid;
newLines.getData()[cid * 3 + 0] = 2;
newLines.getData()[cid * 3 + 1] = pid - 2;
newLines.getData()[cid * 3 + 2] = pid - 1;
++cid;
}
}

// create z-shadows
if (model.zShadows) {
for (let i = 0; i < 2; ++i) {
newPts.getData()[pid * 3 + 0] = model.modelBounds[0];
newPts.getData()[pid * 3 + 1] = model.focalPoint[1];
newPts.getData()[pid * 3 + 2] = model.modelBounds[i + 4];
++pid;
newPts.getData()[pid * 3 + 0] = model.modelBounds[1];
newPts.getData()[pid * 3 + 1] = model.focalPoint[1];
newPts.getData()[pid * 3 + 2] = model.modelBounds[i + 4];
++pid;
newLines.getData()[cid * 3 + 0] = 2;
newLines.getData()[cid * 3 + 1] = pid - 2;
newLines.getData()[cid * 3 + 2] = pid - 1;
++cid;
newPts.getData()[pid * 3 + 0] = model.focalPoint[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[2];
newPts.getData()[pid * 3 + 2] = model.modelBounds[i + 4];
++pid;
newPts.getData()[pid * 3 + 0] = model.focalPoint[0];
newPts.getData()[pid * 3 + 1] = model.modelBounds[3];
newPts.getData()[pid * 3 + 2] = model.modelBounds[i + 4];
++pid;
newLines.getData()[cid * 3 + 0] = 2;
newLines.getData()[cid * 3 + 1] = pid - 2;
newLines.getData()[cid * 3 + 2] = pid - 1;
++cid;
}
}
const pts = vtkPoints.newInstance({ size: 3 });
pts.getData()[0] = model.focalPoint[0];
pts.getData()[1] = model.focalPoint[1];
pts.getData()[2] = model.focalPoint[2];
// update ourseleves
model.focus = vtkPolyData.newInstance();
model.focus.setPoints(pts);

polyData.setPoints(newPts);
polyData.setLines(newLines);
outData[0] = polyData;
};
}

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

const DEFAULT_VALUES = {
focus: null,
modelBounds: [-1.0, 1.0, -1.0, 1.0, -1.0, 1.0],
focalPoint: [0.0, 0.0, 0.0],
outline: true,
axes: true,
xShadows: true,
yShadows: true,
zShadows: true,
wrap: false,
translationMode: false,
};

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

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

// Build VTK API
// Cursor3D
macro.obj(publicAPI, model);
macro.get(publicAPI, model, ['focus']);
macro.getArray(publicAPI, model, ['modelBounds'], 6);
macro.getArray(publicAPI, model, ['focalPoint'], 3);
macro.setGet(publicAPI, model, ['outline']);
macro.setGet(publicAPI, model, ['axes']);
macro.setGet(publicAPI, model, ['xShadows']);
macro.setGet(publicAPI, model, ['yShadows']);
macro.setGet(publicAPI, model, ['zShadows']);
macro.setGet(publicAPI, model, ['wrap']);
macro.setGet(publicAPI, model, ['translationMode']);
macro.algo(publicAPI, model, 0, 1);
vtkCursor3D(publicAPI, model);
}

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

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

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

export default { newInstance, extend };