@kitware/vtk.js
Version:
Visualization Toolkit for the Web
422 lines (326 loc) • 13.9 kB
JavaScript
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import macro from '../../macros.js';
import DataAccessHelper from '../Core/DataAccessHelper.js';
import vtkDataArray from '../../Common/Core/DataArray.js';
import vtkPolyData from '../../Common/DataModel/PolyData.js';
import '../Core/DataAccessHelper/LiteHttpDataAccessHelper.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; }
// import 'vtk.js/Sources/IO/Core/DataAccessHelper/HttpDataAccessHelper'; // HTTP + gz
// import 'vtk.js/Sources/IO/Core/DataAccessHelper/HtmlDataAccessHelper'; // html + base64 + zip
// import 'vtk.js/Sources/IO/Core/DataAccessHelper/JSZipDataAccessHelper'; // zip
// ----------------------------------------------------------------------------
var data = {}; // ----------------------------------------------------------------------------
function copyVector(src, srcOffset, dst, dstOffset, vectorSize) {
for (var i = 0; i < vectorSize; i++) {
dst[dstOffset + i] = src[srcOffset + i];
}
} // ----------------------------------------------------------------------------
function begin(splitMode) {
data.splitOn = splitMode;
data.pieces = [];
data.v = [];
data.vt = [];
data.vn = [];
data.f = [[]];
data.size = 0;
} // ----------------------------------------------------------------------------
function faceMap(str) {
var idxs = str.split('/').map(function (i) {
return Number(i);
});
var vertexIdx = idxs[0] - 1;
var textCoordIdx = idxs[1] ? idxs[1] - 1 : vertexIdx;
var vertexNormal = idxs[2] ? idxs[2] - 1 : vertexIdx;
return [vertexIdx, textCoordIdx, vertexNormal];
} // ----------------------------------------------------------------------------
function parseLine(line) {
if (line[0] === '#') {
return;
}
var tokens = line.split(/[ \t]+/);
if (tokens[0] === data.splitOn) {
tokens.shift();
data.pieces.push(tokens.join(' ').trim());
data.f.push([]);
data.size++;
} else if (tokens[0] === 'v') {
data.v.push(Number(tokens[1]));
data.v.push(Number(tokens[2]));
data.v.push(Number(tokens[3]));
} else if (tokens[0] === 'vt') {
data.vt.push(Number(tokens[1]));
data.vt.push(Number(tokens[2]));
} else if (tokens[0] === 'vn') {
data.vn.push(Number(tokens[1]));
data.vn.push(Number(tokens[2]));
data.vn.push(Number(tokens[3]));
} else if (tokens[0] === 'f') {
// Handle triangles for now
if (data.size === 0) {
data.size++;
}
var cells = data.f[data.size - 1];
tokens.shift();
var faces = tokens.filter(function (s) {
return s.length > 0 && s !== '\r';
});
var size = faces.length;
cells.push(size);
for (var i = 0; i < size; i++) {
cells.push(faceMap(faces[i]));
}
}
} // ----------------------------------------------------------------------------
function end(model) {
var hasTcoords = !!data.vt.length;
var hasNormals = !!data.vn.length;
if (model.splitMode) {
model.numberOfOutputs = data.size;
for (var idx = 0; idx < data.size; idx++) {
var polyIn = data.f[idx];
var nbElems = polyIn.length;
var nbPoints = data.v.length / 3;
var keyPointId = {};
var pointDuplicatesReferences = void 0;
if (model.trackDuplicates) {
// In trackDuplicates mode, we want the following point layout:
// [pt0, pt1, pt2, ... ptN, pt0d1, pt0d2, pt1d1]
var pointKeys = [];
var duplicatesCount = 0;
for (var _offset = 0; _offset < nbElems;) {
var cellSize = polyIn[_offset++];
for (var pIdx = 0; pIdx < cellSize; pIdx++) {
var _polyIn$_offset = _slicedToArray(polyIn[_offset++], 3),
vIdx = _polyIn$_offset[0],
tcIdx = _polyIn$_offset[1],
nIdx = _polyIn$_offset[2];
var key = "".concat(vIdx, "/").concat(tcIdx, "/").concat(nIdx);
if (keyPointId[key] === undefined) {
if (pointKeys[vIdx] === undefined) {
pointKeys[vIdx] = [key];
} else {
pointKeys[vIdx].push(key);
++duplicatesCount;
} // will be overwritten for duplicates
keyPointId[key] = vIdx;
}
}
}
pointDuplicatesReferences = new Uint16Array(nbPoints + duplicatesCount);
var duplicates = 0;
for (var pointId = 0; pointId < pointKeys.length; ++pointId) {
var usageCount = pointKeys[pointId] ? pointKeys[pointId].length : 0; // Set the first duplicate index on the original point
pointDuplicatesReferences[pointId] = usageCount > 1 ? nbPoints + duplicates : pointId; // Set the original index on each duplicated point
for (var duplicateId = 1; duplicateId < usageCount; ++duplicateId) {
var finalDuplicateId = nbPoints + duplicates++;
pointDuplicatesReferences[finalDuplicateId] = pointId; // Associate the duplicate index to the key
keyPointId[pointKeys[pointId][duplicateId]] = finalDuplicateId;
}
}
}
var ctMapping = {};
var polydata = vtkPolyData.newInstance({
name: data.pieces[idx]
});
var pts = [];
var tc = [];
var normals = [];
var polys = [];
var offset = 0;
while (offset < nbElems) {
var _cellSize = polyIn[offset];
polys.push(_cellSize);
for (var _pIdx = 0; _pIdx < _cellSize; _pIdx++) {
var _polyIn = _slicedToArray(polyIn[offset + _pIdx + 1], 3),
_vIdx = _polyIn[0],
_tcIdx = _polyIn[1],
_nIdx = _polyIn[2];
var _key = "".concat(_vIdx, "/").concat(_tcIdx, "/").concat(_nIdx);
if (ctMapping[_key] === undefined) {
var dstOffset = model.trackDuplicates ? keyPointId[_key] : pts.length / 3;
ctMapping[_key] = dstOffset;
copyVector(data.v, _vIdx * 3, pts, dstOffset * 3, 3);
if (hasTcoords) {
copyVector(data.vt, _tcIdx * 2, tc, dstOffset * 2, 2);
}
if (hasNormals) {
copyVector(data.vn, _nIdx * 3, normals, dstOffset * 3, 3);
}
}
polys.push(ctMapping[_key]);
}
offset += _cellSize + 1;
}
polydata.getPoints().setData(Float32Array.from(pts), 3);
if (model.trackDuplicates) {
var duplicatesArray = vtkDataArray.newInstance({
name: 'Duplicates',
values: pointDuplicatesReferences
});
polydata.getPointData().addArray(duplicatesArray);
}
polydata.getPolys().setData(Uint32Array.from(polys));
if (hasTcoords) {
var tcoords = vtkDataArray.newInstance({
numberOfComponents: 2,
values: Float32Array.from(tc),
name: 'TextureCoordinates'
});
polydata.getPointData().setTCoords(tcoords);
}
if (hasNormals) {
var normalsArray = vtkDataArray.newInstance({
numberOfComponents: 3,
values: Float32Array.from(normals),
name: 'Normals'
});
polydata.getPointData().setNormals(normalsArray);
} // register in output
model.output[idx] = polydata;
}
} else {
model.numberOfOutputs = 1;
var _polydata = vtkPolyData.newInstance();
_polydata.getPoints().setData(Float32Array.from(data.v), 3);
if (hasTcoords && data.v.length / 3 === data.vt.length / 2) {
var _tcoords = vtkDataArray.newInstance({
numberOfComponents: 2,
values: Float32Array.from(data.vt),
name: 'TextureCoordinates'
});
_polydata.getPointData().setTCoords(_tcoords);
}
if (hasNormals && data.v.length === data.vn.length) {
var _normalsArray = vtkDataArray.newInstance({
numberOfComponents: 3,
values: Float32Array.from(data.vn),
name: 'Normals'
});
_polydata.getPointData().setNormals(_normalsArray);
}
var _polys = [];
var _polyIn2 = data.f[0];
var _nbElems = _polyIn2.length;
var _offset2 = 0;
while (_offset2 < _nbElems) {
var _cellSize2 = _polyIn2[_offset2];
_polys.push(_cellSize2);
for (var _pIdx2 = 0; _pIdx2 < _cellSize2; _pIdx2++) {
var _polyIn3 = _slicedToArray(_polyIn2[_offset2 + _pIdx2 + 1], 1),
_vIdx2 = _polyIn3[0];
_polys.push(_vIdx2);
}
_offset2 += _cellSize2 + 1;
}
_polydata.getPolys().setData(Uint32Array.from(_polys));
model.output[0] = _polydata;
}
} // ----------------------------------------------------------------------------
// Static API
// ----------------------------------------------------------------------------
function getPointDuplicateIds(polyData, pointId) {
var res = [];
var duplicates = polyData.getPointData().getArrayByName('Duplicates');
if (duplicates == null) {
return res;
}
var duplicatesData = duplicates.getData();
var originalPointId = Math.min(pointId, duplicatesData[pointId]);
res.push(originalPointId);
var duplicateId = duplicatesData[originalPointId];
if (duplicateId !== originalPointId) {
// point has duplicates
while (duplicateId < duplicatesData.length && duplicatesData[duplicateId] === originalPointId) {
// Duplicated points must be next to each other and original point must
// reference first duplicate
res.push(duplicateId++);
}
}
return res;
}
var STATIC = {
getPointDuplicateIds: getPointDuplicateIds
}; // ----------------------------------------------------------------------------
// vtkOBJReader methods
// ----------------------------------------------------------------------------
function vtkOBJReader(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkOBJReader'); // Create default dataAccessHelper if not available
if (!model.dataAccessHelper) {
model.dataAccessHelper = DataAccessHelper.get('http');
} // Internal method to fetch Array
function fetchData(url) {
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return model.dataAccessHelper.fetchText(publicAPI, url, option);
} // Set DataSet url
publicAPI.setUrl = function (url) {
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (url.indexOf('.obj') === -1 && !option.fullpath) {
model.baseURL = url;
model.url = "".concat(url, "/index.obj");
} else {
model.url = url; // Remove the file in the URL
var path = url.split('/');
path.pop();
model.baseURL = path.join('/');
} // Fetch metadata
return publicAPI.loadData(option);
}; // Fetch the actual data arrays
publicAPI.loadData = function () {
var option = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return fetchData(model.url, option).then(function (content) {
return publicAPI.isDeleted() ? false : publicAPI.parseAsText(content);
});
};
publicAPI.parseAsText = function (content) {
if (!content) {
return true;
}
if (content !== model.parseData) {
publicAPI.modified();
}
model.parseData = content;
model.numberOfOutputs = 0;
begin(model.splitMode);
content.split('\n').forEach(parseLine);
end(model);
return true;
};
publicAPI.requestData = function (inData, outData) {
publicAPI.parseAsText(model.parseData);
}; // return Busy state
publicAPI.isBusy = function () {
return !!model.requestCount;
};
publicAPI.getNumberOfOutputPorts = function () {
return model.numberOfOutputs;
};
} // ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
var DEFAULT_VALUES = {
numberOfOutputs: 1,
requestCount: 0,
splitMode: null,
trackDuplicates: false // baseURL: null,
// dataAccessHelper: null,
// url: null,
}; // ----------------------------------------------------------------------------
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.get(publicAPI, model, ['url', 'baseURL']);
macro.setGet(publicAPI, model, ['dataAccessHelper', 'splitMode', 'trackDuplicates']);
macro.algo(publicAPI, model, 0, 1);
macro.event(publicAPI, model, 'busy'); // Object methods
vtkOBJReader(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = macro.newInstance(extend, 'vtkOBJReader'); // ----------------------------------------------------------------------------
var vtkOBJReader$1 = _objectSpread({
newInstance: newInstance,
extend: extend
}, STATIC);
export { STATIC, vtkOBJReader$1 as default, extend, newInstance };