PlaneSource

Introduction

vtkPlaneSource creates an m x n array of quadrilaterals arranged as a regular
tiling in a plane. The plane is defined by specifying an origin point, and then
two other points that, together with the origin, define two axes for the plane.
These axes do not have to be orthogonal - so you can create a parallelogram.
(The axes must not be parallel.) The resolution of the plane (i.e., number of
subdivisions) is controlled by the ivars XResolution and YResolution.

By default, the plane is centered at the origin and perpendicular to the z-axis,
with width and height of length 1 and resolutions set to 1.

Usage

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

const plane = vtkPlaneSource.newInstance({ xResolution: 10, yResolution: 10 });
const polydata = plane.getOutputData();

Methods

extend

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

getCenter

Get the center of the plane.

getCenterByReference

Get the center of the plane.

getNormal

Get the normal of the plane.

getNormalByReference

Get the normal of the plane.

getOrigin

Get the origin of the plane, lower-left corner.

getOriginByReference

Get the origin of the plane, lower-left corner.

getPoint1

Get the x axes of the plane.

getPoint1ByReference

Get the x axes of the plane.

getPoint2

Get the y axes of the plane.

getPoint2ByReference

Get the y axes of the plane.

getXResolution

Get the x resolution of the plane.

getYResolution

Get the y resolution of the plane.

newInstance

Method used to create a new instance of vtkPlaneSource.

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

requestData

Argument Type Required Description
inData Yes
outData Yes

rotate

Rotate plane around a given axis

Argument Type Required Description
angle Yes theta Angle (radian) to rotate about
rotationAxis Yes Axis to rotate around

setCenter

Set the center of the plane.

Argument Type Required Description
center Vector3 Yes The coordinate of the center point.

setCenter

Set the center of the plane.

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

setNormal

Set the normal of the plane.

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

setNormal

Set the normal of the plane.

Argument Type Required Description
normal Vector3 Yes The normal coordinate.

setNormalFrom

Set the normal of the plane.

Argument Type Required Description
normal Vector3 Yes The normal coordinate.

setOrigin

Set the origin of the plane.

Argument Type Required Description
x Number Yes The x coordinate of the origin point.
y Number Yes The y coordinate of the origin point.
z Number Yes The z coordinate of the origin point.

setOrigin

Set the origin of the plane.

Argument Type Required Description
origin Vector3 Yes The coordinate of the origin point.

setOriginFrom

Set the origin of the plane.

Argument Type Required Description
origin Vector3 Yes The coordinate of the origin point.

setPoint1

Specify a point defining the first axis of the plane.

Argument Type Required Description
point1 Vector3 Yes

setPoint1

Specify a point defining the first axis of the plane.

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

setPoint2

Specify a point defining the second axis of the plane.

Argument Type Required Description
point2 Vector3 Yes

setPoint2

Specify a point defining the second axis of the plane.

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

setXResolution

Set the number of facets used to represent the cone.

Argument Type Required Description
xResolution Number Yes

setYResolution

Set the number of facets used to represent the cone.

Argument Type Required Description
yResolution Number Yes

updatePlane

Argument Type Required Description
v1 vec3 Yes
v2 vec3 Yes

Source

index.d.ts
import { vec3 } from 'gl-matrix';
import { vtkAlgorithm, vtkObject } from "../../../interfaces";
import { Vector3 } from '../../../types';

/**
*
*/
export interface IPlaneSourceInitialValues {
xResolution?: number;
yResolution?: number;
origin?: Vector3;
point1?: Vector3;
point2?: Vector3;
pointType?: string;
}

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

export interface vtkPlaneSource extends vtkPlaneSourceBase {

/**
* Get the center of the plane.
* @default [0, 0, 0]
*/
getCenter(): Vector3;

/**
* Get the center of the plane.
*/
getCenterByReference(): Vector3;

/**
* Get the normal of the plane.
* @default [0, 0, 1]
*/
getNormal(): Vector3;

/**
* Get the normal of the plane.
*/
getNormalByReference(): Vector3;

/**
* Get the origin of the plane, lower-left corner.
* @default [0, 0, 0]
*/
getOrigin(): Vector3;

/**
* Get the origin of the plane, lower-left corner.
*/
getOriginByReference(): Vector3;

/**
* Get the x axes of the plane.
* @default [1, 0, 0]
*/
getPoint1(): Vector3;

/**
* Get the x axes of the plane.
*/
getPoint1ByReference(): Vector3;

/**
* Get the y axes of the plane.
* @default [0, 1, 0]
*/
getPoint2(): Vector3;

/**
* Get the y axes of the plane.
*/
getPoint2ByReference(): Vector3;

/**
* Get the x resolution of the plane.
* @default 10
*/
getXResolution(): number;

/**
* Get the y resolution of the plane.
* @default 10
*/
getYResolution(): number;

/**
*
* @param inData
* @param outData
*/
requestData(inData: any, outData: any): void;

/**
* Rotate plane around a given axis
* @param angle theta Angle (radian) to rotate about
* @param rotationAxis Axis to rotate around
*/
rotate(angle: number, rotationAxis: vec3): void;

/**
* Set the center of the plane.
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
*/
setCenter(x: number, y: number, z: number): void;

/**
* Set the center of the plane.
* @param {Vector3} center The coordinate of the center point.
*/
setCenter(center: Vector3): void;

/**
* Set the normal of the plane.
* @param {Vector3} normal The normal coordinate.
*/
setNormal(normal: Vector3): boolean;

/**
* Set the normal of the plane.
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
*/
setNormal(x: number, y: number, z: number): boolean;

/**
* Set the normal of the plane.
* @param {Vector3} normal The normal coordinate.
*/
setNormalFrom(normal: Vector3): boolean;

/**
* Set the origin of the plane.
* @param {Vector3} origin The coordinate of the origin point.
*/
setOrigin(origin: Vector3): boolean;

/**
* Set the origin of the plane.
* @param {Number} x The x coordinate of the origin point.
* @param {Number} y The y coordinate of the origin point.
* @param {Number} z The z coordinate of the origin point.
*/
setOrigin(x: number, y: number, z: number): boolean;

/**
* Set the origin of the plane.
* @param {Vector3} origin The coordinate of the origin point.
*/
setOriginFrom(origin: Vector3): boolean;

/**
* Specify a point defining the first axis of the plane.
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
*/
setPoint1(x: number, y: number, z: number): boolean;

/**
* Specify a point defining the first axis of the plane.
* @param {Vector3} point1
*/
setPoint1(point1: Vector3): boolean;

/**
* Specify a point defining the second axis of the plane.
* @param {Number} x The x coordinate.
* @param {Number} y The y coordinate.
* @param {Number} z The z coordinate.
*/
setPoint2(x: number, y: number, z: number): boolean;

/**
* Specify a point defining the second axis of the plane.
* @param {Vector3} point2
*/
setPoint2(point2: Vector3): boolean;

/**
* Set the number of facets used to represent the cone.
* @param {Number} xResolution
*/
setXResolution(xResolution: number): boolean;

/**
* Set the number of facets used to represent the cone.
* @param {Number} yResolution
*/
setYResolution(yResolution: number): boolean;

/**
*
* @param {vec3} v1
* @param {vec3} v2
*/
updatePlane(v1: vec3, v2: vec3): boolean;
}

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

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

/**
* vtkPlaneSource creates an m x n array of quadrilaterals arranged as a regular
* tiling in a plane. The plane is defined by specifying an origin point, and then
* two other points that, together with the origin, define two axes for the plane.
* These axes do not have to be orthogonal - so you can create a parallelogram.
* (The axes must not be parallel.) The resolution of the plane (i.e., number of
* subdivisions) is controlled by the ivars XResolution and YResolution.
*
* By default, the plane is centered at the origin and perpendicular to the z-axis,
* with width and height of length 1 and resolutions set to 1.
*
* @example
* ```js
* import vtkPlaneSource from '@kitware/vtk.js/Filters/Sources/PlaneSource';
*
* const plane = vtkPlaneSource.newInstance({ xResolution: 10, yResolution: 10 });
* const polydata = plane.getOutputData();
* ```
*/
export declare const vtkPlaneSource: {
newInstance: typeof newInstance,
extend: typeof extend,
};
export default vtkPlaneSource;
index.js
import { vec3, mat4 } from 'gl-matrix';
import macro from 'vtk.js/Sources/macros';
import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray';
import * as vtkMath from 'vtk.js/Sources/Common/Core/Math';
import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder';

import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';

const { vtkWarningMacro } = macro;

const EPSILON = 1e-6;

// ----------------------------------------------------------------------------
// vtkPlaneSource methods
// ----------------------------------------------------------------------------

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

publicAPI.requestData = (inData, outData) => {
if (model.deleted) {
return;
}

const dataset = outData[0];

// Check input
const pointDataType = dataset
? dataset.getPoints().getDataType()
: model.pointType;
const pd = vtkPolyData.newInstance();
const v10 = [];
const v20 = [];
vtkMath.subtract(model.point1, model.origin, v10);
vtkMath.subtract(model.point2, model.origin, v20);

if (!publicAPI.updatePlane(v10, v20)) {
vtkWarningMacro('Bad plane definition');
return;
}

// hand create a plane with special scalars
const xres = model.xResolution;
const yres = model.yResolution;
const numPts = (xres + 1) * (yres + 1);
const numPolys = xres * yres;

// Points
const points = macro.newTypedArray(pointDataType, numPts * 3);
pd.getPoints().setData(points, 3);

// Cells
const polys = new Uint32Array(5 * numPolys);
pd.getPolys().setData(polys, 1);

// Normals
const normalsData = new Float32Array(numPts * 3);
const normals = vtkDataArray.newInstance({
numberOfComponents: 3,
values: normalsData,
name: 'Normals',
});
pd.getPointData().setNormals(normals);

// Texture coords
const tcData = new Float32Array(numPts * 2);
const tcoords = vtkDataArray.newInstance({
numberOfComponents: 2,
values: tcData,
name: 'TextureCoordinates',
});
pd.getPointData().setTCoords(tcoords);

const tc = new Float32Array(2);
let idx = 0;
for (let j = 0; j < yres + 1; j++) {
tc[1] = j / yres;
for (let i = 0; i < xres + 1; i++) {
tc[0] = i / xres;

points[idx * 3] = model.origin[0] + tc[0] * v10[0] + tc[1] * v20[0];
points[idx * 3 + 1] = model.origin[1] + tc[0] * v10[1] + tc[1] * v20[1];
points[idx * 3 + 2] = model.origin[2] + tc[0] * v10[2] + tc[1] * v20[2];

tcData[idx * 2] = tc[0];
tcData[idx * 2 + 1] = tc[1];

normalsData[idx * 3] = model.normal[0];
normalsData[idx * 3 + 1] = model.normal[1];
normalsData[idx * 3 + 2] = model.normal[2];

idx++;
}
}

// Generate polygon connectivity
//
idx = 0;
for (let j = 0; j < yres; j++) {
for (let i = 0; i < xres; i++) {
polys[idx * 5 + 0] = 4;
polys[idx * 5 + 1] = i + j * (xres + 1);
polys[idx * 5 + 2] = polys[idx * 5 + 1] + 1;
polys[idx * 5 + 3] = polys[idx * 5 + 1] + xres + 2;
polys[idx * 5 + 4] = polys[idx * 5 + 1] + xres + 1;

idx++;
}
}

// Update output
outData[0] = pd;
};

publicAPI.setNormal = (...normal) => {
let n = [];

if (normal.length === 1 || Array.isArray(normal[0])) {
n = [...normal[0]];
} else if (normal.length === 3) {
n = [normal[0], normal[1], normal[2]];
}

if (vtkMath.normalize(n) !== 0) {
const dp = vtkMath.dot(model.normal, n);

let theta = 0;
const rotationVector = [];

if (dp < 1.0) {
if (dp <= -1.0) {
theta = vtkMath.radiansFromDegrees(180.0);
vtkMath.subtract(model.point1, model.origin, rotationVector);
} else {
vtkMath.cross(model.normal, n, rotationVector);
theta = Math.acos(dp);
}
publicAPI.rotate(theta, rotationVector);
}
}
};

/**
* Rotate plane around a given axis
* @param {float} theta Angle (radian) to rotate about
* @param {vec3} rotationAxis Axis to rotate around
*/
publicAPI.rotate = (angle, rotationAxis) => {
if (Math.abs(angle) < EPSILON) {
return;
}
// Create rotation matrix
const transform = mat4.identity(new Float64Array(16));
const negCenter = [];
vec3.negate(negCenter, model.center);

mat4.translate(transform, transform, model.center);
mat4.rotate(transform, transform, angle, rotationAxis);
mat4.translate(transform, transform, negCenter);

vec3.transformMat4(model.origin, model.origin, transform);
vec3.transformMat4(model.point1, model.point1, transform);
vec3.transformMat4(model.point2, model.point2, transform);

vtkMatrixBuilder
.buildFromRadian()
.rotate(angle, rotationAxis)
.apply(model.normal);

publicAPI.modified();
};

publicAPI.setCenter = (...center) => {
let c = [];

if (center.length === 1 || Array.isArray(center[0])) {
c = [...center[0]];
} else if (center.length === 3) {
c = [center[0], center[1], center[2]];
}

if (!vec3.exactEquals(c, model.center)) {
const v1 = [];
vtkMath.subtract(model.point1, model.origin, v1);

const v2 = [];
vtkMath.subtract(model.point2, model.origin, v2);

for (let i = 0; i < 3; i++) {
model.center[i] = c[i];
model.origin[i] = model.center[i] - 0.5 * (v1[i] + v2[i]);
model.point1[i] = model.origin[i] + v1[i];
model.point2[i] = model.origin[i] + v2[i];
}
publicAPI.modified();
}
};

publicAPI.setPoint1 = (...point) => {
let point1 = [];

if (point.length === 1 || Array.isArray(point[0])) {
point1 = [...point[0]];
} else if (point.length === 3) {
point1 = [point[0], point[1], point[2]];
}

if (!vec3.exactEquals(point1, model.point1)) {
const v1 = [];
const v2 = [];

model.point1 = [...point1];
vtkMath.subtract(model.point1, model.origin, v1);
vtkMath.subtract(model.point2, model.origin, v2);

// set plane normal
publicAPI.updatePlane(v1, v2);
publicAPI.modified();
}
};

publicAPI.setPoint2 = (...point) => {
let point2 = [];

if (point.length === 1 || Array.isArray(point[0])) {
point2 = [...point[0]];
} else if (point.length === 3) {
point2 = [point[0], point[1], point[2]];
}

if (!vec3.exactEquals(point2, model.point2)) {
const v1 = [];
const v2 = [];

model.point2 = [...point2];
vtkMath.subtract(model.point1, model.origin, v1);
vtkMath.subtract(model.point2, model.origin, v2);

// set plane normal
publicAPI.updatePlane(v1, v2);
publicAPI.modified();
}
};

publicAPI.updatePlane = (v1, v2) => {
// set plane center
for (let i = 0; i < 3; i++) {
model.center[i] = model.origin[i] + 0.5 * (v1[i] + v2[i]);
}

// set plane normal
vtkMath.cross(v1, v2, model.normal);

return vtkMath.normalize(model.normal) !== 0.0;
};
}

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

const DEFAULT_VALUES = {
xResolution: 10,
yResolution: 10,
origin: [0, 0, 0],
point1: [1, 0, 0],
point2: [0, 1, 0],
pointType: 'Float64Array',
};

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

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

model.normal = [0, 0, 1];
model.center = [0, 0, 0];

// Build VTK API
macro.obj(publicAPI, model);
macro.setGet(publicAPI, model, ['xResolution', 'yResolution']);
macro.setGetArray(publicAPI, model, ['origin'], 3);
macro.getArray(publicAPI, model, ['point1', 'point2', 'normal', 'center'], 3);

macro.algo(publicAPI, model, 0, 1);
vtkPlaneSource(publicAPI, model);

publicAPI.setPoint1(model.point1);
publicAPI.setPoint2(model.point2);
}

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

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

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

export default { newInstance, extend };