UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

422 lines (326 loc) 13.9 kB
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 };