@kitware/vtk.js
Version:
Visualization Toolkit for the Web
324 lines (253 loc) • 12.1 kB
JavaScript
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 };