UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

324 lines (253 loc) 12.1 kB
import _defineProperty from '@babel/runtime/helpers/defineProperty'; import macro from '../../macros.js'; import { FormatTypes, TextureCoordinatesName } from './PLYWriter/Constants.js'; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } var vtkErrorMacro = macro.vtkErrorMacro, vtkWarningMacro = macro.vtkWarningMacro; // ---------------------------------------------------------------------------- // vtkPLYWriter methods // ---------------------------------------------------------------------------- var _writeHeader = function writeHeader(polyData, fileFormat, fileType, headerComments, textureFileName, textureCoordinatesName, vertexCount, faceListLength, withNormals, withUVs, withColors, withIndices) { var isBinary = fileFormat !== FormatTypes.ASCII; var format; if (isBinary) { format = fileType ? 'binary_little_endian' : 'binary_big_endian'; } else format = 'ascii'; headerComments.unshift('VTK.js generated PLY File'); if (textureFileName) { headerComments.push("TextureFile ".concat(textureFileName)); } var commentElements = headerComments.map(function (comment) { return "comment ".concat(comment); }).join('\n'); var header = ['ply', "format ".concat(format, " 1.0"), "".concat(commentElements), "element vertex ".concat(vertexCount), 'property float x', 'property float y', 'property float z']; // normals if (withNormals) { header.push('property float nx', 'property float ny', 'property float nz'); } // uvs if (withUVs) { header.push("property float ".concat(textureCoordinatesName[0]), "property float ".concat(textureCoordinatesName[1])); } // colors if (withColors) { header.push('property uchar red', 'property uchar green', 'property uchar blue'); } // faces if (withIndices) { header.push("element face ".concat(faceListLength), 'property list uchar int vertex_indices'); } header.push('end_header\n'); return header.join('\n'); }; var binaryWriter = function binaryWriter() { var output; var vOffset; var fOffset; var indexByteCount = 4; var ft; return { init: function init(polyData) {}, writeHeader: function writeHeader(polyData, fileFormat, fileType, headerComments, textureFileName, textureCoordinatesName, numPts, numPolys, withNormals, withUVs, withColors, withIndices) { var vertexCount = polyData.getPoints().getNumberOfPoints(); ft = fileType; // 1 byte shape descriptor // 3 vertex indices at ${indexByteCount} bytes var faceListLength = withIndices ? numPolys * (indexByteCount * 3 + 1) : 0; // 3 position values at 4 bytes // 3 normal values at 4 bytes // 3 color channels with 1 byte // 2 uv values at 4 bytes var vertexListLength = vertexCount * (4 * 3 + (withNormals ? 4 * 3 : 0) + (withUVs ? 4 * 2 : 0) + (withColors ? 3 : 0)); var header = _writeHeader(polyData, fileFormat, fileType, headerComments, textureFileName, textureCoordinatesName, numPts, numPolys, withNormals, withUVs, withColors, withIndices); var headerBin = new TextEncoder().encode(header); output = new DataView(new ArrayBuffer(headerBin.length + vertexListLength + faceListLength)); new Uint8Array(output.buffer).set(headerBin, 0); vOffset = headerBin.length; fOffset = vOffset + vertexListLength; }, writeVertice: function writeVertice(x, y, z, nx, ny, nz, u, v, r, g, b) { // xyz output.setFloat32(vOffset, x, ft); vOffset += 4; output.setFloat32(vOffset, y, ft); vOffset += 4; output.setFloat32(vOffset, z, ft); vOffset += 4; // nxnynz if (nx !== null && ny !== null && nz !== null) { output.setFloat32(vOffset, nx, ft); vOffset += 4; output.setFloat32(vOffset, ny, ft); vOffset += 4; output.setFloat32(vOffset, nz, ft); vOffset += 4; } // uv if (u !== null && v !== null) { output.setFloat32(vOffset, u, ft); vOffset += 4; output.setFloat32(vOffset, v, ft); vOffset += 4; } // rgb if (r !== null && g !== null && b !== null) { output.setUint8(vOffset, r); vOffset += 1; output.setUint8(vOffset, g); vOffset += 1; output.setUint8(vOffset, b); vOffset += 1; } }, writeFace: function writeFace(n, x, y, z) { output.setUint8(fOffset, n); fOffset += 1; output.setUint32(fOffset, x, ft); fOffset += indexByteCount; output.setUint32(fOffset, y, ft); fOffset += indexByteCount; output.setUint32(fOffset, z, ft); fOffset += indexByteCount; }, writeFooter: function writeFooter(polyData) {}, getOutputData: function getOutputData() { return output; } }; }; var asciiWriter = function asciiWriter() { var fileContent = ''; return { init: function init(polyData) {}, writeHeader: function writeHeader(polyData, fileFormat, fileType, headerComments, textureFileName, textureCoordinatesName, numPts, numPolys, withNormals, withUVs, withColors, withIndices) { fileContent += _writeHeader(polyData, fileFormat, fileType, headerComments, textureFileName, textureCoordinatesName, numPts, numPolys, withNormals, withUVs, withColors, withIndices); }, writeVertice: function writeVertice(x, y, z, nx, ny, nz, u, v, r, g, b) { fileContent += "".concat(x, " ").concat(y, " ").concat(z); if (nx !== null && ny !== null && nz !== null) { fileContent += " ".concat(nx, " ").concat(ny, " ").concat(nz); } if (u !== null && v !== null) { fileContent += " ".concat(u, " ").concat(v); } if (r !== null && g !== null && b !== null) { fileContent += " ".concat(r, " ").concat(g, " ").concat(b); } fileContent += '\n'; }, writeFace: function writeFace(n, x, y, z) { fileContent += "".concat(n, " ").concat(x, " ").concat(y, " ").concat(z, "\n"); }, writeFooter: function writeFooter(polyData) {}, getOutputData: function getOutputData() { return fileContent; } }; }; function writePLY(polyData, format, dataByteOrder, headerComments, textureFileName, textureCoordinatesName, transform, withNormals, withUVs, withColors, withIndices) { var inPts = polyData.getPoints(); var polys = polyData.getPolys(); if (inPts === null || polys === null) { vtkErrorMacro('No data to write!'); } var writer = null; if (format === FormatTypes.BINARY) { writer = binaryWriter(); } else if (format === FormatTypes.ASCII) { writer = asciiWriter(); } else { vtkErrorMacro('Invalid type format'); } var tCoordsName = textureCoordinatesName; if (typeof textureCoordinatesName === 'undefined') { vtkWarningMacro('Invalid TextureCoordinatesName value, fallback to default uv values'); tCoordsName = TextureCoordinatesName.UV; } writer.init(polyData); var numPts = inPts.getNumberOfPoints(); var numPolys = polys.getNumberOfCells(); // textureCoords / uvs var textureCoords = polyData.getPointData().getTCoords(); // eslint-disable-next-line no-param-reassign withUVs = !(textureCoords === null); // scalars / colors var scalars = polyData.getPointData().getScalars(); // eslint-disable-next-line no-param-reassign withColors = !(scalars === null); var fileType = dataByteOrder ? 0 : 1; writer.writeHeader(polyData, format, fileType, headerComments, textureFileName, tCoordsName, numPts, numPolys, withNormals, withUVs, withColors, withIndices); var normals = polyData.getPointData().getNormals(); // points / vertices for (var i = 0; i < numPts; i++) { // eslint-disable-next-line prefer-const var p = inPts.getPoint(i); // TODO: apply transform matrix // divide by 1 to remove trailing zeros var x = p[0].toPrecision(6) / 1; var y = p[1].toPrecision(6) / 1; var z = p[2].toPrecision(6) / 1; // normals var nx = null; var ny = null; var nz = null; // uvs var u = null; var v = null; // colors var r = null; var g = null; var b = null; if (textureCoords) { u = textureCoords.getData()[i * 2]; v = textureCoords.getData()[i * 2 + 1]; } if (scalars) { r = scalars.getData()[i * 3]; g = scalars.getData()[i * 3 + 1]; b = scalars.getData()[i * 3 + 2]; } if (normals) { nx = normals.getData()[i * 2]; ny = normals.getData()[i * 2 + 1]; nz = normals.getData()[i * 2 + 2]; } writer.writeVertice(x, y, z, nx, ny, nz, u, v, r, g, b); } // polys / indices var pd = polys.getData(); for (var _i = 0, l = pd.length; _i < l; _i += 4) { writer.writeFace(pd[_i + 0], pd[_i + 1], pd[_i + 2], pd[_i + 3]); } writer.writeFooter(polyData); return writer.getOutputData(); } // ---------------------------------------------------------------------------- // Static API // ---------------------------------------------------------------------------- var STATIC = { writePLY: writePLY }; // ---------------------------------------------------------------------------- // vtkPLYWriter methods // ---------------------------------------------------------------------------- function vtkPLYWriter(publicAPI, model) { // Set our className model.classHierarchy.push('vtkPLYWriter'); publicAPI.requestData = function (inData, outData) { var input = inData[0]; if (!input || input.getClassName() !== 'vtkPolyData') { vtkErrorMacro('Invalid or missing input'); return; } outData[0] = writePLY(input, model.format, model.dataByteOrder, model.headerComments, model.textureFileName, model.textureCoordinatesName, model.transform, model.withNormals, model.withUVs, model.withColors, model.withIndices); }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- var DEFAULT_VALUES = { format: FormatTypes.ASCII, dataByteOrder: 0, headerComments: [], textureFileName: null, textureCoordinatesName: TextureCoordinatesName.UV, transform: null, withNormals: true, withUVs: true, withColors: true, withIndices: true }; // ---------------------------------------------------------------------------- function extend(publicAPI, model) { var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.assign(model, DEFAULT_VALUES, initialValues); // Make this a VTK object macro.obj(publicAPI, model); // Also make it an algorithm with one input and one output macro.algo(publicAPI, model, 1, 1); macro.setGet(publicAPI, model, ['format', 'dataByteOrder', // binary_little_endian 0 binary_big_endian 1 'headerComments', 'textureFileName', 'textureCoordinatesName', 'transform', 'withNormals', 'withUVs', 'withColors', 'withIndices']); // Object specific methods vtkPLYWriter(publicAPI, model); } // ---------------------------------------------------------------------------- var newInstance = macro.newInstance(extend, 'vtkPLYWriter'); // ---------------------------------------------------------------------------- var vtkPLYWriter$1 = _objectSpread({ newInstance: newInstance, extend: extend }, STATIC); export { STATIC, vtkPLYWriter$1 as default, extend, newInstance };