UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

205 lines (166 loc) 7.58 kB
import macro from '../../macros.js'; import vtkPolyData from '../../Common/DataModel/PolyData.js'; import vtkDataArray from '../../Common/Core/DataArray.js'; // vtkSphereSource methods // ---------------------------------------------------------------------------- function vtkSphereSource(publicAPI, model) { // Set our className model.classHierarchy.push('vtkSphereSource'); publicAPI.requestData = function (inData, outData) { if (model.deleted) { return; } var dataset = outData[0]; var pointDataType = dataset ? dataset.getPoints().getDataType() : model.pointType; dataset = vtkPolyData.newInstance(); // ---------------------------------------------------------------------- var numPoles = 0; // Check data, determine increments, and convert to radians var thetaResolution = model.thetaResolution; 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 startPhi = model.startPhi < model.endPhi ? model.startPhi : model.endPhi; startPhi *= Math.PI / 180.0; var endPhi = model.endPhi > model.startPhi ? model.endPhi : model.startPhi; endPhi *= Math.PI / 180.0; if (Math.abs(startTheta - endTheta) < 2.0 * Math.PI) { ++thetaResolution; } var deltaTheta = (endTheta - startTheta) / model.thetaResolution; var jStart = model.startPhi <= 0.0 ? 1 : 0; var jEnd = model.phiResolution + (model.endPhi >= 180.0 ? -1 : 0); var numPts = model.phiResolution * thetaResolution + 2; var numPolys = model.phiResolution * 2 * model.thetaResolution; // Points var pointIdx = 0; var points = macro.newTypedArray(pointDataType, numPts * 3); // Normals var normals = new Float32Array(numPts * 3); // Cells var cellLocation = 0; var polys = new Uint32Array(numPolys * 5); // Create north pole if needed if (model.startPhi <= 0.0) { points[pointIdx * 3 + 0] = model.center[0]; points[pointIdx * 3 + 1] = model.center[1]; points[pointIdx * 3 + 2] = model.center[2] + model.radius; normals[pointIdx * 3 + 0] = 0; normals[pointIdx * 3 + 1] = 0; normals[pointIdx * 3 + 2] = 1; pointIdx++; numPoles++; } // Create south pole if needed if (model.endPhi >= 180.0) { points[pointIdx * 3 + 0] = model.center[0]; points[pointIdx * 3 + 1] = model.center[1]; points[pointIdx * 3 + 2] = model.center[2] - model.radius; normals[pointIdx * 3 + 0] = 0; normals[pointIdx * 3 + 1] = 0; normals[pointIdx * 3 + 2] = -1; pointIdx++; numPoles++; } var phiResolution = model.phiResolution - numPoles; var deltaPhi = (endPhi - startPhi) / (model.phiResolution - 1); // Create intermediate points for (var i = 0; i < thetaResolution; i++) { var theta = startTheta + i * deltaTheta; for (var j = jStart; j < jEnd; j++) { var phi = startPhi + j * deltaPhi; var radius = model.radius * Math.sin(phi); normals[pointIdx * 3 + 0] = radius * Math.cos(theta); normals[pointIdx * 3 + 1] = radius * Math.sin(theta); normals[pointIdx * 3 + 2] = model.radius * Math.cos(phi); points[pointIdx * 3 + 0] = normals[pointIdx * 3 + 0] + model.center[0]; points[pointIdx * 3 + 1] = normals[pointIdx * 3 + 1] + model.center[1]; points[pointIdx * 3 + 2] = normals[pointIdx * 3 + 2] + model.center[2]; var norm = Math.sqrt(normals[pointIdx * 3 + 0] * normals[pointIdx * 3 + 0] + normals[pointIdx * 3 + 1] * normals[pointIdx * 3 + 1] + normals[pointIdx * 3 + 2] * normals[pointIdx * 3 + 2]); norm = norm === 0 ? 1 : norm; normals[pointIdx * 3 + 0] /= norm; normals[pointIdx * 3 + 1] /= norm; normals[pointIdx * 3 + 2] /= norm; pointIdx++; } } // Generate mesh connectivity var base = phiResolution * thetaResolution; if (Math.abs(startTheta - endTheta) < 2.0 * Math.PI) { --thetaResolution; } // around north pole if (model.startPhi <= 0.0) { for (var _i = 0; _i < thetaResolution; _i++) { polys[cellLocation++] = 3; polys[cellLocation++] = phiResolution * _i + numPoles; polys[cellLocation++] = phiResolution * (_i + 1) % base + numPoles; polys[cellLocation++] = 0; } } // around south pole if (model.endPhi >= 180.0) { var numOffset = phiResolution - 1 + numPoles; for (var _i2 = 0; _i2 < thetaResolution; _i2++) { polys[cellLocation++] = 3; polys[cellLocation++] = phiResolution * _i2 + numOffset; polys[cellLocation++] = numPoles - 1; polys[cellLocation++] = phiResolution * (_i2 + 1) % base + numOffset; } } // bands in-between poles for (var _i3 = 0; _i3 < thetaResolution; _i3++) { for (var _j = 0; _j < phiResolution - 1; _j++) { var a = phiResolution * _i3 + _j + numPoles; var b = a + 1; var c = (phiResolution * (_i3 + 1) + _j) % base + numPoles + 1; if (!model.latLongTessellation) { polys[cellLocation++] = 3; polys[cellLocation++] = a; polys[cellLocation++] = b; polys[cellLocation++] = c; polys[cellLocation++] = 3; polys[cellLocation++] = a; polys[cellLocation++] = c; polys[cellLocation++] = c - 1; } else { polys[cellLocation++] = 4; polys[cellLocation++] = a; polys[cellLocation++] = b; polys[cellLocation++] = c; polys[cellLocation++] = c - 1; } } } // Squeeze points = points.subarray(0, pointIdx * 3); dataset.getPoints().setData(points, 3); normals = normals.subarray(0, pointIdx * 3); var normalArray = vtkDataArray.newInstance({ name: 'Normals', values: normals, numberOfComponents: 3 }); dataset.getPointData().setNormals(normalArray); polys = polys.subarray(0, cellLocation); dataset.getPolys().setData(polys, 1); // Update output outData[0] = dataset; }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- var DEFAULT_VALUES = { radius: 0.5, latLongTessellation: false, thetaResolution: 8, startTheta: 0.0, endTheta: 360.0, phiResolution: 8, startPhi: 0.0, endPhi: 180.0, center: [0, 0, 0], 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, ['radius', 'latLongTessellation', 'thetaResolution', 'startTheta', 'endTheta', 'phiResolution', 'startPhi', 'endPhi']); macro.setGetArray(publicAPI, model, ['center'], 3); macro.algo(publicAPI, model, 0, 1); vtkSphereSource(publicAPI, model); } // ---------------------------------------------------------------------------- var newInstance = macro.newInstance(extend, 'vtkSphereSource'); // ---------------------------------------------------------------------------- var vtkSphereSource$1 = { newInstance: newInstance, extend: extend }; export { vtkSphereSource$1 as default, extend, newInstance };