UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

412 lines (319 loc) 14.4 kB
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 };