PolyData

Introduction

vtkPolyData is a dataset that represents a geometric structure consisting of vertices, lines, polygons, and/or strips.

Methods

buildCells

Create data structure that allows random access of cells.

buildLinks

Create upward links from points to cells that use each point. Enables
topologically complex queries.

Argument Type Required Description
initialSize Number Yes

extend

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

getCell

If you know the type of cell, you may provide it to improve performances.

Argument Type Required Description
cellId Number Yes
cellHint Yes

getCellEdgeNeighbors

Get the neighbors at an edge.

Argument Type Required Description
cellId Number Yes The Id of the cell.
point1 Vector3 Yes The first point coordinate.
point2 Vector3 Yes The second point coordinate.

getCellPoints

Get a list of point ids that define a cell.

Argument Type Required Description
cellId Number Yes The Id of the cell.

getCells

Get the cell array defining cells.

getLines

Get the cell array defining lines.

getLinks

getNumberOfCells

Determine the number of cells composing the polydata.

getNumberOfLines

Determine the number of lines composing the polydata.

getNumberOfPoints

Determine the number of points composing the polydata.

getNumberOfPolys

Determine the number of polys composing the polydata.

getNumberOfStrips

Determine the number of strips composing the polydata.

getNumberOfVerts

Determine the number of vertices composing the polydata.

getPointCells

Topological inquiry to get cells using point.

Argument Type Required Description
ptId Yes

getPolys

Get the cell array defining polys.

getStrips

Get the cell array defining strips.

getVerts

Get the cell array defining vertices.
If there are no vertices, an empty array will be returned (convenience to
simplify traversal).

newInstance

Method used to create a new instance of vtkPolyData.

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

setLines

Set the cell array defining lines.

Argument Type Required Description
lines vtkCellArray Yes The cell array defining lines.

setPolys

Set the cell array defining polys.

Argument Type Required Description
polys vtkCellArray Yes The cell array defining polys.

setStrips

Set the cell array defining strips.

Argument Type Required Description
strips vtkCellArray Yes The cell array defining strips.

setVerts

Set the cell array defining vertices.

Argument Type Required Description
verts vtkCellArray Yes The cell array defining vertices.

Source

Constants.js
export const POLYDATA_FIELDS = ['verts', 'lines', 'polys', 'strips'];

export default {
POLYDATA_FIELDS,
};
index.d.ts
import { Vector3 } from '../../../types';
import vtkCellArray from '../../Core/CellArray';
import vtkPointSet, { IPointSetInitialValues } from '../PointSet';

/**
*
*/
export interface IPolyDataInitialValues extends IPointSetInitialValues {
}


export interface vtkPolyData extends vtkPointSet {

/**
* Create data structure that allows random access of cells.
*/
buildCells(): void;

/**
* Create upward links from points to cells that use each point. Enables
* topologically complex queries.
* @param {Number} initialSize
*/
buildLinks(initialSize?: number): void;

/**
* If you know the type of cell, you may provide it to improve performances.
* @param {Number} cellId
* @param cellHint
*/
getCell(cellId: number, cellHint: any): void;

/**
* Get the neighbors at an edge.
* @param {Number} cellId The Id of the cell.
* @param {Vector3} point1 The first point coordinate.
* @param {Vector3} point2 The second point coordinate.
*/
getCellEdgeNeighbors(cellId: number, point1: Vector3, point2: Vector3): void;

/**
* Get a list of point ids that define a cell.
* @param {Number} cellId The Id of the cell.
* @return an object made of the cellType and a subarray `cellPointIds` of the cell points.
*/
getCellPoints(cellId: number): object;

/**
* Get the cell array defining cells.
*/
getCells(): vtkCellArray;

/**
* Get the cell array defining lines.
*/
getLines(): vtkCellArray;

/**
*
*/
getLinks(): any;

/**
* Determine the number of cells composing the polydata.
*/
getNumberOfCells(): number;

/**
* Determine the number of lines composing the polydata.
*/
getNumberOfLines(): number;

/**
* Determine the number of points composing the polydata.
*/
getNumberOfPoints(): number;

/**
* Determine the number of polys composing the polydata.
*/
getNumberOfPolys(): number;

/**
* Determine the number of strips composing the polydata.
*/
getNumberOfStrips(): number;

/**
* Determine the number of vertices composing the polydata.
*/
getNumberOfVerts(): number;

/**
* Topological inquiry to get cells using point.
* @param ptId
*/
getPointCells(ptId: any): void;

/**
* Get the cell array defining polys.
*/
getPolys(): vtkCellArray;

/**
* Get the cell array defining strips.
*/
getStrips(): vtkCellArray;

/**
* Get the cell array defining vertices.
* If there are no vertices, an empty array will be returned (convenience to
* simplify traversal).
*/
getVerts(): vtkCellArray;

/**
* Set the cell array defining lines.
* @param {vtkCellArray} lines The cell array defining lines.
*/
setLines(lines: vtkCellArray): boolean;

/**
* Set the cell array defining polys.
* @param {vtkCellArray} polys The cell array defining polys.
*/
setPolys(polys: vtkCellArray): boolean;

/**
* Set the cell array defining strips.
* @param {vtkCellArray} strips The cell array defining strips.
*/
setStrips(strips: vtkCellArray): boolean;

/**
* Set the cell array defining vertices.
* @param {vtkCellArray} verts The cell array defining vertices.
*/
setVerts(verts: vtkCellArray): boolean;
}

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

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

/**
* vtkPolyData is a dataset that represents a geometric structure consisting of vertices, lines, polygons, and/or strips.
*/
export declare const vtkPolyData: {
newInstance: typeof newInstance,
extend: typeof extend,
};
export default vtkPolyData;
index.js
import macro from 'vtk.js/Sources/macros';
import vtk from 'vtk.js/Sources/vtk';
import vtkCellArray from 'vtk.js/Sources/Common/Core/CellArray';
import vtkCellLinks from 'vtk.js/Sources/Common/DataModel/CellLinks';
import vtkCellTypes from 'vtk.js/Sources/Common/DataModel/CellTypes';
import vtkLine from 'vtk.js/Sources/Common/DataModel/Line';
import vtkPointSet from 'vtk.js/Sources/Common/DataModel/PointSet';
import vtkTriangle from 'vtk.js/Sources/Common/DataModel/Triangle';

import { CellType } from 'vtk.js/Sources/Common/DataModel/CellTypes/Constants';
import { POLYDATA_FIELDS } from 'vtk.js/Sources/Common/DataModel/PolyData/Constants';

const { vtkWarningMacro } = macro;

export const CELL_FACTORY = {
[CellType.VTK_LINE]: vtkLine,
[CellType.VTK_POLY_LINE]: vtkLine,
[CellType.VTK_TRIANGLE]: vtkTriangle,
};

// ----------------------------------------------------------------------------
// vtkPolyData methods
// ----------------------------------------------------------------------------

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

function camelize(str) {
return str
.replace(/(?:^\w|[A-Z]|\b\w)/g, (letter) => letter.toUpperCase())
.replace(/\s+/g, '');
}

// build empty cell arrays and set methods
POLYDATA_FIELDS.forEach((type) => {
publicAPI[`getNumberOf${camelize(type)}`] = () =>
model[type].getNumberOfCells();
if (!model[type]) {
model[type] = vtkCellArray.newInstance();
} else {
model[type] = vtk(model[type]);
}
});

publicAPI.getNumberOfCells = () =>
POLYDATA_FIELDS.reduce(
(num, cellType) => num + model[cellType].getNumberOfCells(),
0
);

const superShallowCopy = publicAPI.shallowCopy;
publicAPI.shallowCopy = (other, debug = false) => {
superShallowCopy(other, debug);
POLYDATA_FIELDS.forEach((type) => {
model[type] = vtkCellArray.newInstance();
model[type].shallowCopy(other.getReferenceByName(type));
});
};

publicAPI.buildCells = () => {
// here are the number of cells we have
const nVerts = publicAPI.getNumberOfVerts();
const nLines = publicAPI.getNumberOfLines();
const nPolys = publicAPI.getNumberOfPolys();
const nStrips = publicAPI.getNumberOfStrips();

// pre-allocate the space we need
const nCells = nVerts + nLines + nPolys + nStrips;

const types = new Uint8Array(nCells);
let pTypes = types;
const locs = new Uint32Array(nCells);
let pLocs = locs;

// record locations and type of each cell.
// verts
if (nVerts) {
let nextCellPts = 0;
model.verts.getCellSizes().forEach((numCellPts, index) => {
pLocs[index] = nextCellPts;
pTypes[index] =
numCellPts > 1 ? CellType.VTK_POLY_VERTEX : CellType.VTK_VERTEX;
nextCellPts += numCellPts + 1;
});

pLocs = pLocs.subarray(nVerts);
pTypes = pTypes.subarray(nVerts);
}

// lines
if (nLines) {
let nextCellPts = 0;
model.lines.getCellSizes().forEach((numCellPts, index) => {
pLocs[index] = nextCellPts;
pTypes[index] =
numCellPts > 2 ? CellType.VTK_POLY_LINE : CellType.VTK_LINE;
if (numCellPts === 1) {
vtkWarningMacro(
'Building VTK_LINE ',
index,
' with only one point, but VTK_LINE needs at least two points. Check the input.'
);
}
nextCellPts += numCellPts + 1;
});

pLocs = pLocs.subarray(nLines);
pTypes = pTypes.subarray(nLines);
}

// polys
if (nPolys) {
let nextCellPts = 0;
model.polys.getCellSizes().forEach((numCellPts, index) => {
pLocs[index] = nextCellPts;
switch (numCellPts) {
case 3:
pTypes[index] = CellType.VTK_TRIANGLE;
break;
case 4:
pTypes[index] = CellType.VTK_QUAD;
break;
default:
pTypes[index] = CellType.VTK_POLYGON;
break;
}
if (numCellPts < 3) {
vtkWarningMacro(
'Building VTK_TRIANGLE ',
index,
' with less than three points, but VTK_TRIANGLE needs at least three points. Check the input.'
);
}
nextCellPts += numCellPts + 1;
});

pLocs += pLocs.subarray(nPolys);
pTypes += pTypes.subarray(nPolys);
}

// strips
if (nStrips) {
let nextCellPts = 0;
pTypes.fill(CellType.VTK_TRIANGLE_STRIP, 0, nStrips);

model.strips.getCellSizes().forEach((numCellPts, index) => {
pLocs[index] = nextCellPts;
nextCellPts += numCellPts + 1;
});
}

// set up the cell types data structure
model.cells = vtkCellTypes.newInstance();
model.cells.setCellTypes(nCells, types, locs);
};

/**
* Create upward links from points to cells that use each point. Enables
* topologically complex queries.
*/
publicAPI.buildLinks = (initialSize = 0) => {
if (model.cells === undefined) {
publicAPI.buildCells();
}

model.links = vtkCellLinks.newInstance();
if (initialSize > 0) {
model.links.allocate(initialSize);
} else {
model.links.allocate(publicAPI.getPoints().getNumberOfPoints());
}

model.links.buildLinks(publicAPI);
};

// Returns an object made of the cellType and a subarray `cellPointIds` of
// the cell points.
publicAPI.getCellPoints = (cellId) => {
const cellType = model.cells.getCellType(cellId);
let cells = null;
switch (cellType) {
case CellType.VTK_VERTEX:
case CellType.VTK_POLY_VERTEX:
cells = model.verts;
break;

case CellType.VTK_LINE:
case CellType.VTK_POLY_LINE:
cells = model.lines;
break;

case CellType.VTK_TRIANGLE:
case CellType.VTK_QUAD:
case CellType.VTK_POLYGON:
cells = model.polys;
break;

case CellType.VTK_TRIANGLE_STRIP:
cells = model.strips;
break;

default:
cells = null;
return { type: 0, cellPointIds: null };
}
const loc = model.cells.getCellLocation(cellId);
const cellPointIds = cells.getCell(loc);
return { cellType, cellPointIds };
};

publicAPI.getPointCells = (ptId) => model.links.getCells(ptId);

publicAPI.getCellEdgeNeighbors = (cellId, point1, point2) => {
const link1 = model.links.getLink(point1);
const link2 = model.links.getLink(point2);

return link1.cells.filter(
(cell) => cell !== cellId && link2.cells.indexOf(cell) !== -1
);
};

/**
* If you know the type of cell, you may provide it to improve performances.
*/
publicAPI.getCell = (cellId, cellHint = null) => {
const cellInfo = publicAPI.getCellPoints(cellId);
const cell = cellHint || CELL_FACTORY[cellInfo.cellType].newInstance();
cell.initialize(publicAPI.getPoints(), cellInfo.cellPointIds);
return cell;
};
}

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

const DEFAULT_VALUES = {
// verts: null,
// lines: null,
// polys: null,
// strips: null,
// cells: null,
// links: null,
};

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

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

// Inheritance
vtkPointSet.extend(publicAPI, model, initialValues);
macro.get(publicAPI, model, ['cells', 'links']);
macro.setGet(publicAPI, model, ['verts', 'lines', 'polys', 'strips']);

// Object specific methods
vtkPolyData(publicAPI, model);
}

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

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

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

export default { newInstance, extend };