Skip to content

Commit

Permalink
Merge pull request #446 from floryst/vtp_appended_format
Browse files Browse the repository at this point in the history
Add vti/vtp appended data format support
  • Loading branch information
jourdain authored Dec 7, 2017
2 parents a6019d0 + cb3ce32 commit 66ed348
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 30 deletions.
15 changes: 10 additions & 5 deletions Examples/Applications/GeometryViewer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import vtkURLExtract from 'vtk.js/Sources/Common/Core/URLExtract';
import vtkXMLPolyDataReader from 'vtk.js/Sources/IO/XML/XMLPolyDataReader';
import { ColorMode, ScalarMode } from 'vtk.js/Sources/Rendering/Core/Mapper/Constants';

import BinaryHelper from 'vtk.js/Sources/IO/Core/BinaryHelper';

import style from './GeometryViewer.mcss';
import icon from '../../../Documentation/content/icon/favicon-96x96.png';

Expand Down Expand Up @@ -111,7 +113,7 @@ function createViewer(container) {

// ----------------------------------------------------------------------------

function createPipeline(fileName, fileContentAsText) {
function createPipeline(fileName, parsedFileContents) {
// Create UI
const presetSelector = document.createElement('select');
presetSelector.setAttribute('class', selectorClass);
Expand Down Expand Up @@ -156,7 +158,7 @@ function createPipeline(fileName, fileContentAsText) {

// VTK pipeline
const vtpReader = vtkXMLPolyDataReader.newInstance();
vtpReader.parse(fileContentAsText);
vtpReader.parse(parsedFileContents.text, parsedFileContents.binaryBuffer);

const lookupTable = vtkColorTransferFunction.newInstance();
const source = vtpReader.getOutputData(0);
Expand Down Expand Up @@ -302,9 +304,12 @@ function createPipeline(fileName, fileContentAsText) {
function loadFile(file) {
const reader = new FileReader();
reader.onload = function onLoad(e) {
createPipeline(file.name, reader.result);
const prefixRegex = /^\s*<AppendedData\s+encoding="raw">\s*_/m;
const suffixRegex = /\n\s*<\/AppendedData>/m;
const result = BinaryHelper.extractBinary(reader.result, prefixRegex, suffixRegex);
createPipeline(file.name, result);
};
reader.readAsText(file);
reader.readAsArrayBuffer(file);
}

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -333,7 +338,7 @@ export function load(container, options) {
HttpDataAccessHelper.fetchText({}, options.fileURL, { progressCallback }).then((txt) => {
container.removeChild(progressContainer);
createViewer(container);
createPipeline(defaultName, txt);
createPipeline(defaultName, { text: txt });
updateCamera(renderer.getActiveCamera());
});
}
Expand Down
15 changes: 10 additions & 5 deletions Examples/Applications/VolumeViewer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import vtkVolume from 'vtk.js/Sources/Rendering/Core/Volume';
import vtkVolumeMapper from 'vtk.js/Sources/Rendering/Core/VolumeMapper';
import vtkXMLImageDataReader from 'vtk.js/Sources/IO/XML/XMLImageDataReader';

import BinaryHelper from 'vtk.js/Sources/IO/Core/BinaryHelper';

import style from './VolumeViewer.mcss';

let autoInit = true;
Expand Down Expand Up @@ -47,7 +49,7 @@ function preventDefaults(e) {

// ----------------------------------------------------------------------------

function createViewer(rootContainer, fileContentAsText, options) {
function createViewer(rootContainer, parsedFileContents, options) {
const background = options.background ? options.background.split(',').map(s => Number(s)) : [0, 0, 0];
const containerStyle = options.containerStyle;
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ background, rootContainer, containerStyle });
Expand All @@ -56,7 +58,7 @@ function createViewer(rootContainer, fileContentAsText, options) {
renderWindow.getInteractor().setDesiredUpdateRate(15);

const vtiReader = vtkXMLImageDataReader.newInstance();
vtiReader.parse(fileContentAsText);
vtiReader.parse(parsedFileContents.text, parsedFileContents.binaryBuffer);

const source = vtiReader.getOutputData(0);
const mapper = vtkVolumeMapper.newInstance();
Expand Down Expand Up @@ -144,9 +146,12 @@ export function load(container, options) {
if (options.ext === 'vti') {
const reader = new FileReader();
reader.onload = function onLoad(e) {
createViewer(container, reader.result, options);
const prefixRegex = /^\s*<AppendedData\s+encoding="raw">\s*_/m;
const suffixRegex = /\n\s*<\/AppendedData>/m;
const result = BinaryHelper.extractBinary(reader.result, prefixRegex, suffixRegex);
createViewer(container, result, options);
};
reader.readAsText(options.file);
reader.readAsArrayBuffer(options.file);
} else {
console.error('Unkown file...');
}
Expand All @@ -162,7 +167,7 @@ export function load(container, options) {

HttpDataAccessHelper.fetchText({}, options.fileURL, { progressCallback }).then((txt) => {
container.removeChild(progressContainer);
createViewer(container, txt, options);
createViewer(container, { text: txt }, options);
});
}
}
Expand Down
54 changes: 54 additions & 0 deletions Sources/IO/Core/BinaryHelper/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Converts a binary buffer in an ArrayBuffer to a string.
*
* Note this does not take encoding into consideration, so don't
* expect proper Unicode or any other encoding.
*/
function arrayBufferToString(arrayBuffer) {
const byteArray = new Uint8Array(arrayBuffer);
const strArr = [];
for (let i = 0; i < byteArray.length; ++i) {
strArr[i] = String.fromCharCode(byteArray[i]);
}
return strArr.join('');
}

/**
* Extracts binary data out of a file ArrayBuffer given a prefix/suffix.
*/
function extractBinary(arrayBuffer, prefixRegex, suffixRegex = null) {
const str = arrayBufferToString(arrayBuffer);

const prefixMatch = prefixRegex.exec(str);
if (!prefixMatch) {
return { text: str };
}

const dataStartIndex = prefixMatch.index + prefixMatch[0].length;
const strFirstHalf = str.substring(0, dataStartIndex);
let retVal = null;

const suffixMatch = suffixRegex ? suffixRegex.exec(str) : null;
if (suffixMatch) {
const strSecondHalf = str.substr(suffixMatch.index);
retVal = {
text: strFirstHalf + strSecondHalf,
binaryBuffer: arrayBuffer.slice(dataStartIndex, suffixMatch.index),
};
} else {
// no suffix, so just take all the data starting from dataStartIndex
retVal = {
text: strFirstHalf,
binaryBuffer: arrayBuffer.slice(dataStartIndex),
};
}

// TODO Maybe delete the internal ref to strArr from the match objs?
retVal.prefixMatch = prefixMatch;
retVal.suffixMatch = suffixMatch;
return retVal;
}

export default {
arrayBufferToString, extractBinary,
};
2 changes: 2 additions & 0 deletions Sources/IO/Core/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import BinaryHelper from './BinaryHelper';
import DataAccessHelper from './DataAccessHelper';
import vtkHttpDataSetReader from './HttpDataSetReader';
import vtkHttpSceneLoader from './HttpSceneLoader';

export default {
BinaryHelper,
DataAccessHelper,
vtkHttpDataSetReader,
vtkHttpSceneLoader,
Expand Down
6 changes: 4 additions & 2 deletions Sources/IO/XML/XMLImageDataReader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ function vtkXMLImageDataReader(publicAPI, model) {
imageData.getNumberOfPoints(),
piece.getElementsByTagName('PointData')[0],
imageData.getPointData(),
compressor, byteOrder, headerType);
compressor, byteOrder, headerType,
model.binaryBuffer);

vtkXMLReader.processFieldData(
imageData.getNumberOfCells(),
piece.getElementsByTagName('CellData')[0],
imageData.getCellData(),
compressor, byteOrder, headerType);
compressor, byteOrder, headerType,
model.binaryBuffer);

// Add new output
model.output[outputIndex++] = imageData;
Expand Down
18 changes: 10 additions & 8 deletions Sources/IO/XML/XMLPolyDataReader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
// Global method
// ----------------------------------------------------------------------------

function handleArray(polydata, cellType, piece, compressor, byteOrder, headerType) {
function handleArray(polydata, cellType, piece, compressor, byteOrder, headerType, binaryBuffer) {
const size = Number(piece.getAttribute(`NumberOf${cellType}`));
if (size > 0) {
const dataArrayElem = piece.getElementsByTagName(cellType)[0].getElementsByTagName('DataArray')[0];
const { values, numberOfComponents } = vtkXMLReader.processDataArray(size, dataArrayElem, compressor, byteOrder, headerType);
const { values, numberOfComponents } = vtkXMLReader.processDataArray(size, dataArrayElem, compressor, byteOrder, headerType, binaryBuffer);
polydata[`get${cellType}`]().setData(values, numberOfComponents);
}
return size;
}

// ----------------------------------------------------------------------------

function handleCells(polydata, cellType, piece, compressor, byteOrder, headerType) {
function handleCells(polydata, cellType, piece, compressor, byteOrder, headerType, binaryBuffer) {
const size = Number(piece.getAttribute(`NumberOf${cellType}`));
if (size > 0) {
const values = vtkXMLReader.processCells(size, piece.getElementsByTagName(cellType)[0], compressor, byteOrder, headerType);
const values = vtkXMLReader.processCells(size, piece.getElementsByTagName(cellType)[0], compressor, byteOrder, headerType, binaryBuffer);
polydata[`get${cellType}`]().setData(values);
}
return size;
Expand All @@ -46,17 +46,19 @@ function vtkXMLPolyDataReader(publicAPI, model) {
const piece = pieces[outputIndex];

// Points
const nbPoints = handleArray(polydata, 'Points', piece, compressor, byteOrder, headerType);
const nbPoints = handleArray(polydata, 'Points', piece, compressor, byteOrder, headerType, model.binaryBuffer);

// Cells
let nbCells = 0;
['Verts', 'Lines', 'Strips', 'Polys'].forEach((cellType) => {
nbCells += handleCells(polydata, cellType, piece, compressor, byteOrder, headerType);
nbCells += handleCells(polydata, cellType, piece, compressor, byteOrder, headerType, model.binaryBuffer);
});

// Fill data
vtkXMLReader.processFieldData(nbPoints, piece.getElementsByTagName('PointData')[0], polydata.getPointData(), compressor, byteOrder, headerType);
vtkXMLReader.processFieldData(nbCells, piece.getElementsByTagName('CellData')[0], polydata.getCellData(), compressor, byteOrder, headerType);
vtkXMLReader.processFieldData(nbPoints, piece.getElementsByTagName('PointData')[0], polydata.getPointData(),
compressor, byteOrder, headerType, model.binaryBuffer);
vtkXMLReader.processFieldData(nbCells, piece.getElementsByTagName('CellData')[0], polydata.getCellData(),
compressor, byteOrder, headerType, model.binaryBuffer);

// Add new output
model.output[outputIndex++] = polydata;
Expand Down
Loading

0 comments on commit 66ed348

Please sign in to comment.