@kitware/vtk.js
Version:
Visualization Toolkit for the Web
412 lines (319 loc) • 14.4 kB
JavaScript
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import macro from '../../macros.js';
import vtkPolyData from '../../Common/DataModel/PolyData.js';
import vtkMatrixBuilder from '../../Common/Core/MatrixBuilder.js';
import vtkDataArray from '../../Common/Core/DataArray.js';
// vtkConcentricCylinderSource methods
// ----------------------------------------------------------------------------
function vtkConcentricCylinderSource(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkConcentricCylinderSource'); // Internal private function
function validateCellFields() {
while (model.cellFields.length < model.radius.length) {
model.cellFields.push(model.cellFields.length);
}
}
publicAPI.clearRadius = function () {
model.radius = [];
model.cellFields = [];
publicAPI.modified();
};
publicAPI.addRadius = function (radius, cellField) {
model.radius.push(radius);
if (cellField !== undefined) {
model.cellFields.push(cellField);
}
validateCellFields();
publicAPI.modified();
};
publicAPI.getNumberOfRadius = function () {
return model.radius.length;
};
publicAPI.getRadius = function () {
var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
return model.radius[index];
};
publicAPI.setRadius = function (index, radius) {
model.radius[index] = radius;
publicAPI.modified();
};
publicAPI.setCellField = function (index, field) {
model.cellFields[index] = field;
publicAPI.modified();
};
publicAPI.removeMask = function () {
model.mask = null;
publicAPI.modified();
};
publicAPI.setMaskLayer = function (index, hidden) {
var changeDetected = false;
if (!model.mask && hidden) {
changeDetected = true;
model.mask = [];
}
if (model.mask) {
if (!model.mask[index] !== !hidden) {
changeDetected = true;
}
model.mask[index] = hidden;
}
if (changeDetected) {
publicAPI.modified();
}
};
publicAPI.getMaskLayer = function (index) {
return index === undefined ? model.mask : model.mask[index];
};
function requestData(inData, outData) {
var _vtkMatrixBuilder$bui;
if (model.deleted || !model.radius.length) {
return;
} // Make sure we have consistency
validateCellFields();
var dataset = outData[0];
var numLayers = model.radius.length;
var zRef = model.height / 2.0; // Compute cell count
var cellArraySize = 0;
var numCells = 0;
var startTheta = model.startTheta < model.endTheta ? model.startTheta : model.endTheta;
startTheta *= Math.PI / 180.0;
var endTheta = model.endTheta > model.startTheta ? model.endTheta : model.startTheta;
endTheta *= Math.PI / 180.0;
var thetaResolution = model.resolution;
var partialDisk = false;
if (endTheta >= startTheta + 2 * Math.PI) {
// complete, closed cylinder
endTheta = startTheta + 2 * Math.PI;
} else {
// We add an extra point at endTheta, since the cylinder isn't closed.
// We cap the sides of the partial cylinder, so set the partialDisk flag.
++thetaResolution;
partialDisk = true;
}
var deltaTheta = (endTheta - startTheta) / model.resolution;
var numberOfPoints = thetaResolution * numLayers * 2 + 2; // 5 entries per poly, 4 polys (top, bottom, in, out) per resolution
if (!model.skipInnerFaces && !model.mask) {
// We keep everything
cellArraySize = 2 * (thetaResolution + 1) + 5 * thetaResolution + (numLayers - 1) * thetaResolution * 20 + (partialDisk ? 10 * numLayers : 0);
numCells = 2 + thetaResolution + (numLayers - 1) * 4 * thetaResolution + (partialDisk ? 2 * numLayers : 0);
} else if (!model.skipInnerFaces && model.mask) {
// We skip some cylinders
// Handle core
if (!model.mask[0]) {
cellArraySize += 2 * (thetaResolution + 1) + 5 * thetaResolution + (partialDisk ? 10 : 0);
numCells += 2 + thetaResolution + (partialDisk ? 2 : 0);
} // Handle inside cylinders
for (var layer = 1; layer < numLayers; layer++) {
if (!model.mask[layer]) {
// Add inside cylinder count
cellArraySize += thetaResolution * 20 + (partialDisk ? 10 : 0);
numCells += 4 * thetaResolution + (partialDisk ? 2 : 0);
}
}
} else {
// We skip cylinders and internal faces
if (!model.skipInnerFaces || !model.mask || !model.mask[0]) {
// core handling
cellArraySize += 2 * (thetaResolution + 1) + (partialDisk ? 10 : 0);
numCells += 2 + (partialDisk ? 2 : 0);
if (model.radius.length === 1 || !model.skipInnerFaces || model.mask && model.mask[1]) {
// add side faces
cellArraySize += 5 * thetaResolution;
numCells += thetaResolution;
}
} // Handle inside cylinders
for (var _layer = 1; _layer < numLayers; _layer++) {
if (!model.skipInnerFaces || !model.mask || !model.mask[_layer]) {
var lastLayer = numLayers - 1 === _layer; // Add inside cylinder
cellArraySize += thetaResolution * 10 + (partialDisk ? 10 : 0);
numCells += thetaResolution * 2 + (partialDisk ? 2 : 0); // top + bottom + side caps
// Do we add innerFaces
if (!model.skipInnerFaces || model.mask && model.mask[_layer - 1]) {
cellArraySize += thetaResolution * 5;
numCells += thetaResolution;
} // Do we add outerFaces
if (lastLayer || !model.skipInnerFaces || model.mask && model.mask[_layer + 1]) {
cellArraySize += thetaResolution * 5;
numCells += thetaResolution;
}
}
}
} // Points
var pointIdx = 0;
var points = macro.newTypedArray(model.pointType, numberOfPoints * 3); // Cells
var cellLocation = 0;
var polys = new Uint32Array(cellArraySize); // CellFields
var fieldLocation = 0;
var field = new Float32Array(numCells); // Create points
// First two are centered, top and bottom. Used only if partialDisk is true.
points[pointIdx * 3 + 0] = 0;
points[pointIdx * 3 + 1] = 0;
points[pointIdx * 3 + 2] = zRef;
pointIdx++;
points[pointIdx * 3 + 0] = 0;
points[pointIdx * 3 + 1] = 0;
points[pointIdx * 3 + 2] = -zRef;
pointIdx++;
for (var _layer2 = 0; _layer2 < numLayers; _layer2++) {
var radius = model.radius[_layer2]; // Create top
for (var i = 0; i < thetaResolution; i++) {
var theta = startTheta + i * deltaTheta;
points[pointIdx * 3 + 0] = radius * Math.cos(theta);
points[pointIdx * 3 + 1] = radius * Math.sin(theta);
points[pointIdx * 3 + 2] = zRef;
pointIdx++;
} // Create bottom
for (var _i = 0; _i < thetaResolution; _i++) {
var _theta = startTheta + _i * deltaTheta;
points[pointIdx * 3 + 0] = radius * Math.cos(_theta);
points[pointIdx * 3 + 1] = radius * Math.sin(_theta);
points[pointIdx * 3 + 2] = -zRef;
pointIdx++;
}
} // Create cells for the core
var currentField = model.cellFields[0]; // Core: filtering
if (!model.mask || !model.mask[0]) {
// Core: Top disk
field[fieldLocation++] = currentField; // partial adds the center point and the last point.
polys[cellLocation++] = thetaResolution + (partialDisk ? 1 : 0);
if (partialDisk) polys[cellLocation++] = 0;
for (var _i2 = 0; _i2 < thetaResolution; _i2++) {
polys[cellLocation++] = _i2 + 2;
} // Core: Bottom disk
field[fieldLocation++] = currentField;
polys[cellLocation++] = thetaResolution + (partialDisk ? 1 : 0);
if (partialDisk) polys[cellLocation++] = 1;
for (var _i3 = 0; _i3 < thetaResolution; _i3++) {
polys[cellLocation++] = 2 * thetaResolution - _i3 - 1 + 2;
} // Core: sides
if (!model.skipInnerFaces || model.mask && model.mask[1] || numLayers === 1) {
for (var _i4 = 0; _i4 < model.resolution; _i4++) {
polys[cellLocation++] = 4;
polys[cellLocation++] = (_i4 + 1) % thetaResolution + 2;
polys[cellLocation++] = _i4 + 2;
polys[cellLocation++] = _i4 + thetaResolution + 2;
polys[cellLocation++] = (_i4 + 1) % thetaResolution + thetaResolution + 2;
field[fieldLocation++] = currentField;
}
}
if (partialDisk) {
polys[cellLocation++] = 4;
polys[cellLocation++] = 2;
polys[cellLocation++] = 0;
polys[cellLocation++] = 1;
polys[cellLocation++] = thetaResolution + 2;
field[fieldLocation++] = currentField;
polys[cellLocation++] = 4;
polys[cellLocation++] = 0;
polys[cellLocation++] = thetaResolution + 1;
polys[cellLocation++] = 2 * thetaResolution + 1;
polys[cellLocation++] = 1;
field[fieldLocation++] = currentField;
}
} // Create cells for the layers
for (var _layer3 = 1; _layer3 < numLayers; _layer3++) {
// Skip layer if masked
if (model.mask && model.mask[_layer3]) {
/* eslint-disable no-continue */
continue;
/* eslint-enable no-continue */
} // two for center points, then skip previous layer's points
var offset = thetaResolution * 2 * (_layer3 - 1) + 2;
var a = offset + 2 * thetaResolution; // next layer offset
var _lastLayer = numLayers - 1 === _layer3;
currentField = model.cellFields[_layer3]; // Create top
for (var _i5 = 0; _i5 < model.resolution; _i5++) {
polys[cellLocation++] = 4;
polys[cellLocation++] = _i5 + offset;
polys[cellLocation++] = (_i5 + 1) % thetaResolution + offset;
polys[cellLocation++] = (_i5 + 1) % thetaResolution + a;
polys[cellLocation++] = _i5 + a;
field[fieldLocation++] = currentField;
} // Create bottom
for (var _i6 = 0; _i6 < model.resolution; _i6++) {
polys[cellLocation++] = 4;
polys[cellLocation++] = (_i6 + 1) % thetaResolution + offset + thetaResolution;
polys[cellLocation++] = _i6 + offset + thetaResolution;
polys[cellLocation++] = _i6 + a + thetaResolution;
polys[cellLocation++] = (_i6 + 1) % thetaResolution + a + thetaResolution;
field[fieldLocation++] = currentField;
} // Create inner
if (!model.skipInnerFaces || model.mask && model.mask[_layer3 - 1]) {
for (var _i7 = 0; _i7 < model.resolution; _i7++) {
polys[cellLocation++] = 4;
polys[cellLocation++] = _i7 + offset;
polys[cellLocation++] = (_i7 + 1) % thetaResolution + offset;
polys[cellLocation++] = (_i7 + 1) % thetaResolution + thetaResolution + offset;
polys[cellLocation++] = _i7 + thetaResolution + offset;
field[fieldLocation++] = currentField;
}
} // Create outer
if (!model.skipInnerFaces || _lastLayer || model.mask && (model.mask[_layer3 + 1] || _lastLayer)) {
for (var _i8 = 0; _i8 < model.resolution; _i8++) {
polys[cellLocation++] = 4;
polys[cellLocation++] = (_i8 + 1) % thetaResolution + a;
polys[cellLocation++] = _i8 + a;
polys[cellLocation++] = _i8 + thetaResolution + a;
polys[cellLocation++] = (_i8 + 1) % thetaResolution + thetaResolution + a;
field[fieldLocation++] = currentField;
}
} // create caps
if (partialDisk) {
polys[cellLocation++] = 4;
polys[cellLocation++] = a; // from first outer
polys[cellLocation++] = offset; // first inner
polys[cellLocation++] = thetaResolution + offset; // first inner
polys[cellLocation++] = thetaResolution + a; // first outer
field[fieldLocation++] = currentField;
polys[cellLocation++] = 4;
polys[cellLocation++] = model.resolution + a; // last outer
polys[cellLocation++] = model.resolution + offset; // last inner
polys[cellLocation++] = model.resolution + thetaResolution + offset; // last inner
polys[cellLocation++] = model.resolution + thetaResolution + a; // last outer
field[fieldLocation++] = currentField;
}
} // Apply transformation to the point coordinates
(_vtkMatrixBuilder$bui = vtkMatrixBuilder.buildFromRadian()).translate.apply(_vtkMatrixBuilder$bui, _toConsumableArray(model.center)).rotateFromDirections([0, 0, 1], model.direction).apply(points);
dataset = vtkPolyData.newInstance();
dataset.getPoints().setData(points, 3);
dataset.getPolys().setData(polys, 1);
dataset.getCellData().setScalars(vtkDataArray.newInstance({
name: 'layer',
values: field
})); // Update output
outData[0] = dataset;
} // Expose methods
publicAPI.requestData = requestData;
} // ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
var DEFAULT_VALUES = {
height: 1.0,
radius: [0.5],
cellFields: [1],
resolution: 6,
startTheta: 0.0,
endTheta: 360.0,
center: [0, 0, 0],
direction: [0.0, 0.0, 1.0],
skipInnerFaces: true,
mask: null,
// If present, array to know if a layer should be skipped(=true)
pointType: 'Float64Array'
}; // ----------------------------------------------------------------------------
function extend(publicAPI, model) {
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues); // Build VTK API
macro.obj(publicAPI, model);
macro.setGet(publicAPI, model, ['height', 'resolution', 'startTheta', 'endTheta', 'skipInnerFaces']);
macro.setGetArray(publicAPI, model, ['center', 'direction'], 3);
macro.getArray(publicAPI, model, ['cellFields']);
macro.algo(publicAPI, model, 0, 1);
vtkConcentricCylinderSource(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = macro.newInstance(extend, 'vtkConcentricCylinderSource'); // ----------------------------------------------------------------------------
var vtkConcentricCylinderSource$1 = {
newInstance: newInstance,
extend: extend
};
export { vtkConcentricCylinderSource$1 as default, extend, newInstance };