import { create } from 'xmlbuilder2'; import { zlibSync } from 'fflate';
import macro from 'vtk.js/Sources/macros'; import { fromArrayBuffer } from 'vtk.js/Sources/Common/Core/Base64'; import { FormatTypes, TYPED_ARRAY, } from 'vtk.js/Sources/IO/XML/XMLWriter/Constants';
function compressBlock(uncompressed) { return zlibSync(uncompressed); }
function processDataArray( dataArray, format, blockSize, compressor = 'vtkZLibDataCompressor' ) { if (format === FormatTypes.ASCII) { return dataArray.getData().join(' '); } if (format === FormatTypes.BINARY) { if (compressor === 'vtkZLibDataCompressor') {
const componentUint8Size = dataArray.getElementComponentSize(); const uncompressedUint8Size = dataArray.getNumberOfValues() * componentUint8Size; const blockUint8Size = blockSize; const nbFullBlocks = Math.trunc(uncompressedUint8Size / blockUint8Size); const lastBlockUint8Size = uncompressedUint8Size % blockUint8Size; const nbBlocks = nbFullBlocks + (lastBlockUint8Size ? 1 : 0); const header = new Uint32Array(3 + nbBlocks); header[0] = nbBlocks; header[1] = blockUint8Size; header[2] = lastBlockUint8Size;
let totalUint8Length = 0; const blocks = []; let dataOffset = 0; const lastBlockId = nbBlocks - 1; for (let blockId = 0; blockId < nbBlocks; ++blockId) { const currentBlockUint8Size = lastBlockUint8Size === 0 || blockId < lastBlockId ? blockUint8Size : header[2]; const uncompressedBlock = new Uint8Array( dataArray.getData().buffer, dataOffset, currentBlockUint8Size ); dataOffset += blockUint8Size; const compressedUint8Block = compressBlock(uncompressedBlock); blocks.push(compressedUint8Block); header[3 + blockId] = compressedUint8Block.length; totalUint8Length += compressedUint8Block.length; } const uint8 = new Uint8Array(totalUint8Length); let uint8Offset = 0; const headerUint8 = new Uint8Array(header.buffer); for (let blockId = 0; blockId < nbBlocks; ++blockId) { uint8.set(blocks[blockId], uint8Offset); uint8Offset += header[3 + blockId]; } return ( fromArrayBuffer(headerUint8.buffer) + fromArrayBuffer(uint8.buffer) ); } throw new Error('Only vtkZLibDataCompressor is supported'); } if (format === FormatTypes.APPENDED) { throw new Error('Appended format is not supported'); } throw new Error('Format is not supported'); }
function vtkXMLWriter(publicAPI, model) { model.classHierarchy.push('vtkXMLWriter');
publicAPI.create = (dataObject) => create() .ele('VTKFile') .att('type', model.dataType) .att('version', '0.1') .att('byte_order', 'LittleEndian') .att('header_type', 'UInt32') .att( 'compressor', model.format === FormatTypes.ASCII ? '' : 'vtkZLibDataCompressor' );
publicAPI.write = (object) => publicAPI.create(object).end({ pretty: true });
publicAPI.processDataSetAttributes = ( parentElement, name, datasetAttributes ) => { const activeAttributes = {}; const attrTypes = [ 'Scalars', 'Vectors', 'Normals', 'TCoords', 'Tensors', 'GlobalIds', 'PedigreeIds', ]; attrTypes.forEach((attrType) => { const activeAttribute = datasetAttributes.getActiveAttribute(attrType); if (activeAttribute) { activeAttributes[attrType] = activeAttribute.getName(); } });
const datasetAttributesEle = parentElement.ele(name, activeAttributes);
for (let i = 0; i < datasetAttributes.getNumberOfArrays(); ++i) { publicAPI.processDataArray( datasetAttributesEle, datasetAttributes.getArrayByIndex(i) ); } return datasetAttributesEle; };
publicAPI.processDataArray = (parentEle, scalars) => parentEle .ele('DataArray', { type: TYPED_ARRAY[scalars.getDataType()], Name: scalars.getName(), format: publicAPI.getFormat(), RangeMin: scalars.getRange()[0], RangeMax: scalars.getRange()[1], NumberOfComponents: scalars.getNumberOfComponents(), }) .txt( processDataArray( scalars, publicAPI.getFormat(), publicAPI.getBlockSize() ) );
publicAPI.requestData = (inData, outData) => { model.file = publicAPI.write(inData); }; }
const DEFAULT_VALUES = { blockSize: 1024, format: FormatTypes.BINARY, };
export function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model); macro.setGet(publicAPI, model, ['blockSize', 'format']); macro.get(publicAPI, model, ['file']); macro.algo(publicAPI, model, 1, 0);
vtkXMLWriter(publicAPI, model); }
export default { extend, compressBlock, processDataArray, FormatTypes };
|