VTKLoader.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. * @author Alex Pletzer
  4. * @author Sagar DV / https://dvenkatsagar.github.io
  5. */
  6. // Work In Progress
  7. // Custom VTKLoader based on the original but with extra xml polydata support
  8. THREE.VTKLoader = function( manager ) {
  9. this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
  10. };
  11. THREE.VTKLoader.prototype = {
  12. constructor: THREE.VTKLoader,
  13. load: function ( url, onLoad, onProgress, onError ) {
  14. var scope = this;
  15. var loader = new THREE.XHRLoader( scope.manager );
  16. loader.setResponseType( 'arraybuffer' );
  17. loader.load( url, function( text ) {
  18. onLoad( scope.parse( text ) );
  19. }, onProgress, onError );
  20. },
  21. parse: function ( data ) {
  22. function parseASCII( data ) {
  23. // connectivity of the triangles
  24. var indices = [];
  25. // triangles vertices
  26. var positions = [];
  27. // red, green, blue colors in the range 0 to 1
  28. var colors = [];
  29. // normal vector, one per vertex
  30. var normals = [];
  31. var result;
  32. // pattern for reading vertices, 3 floats or integers
  33. var pat3Floats = /(\-?\d+\.?[\d\-\+e]*)\s+(\-?\d+\.?[\d\-\+e]*)\s+(\-?\d+\.?[\d\-\+e]*)/g;
  34. // pattern for connectivity, an integer followed by any number of ints
  35. // the first integer is the number of polygon nodes
  36. var patConnectivity = /^(\d+)\s+([\s\d]*)/;
  37. // indicates start of vertex data section
  38. var patPOINTS = /^POINTS /;
  39. // indicates start of polygon connectivity section
  40. var patPOLYGONS = /^POLYGONS /;
  41. // indicates start of triangle strips section
  42. var patTRIANGLE_STRIPS = /^TRIANGLE_STRIPS /;
  43. // POINT_DATA number_of_values
  44. var patPOINT_DATA = /^POINT_DATA[ ]+(\d+)/;
  45. // CELL_DATA number_of_polys
  46. var patCELL_DATA = /^CELL_DATA[ ]+(\d+)/;
  47. // Start of color section
  48. var patCOLOR_SCALARS = /^COLOR_SCALARS[ ]+(\w+)[ ]+3/;
  49. // NORMALS Normals float
  50. var patNORMALS = /^NORMALS[ ]+(\w+)[ ]+(\w+)/;
  51. var inPointsSection = false;
  52. var inPolygonsSection = false;
  53. var inTriangleStripSection = false;
  54. var inPointDataSection = false;
  55. var inCellDataSection = false;
  56. var inColorSection = false;
  57. var inNormalsSection = false;
  58. var lines = data.split( '\n' );
  59. for ( var i in lines ) {
  60. var line = lines[ i ];
  61. if ( inPointsSection ) {
  62. // get the vertices
  63. while ( ( result = pat3Floats.exec( line ) ) !== null ) {
  64. var x = parseFloat( result[ 1 ] );
  65. var y = parseFloat( result[ 2 ] );
  66. var z = parseFloat( result[ 3 ] );
  67. positions.push( x, y, z );
  68. }
  69. } else if ( inPolygonsSection ) {
  70. if ( ( result = patConnectivity.exec( line ) ) !== null ) {
  71. // numVertices i0 i1 i2 ...
  72. var numVertices = parseInt( result[ 1 ] );
  73. var inds = result[ 2 ].split( /\s+/ );
  74. if ( numVertices >= 3 ) {
  75. var i0 = parseInt( inds[ 0 ] );
  76. var i1, i2;
  77. var k = 1;
  78. // split the polygon in numVertices - 2 triangles
  79. for ( var j = 0; j < numVertices - 2; ++ j ) {
  80. i1 = parseInt( inds[ k ] );
  81. i2 = parseInt( inds[ k + 1 ] );
  82. indices.push( i0, i1, i2 );
  83. k ++;
  84. }
  85. }
  86. }
  87. } else if ( inTriangleStripSection ) {
  88. if ( ( result = patConnectivity.exec( line ) ) !== null ) {
  89. // numVertices i0 i1 i2 ...
  90. var numVertices = parseInt( result[ 1 ] );
  91. var inds = result[ 2 ].split( /\s+/ );
  92. if ( numVertices >= 3 ) {
  93. var i0, i1, i2;
  94. // split the polygon in numVertices - 2 triangles
  95. for ( var j = 0; j < numVertices - 2; j ++ ) {
  96. if ( j % 2 === 1 ) {
  97. i0 = parseInt( inds[ j ] );
  98. i1 = parseInt( inds[ j + 2 ] );
  99. i2 = parseInt( inds[ j + 1 ] );
  100. indices.push( i0, i1, i2 );
  101. } else {
  102. i0 = parseInt( inds[ j ] );
  103. i1 = parseInt( inds[ j + 1 ] );
  104. i2 = parseInt( inds[ j + 2 ] );
  105. indices.push( i0, i1, i2 );
  106. }
  107. }
  108. }
  109. }
  110. } else if ( inPointDataSection || inCellDataSection ) {
  111. if ( inColorSection ) {
  112. // Get the colors
  113. while ( ( result = pat3Floats.exec( line ) ) !== null ) {
  114. var r = parseFloat( result[ 1 ] );
  115. var g = parseFloat( result[ 2 ] );
  116. var b = parseFloat( result[ 3 ] );
  117. colors.push( r, g, b );
  118. }
  119. } else if ( inNormalsSection ) {
  120. // Get the normal vectors
  121. while ( ( result = pat3Floats.exec( line ) ) !== null ) {
  122. var nx = parseFloat( result[ 1 ] );
  123. var ny = parseFloat( result[ 2 ] );
  124. var nz = parseFloat( result[ 3 ] );
  125. normals.push( nx, ny, nz );
  126. }
  127. }
  128. }
  129. if ( patPOLYGONS.exec( line ) !== null ) {
  130. inPolygonsSection = true;
  131. inPointsSection = false;
  132. inTriangleStripSection = false;
  133. } else if ( patPOINTS.exec( line ) !== null ) {
  134. inPolygonsSection = false;
  135. inPointsSection = true;
  136. inTriangleStripSection = false;
  137. } else if ( patTRIANGLE_STRIPS.exec( line ) !== null ) {
  138. inPolygonsSection = false;
  139. inPointsSection = false;
  140. inTriangleStripSection = true;
  141. } else if ( patPOINT_DATA.exec( line ) !== null ) {
  142. inPointDataSection = true;
  143. inPointsSection = false;
  144. inPolygonsSection = false;
  145. inTriangleStripSection = false;
  146. } else if ( patCELL_DATA.exec( line ) !== null ) {
  147. inCellDataSection = true;
  148. inPointsSection = false;
  149. inPolygonsSection = false;
  150. inTriangleStripSection = false;
  151. } else if ( patCOLOR_SCALARS.exec( line ) !== null ) {
  152. inColorSection = true;
  153. inNormalsSection = false;
  154. inPointsSection = false;
  155. inPolygonsSection = false;
  156. inTriangleStripSection = false;
  157. } else if ( patNORMALS.exec( line ) !== null ) {
  158. inNormalsSection = true;
  159. inColorSection = false;
  160. inPointsSection = false;
  161. inPolygonsSection = false;
  162. inTriangleStripSection = false;
  163. }
  164. }
  165. var geometry;
  166. var stagger = 'point';
  167. if ( colors.length == indices.length ) {
  168. stagger = 'cell';
  169. }
  170. if ( stagger == 'point' ) {
  171. // Nodal. Use BufferGeometry
  172. geometry = new THREE.BufferGeometry();
  173. geometry.setIndex( new THREE.BufferAttribute( new Uint32Array( indices ), 1 ) );
  174. geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( positions ), 3 ) );
  175. if ( colors.length == positions.length ) {
  176. geometry.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( colors ), 3 ) );
  177. }
  178. if ( normals.length == positions.length ) {
  179. geometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( normals ), 3 ) );
  180. }
  181. } else {
  182. // Cell centered colors. The only way to attach a solid color to each triangle
  183. // is to use Geometry, which is less efficient than BufferGeometry
  184. geometry = new THREE.Geometry();
  185. var numTriangles = indices.length / 3;
  186. var numPoints = positions.length / 3;
  187. var va, vb, vc;
  188. var face;
  189. var ia, ib, ic;
  190. var x, y, z;
  191. var r, g, b;
  192. for ( var j = 0; j < numPoints; ++ j ) {
  193. x = positions[ 3 * j + 0 ];
  194. y = positions[ 3 * j + 1 ];
  195. z = positions[ 3 * j + 2 ];
  196. geometry.vertices.push( new THREE.Vector3( x, y, z ) );
  197. }
  198. for ( var i = 0; i < numTriangles; ++ i ) {
  199. ia = indices[ 3 * i + 0 ];
  200. ib = indices[ 3 * i + 1 ];
  201. ic = indices[ 3 * i + 2 ];
  202. geometry.faces.push( new THREE.Face3( ia, ib, ic ) );
  203. }
  204. if ( colors.length == numTriangles * 3 ) {
  205. for ( var i = 0; i < numTriangles; ++ i ) {
  206. face = geometry.faces[ i ];
  207. r = colors[ 3 * i + 0 ];
  208. g = colors[ 3 * i + 1 ];
  209. b = colors[ 3 * i + 2 ];
  210. face.color = new THREE.Color().setRGB( r, g, b );
  211. }
  212. }
  213. }
  214. return geometry;
  215. }
  216. function parseBinary( data ) {
  217. var count, pointIndex, i, numberOfPoints, pt, s;
  218. var buffer = new Uint8Array ( data );
  219. var dataView = new DataView ( data );
  220. // Points and normals, by default, are empty
  221. var points = [];
  222. var normals = [];
  223. var indices = [];
  224. // Going to make a big array of strings
  225. var vtk = [];
  226. var index = 0;
  227. function findString( buffer, start ) {
  228. var index = start;
  229. var c = buffer[ index ];
  230. var s = [];
  231. while ( c != 10 ) {
  232. s.push ( String.fromCharCode ( c ) );
  233. index ++;
  234. c = buffer[ index ];
  235. }
  236. return { start: start,
  237. end: index,
  238. next: index + 1,
  239. parsedString: s.join( '' ) };
  240. }
  241. var state, line;
  242. while ( true ) {
  243. // Get a string
  244. state = findString ( buffer, index );
  245. line = state.parsedString;
  246. if ( line.indexOf ( "POINTS" ) === 0 ) {
  247. vtk.push ( line );
  248. // Add the points
  249. numberOfPoints = parseInt ( line.split( " " )[ 1 ], 10 );
  250. // Each point is 3 4-byte floats
  251. count = numberOfPoints * 4 * 3;
  252. points = new Float32Array( numberOfPoints * 3 );
  253. pointIndex = state.next;
  254. for ( i = 0; i < numberOfPoints; i ++ ) {
  255. points[ 3 * i ] = dataView.getFloat32( pointIndex, false );
  256. points[ 3 * i + 1 ] = dataView.getFloat32( pointIndex + 4, false );
  257. points[ 3 * i + 2 ] = dataView.getFloat32( pointIndex + 8, false );
  258. pointIndex = pointIndex + 12;
  259. }
  260. // increment our next pointer
  261. state.next = state.next + count + 1;
  262. } else if ( line.indexOf ( "TRIANGLE_STRIPS" ) === 0 ) {
  263. var numberOfStrips = parseInt ( line.split( " " )[ 1 ], 10 );
  264. var size = parseInt ( line.split ( " " )[ 2 ], 10 );
  265. // 4 byte integers
  266. count = size * 4;
  267. indices = new Uint32Array( 3 * size - 9 * numberOfStrips );
  268. var indicesIndex = 0;
  269. pointIndex = state.next;
  270. for ( i = 0; i < numberOfStrips; i ++ ) {
  271. // For each strip, read the first value, then record that many more points
  272. var indexCount = dataView.getInt32( pointIndex, false );
  273. var strip = [];
  274. pointIndex += 4;
  275. for ( s = 0; s < indexCount; s ++ ) {
  276. strip.push ( dataView.getInt32( pointIndex, false ) );
  277. pointIndex += 4;
  278. }
  279. // retrieves the n-2 triangles from the triangle strip
  280. for ( var j = 0; j < indexCount - 2; j ++ ) {
  281. if ( j % 2 ) {
  282. indices[ indicesIndex ++ ] = strip[ j ];
  283. indices[ indicesIndex ++ ] = strip[ j + 2 ];
  284. indices[ indicesIndex ++ ] = strip[ j + 1 ];
  285. } else {
  286. indices[ indicesIndex ++ ] = strip[ j ];
  287. indices[ indicesIndex ++ ] = strip[ j + 1 ];
  288. indices[ indicesIndex ++ ] = strip[ j + 2 ];
  289. }
  290. }
  291. }
  292. // increment our next pointer
  293. state.next = state.next + count + 1;
  294. } else if ( line.indexOf ( "POLYGONS" ) === 0 ) {
  295. var numberOfStrips = parseInt ( line.split( " " )[ 1 ], 10 );
  296. var size = parseInt ( line.split ( " " )[ 2 ], 10 );
  297. // 4 byte integers
  298. count = size * 4;
  299. indices = new Uint32Array( 3 * size - 9 * numberOfStrips );
  300. var indicesIndex = 0;
  301. pointIndex = state.next;
  302. for ( i = 0; i < numberOfStrips; i ++ ) {
  303. // For each strip, read the first value, then record that many more points
  304. var indexCount = dataView.getInt32( pointIndex, false );
  305. var strip = [];
  306. pointIndex += 4;
  307. for ( s = 0; s < indexCount; s ++ ) {
  308. strip.push ( dataView.getInt32( pointIndex, false ) );
  309. pointIndex += 4;
  310. }
  311. var i0 = strip[ 0 ];
  312. // divide the polygon in n-2 triangle
  313. for ( var j = 1; j < indexCount - 1; j ++ ) {
  314. indices[ indicesIndex ++ ] = strip[ 0 ];
  315. indices[ indicesIndex ++ ] = strip[ j ];
  316. indices[ indicesIndex ++ ] = strip[ j + 1 ];
  317. }
  318. }
  319. // increment our next pointer
  320. state.next = state.next + count + 1;
  321. } else if ( line.indexOf ( "POINT_DATA" ) === 0 ) {
  322. numberOfPoints = parseInt ( line.split( " " )[ 1 ], 10 );
  323. // Grab the next line
  324. state = findString ( buffer, state.next );
  325. // Now grab the binary data
  326. count = numberOfPoints * 4 * 3;
  327. normals = new Float32Array( numberOfPoints * 3 );
  328. pointIndex = state.next;
  329. for ( i = 0; i < numberOfPoints; i ++ ) {
  330. normals[ 3 * i ] = dataView.getFloat32( pointIndex, false );
  331. normals[ 3 * i + 1 ] = dataView.getFloat32( pointIndex + 4, false );
  332. normals[ 3 * i + 2 ] = dataView.getFloat32( pointIndex + 8, false );
  333. pointIndex += 12;
  334. }
  335. // Increment past our data
  336. state.next = state.next + count;
  337. }
  338. // Increment index
  339. index = state.next;
  340. if ( index >= buffer.byteLength ) {
  341. break;
  342. }
  343. }
  344. var geometry = new THREE.BufferGeometry();
  345. geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
  346. geometry.addAttribute( 'position', new THREE.BufferAttribute( points, 3 ) );
  347. if ( normals.length == points.length ) {
  348. geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
  349. }
  350. return geometry;
  351. }
  352. function parseXML(stringFile){
  353. // Changes XML to JSON, based on https://davidwalsh.name/convert-xml-json
  354. var xmlToJson = function (xml) {
  355. // Create the return object
  356. var obj = {};
  357. if (xml.nodeType == 1) { // element
  358. // do attributes
  359. if (xml.attributes) {
  360. if (xml.attributes.length > 0) {
  361. obj["attributes"] = {};
  362. for (var j = 0; j < xml.attributes.length; j++) {
  363. var attribute = xml.attributes.item(j);
  364. obj["attributes"][attribute.nodeName] = attribute.nodeValue.trim();
  365. }
  366. }
  367. }
  368. } else if (xml.nodeType == 3) { // text
  369. obj = xml.nodeValue.trim();
  370. }
  371. // do children
  372. if (xml.hasChildNodes()) {
  373. for(var i = 0; i < xml.childNodes.length; i++) {
  374. var item = xml.childNodes.item(i);
  375. var nodeName = item.nodeName;
  376. if (typeof(obj[nodeName]) == "undefined") {
  377. var tmp = xmlToJson(item);
  378. if(tmp != ""){
  379. obj[nodeName] = tmp;
  380. }
  381. } else {
  382. if (typeof(obj[nodeName].push) == "undefined") {
  383. var old = obj[nodeName];
  384. obj[nodeName] = [];
  385. obj[nodeName].push(old);
  386. }
  387. var tmp = xmlToJson(item);
  388. if(tmp != ""){
  389. obj[nodeName].push(tmp);
  390. }
  391. }
  392. }
  393. }
  394. return obj;
  395. };
  396. // Taken from Base64-js
  397. var Base64toByteArray = function(b64) {
  398. var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
  399. var i;
  400. var lookup = [];
  401. var revLookup = [];
  402. var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  403. var len = code.length;
  404. for (i = 0; i < len; i++) {
  405. lookup[i] = code[i];
  406. }
  407. for (i = 0; i < len; ++i) {
  408. revLookup[code.charCodeAt(i)] = i;
  409. }
  410. revLookup['-'.charCodeAt(0)] = 62;
  411. revLookup['_'.charCodeAt(0)] = 63;
  412. var j, l, tmp, placeHolders, arr;
  413. var len = b64.length;
  414. if (len % 4 > 0) {
  415. throw new Error('Invalid string. Length must be a multiple of 4');
  416. }
  417. placeHolders = b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0;
  418. arr = new Arr(len * 3 / 4 - placeHolders);
  419. l = placeHolders > 0 ? len - 4 : len;
  420. var L = 0;
  421. for (i = 0, j = 0; i < l; i += 4, j += 3) {
  422. tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)];
  423. arr[L++] = (tmp & 0xFF0000) >> 16;
  424. arr[L++] = (tmp & 0xFF00) >> 8;
  425. arr[L++] = tmp & 0xFF;
  426. }
  427. if (placeHolders === 2) {
  428. tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4);
  429. arr[L++] = tmp & 0xFF;
  430. } else if (placeHolders === 1) {
  431. tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2);
  432. arr[L++] = (tmp >> 8) & 0xFF;
  433. arr[L++] = tmp & 0xFF;
  434. }
  435. return arr;
  436. }
  437. var parseDataArray = function(ele, compressed){
  438. // Check the format
  439. if (ele.attributes.format == "binary"){
  440. if(compressed){
  441. // Split the blob_header and compressed Data
  442. if(ele["#text"].indexOf('==') != -1){
  443. var data = ele["#text"].split("==");
  444. //console.log(data);
  445. if (data.length == 2){
  446. var blob = data.shift();
  447. var content = data.shift();
  448. if(content == ""){
  449. content = blob + "==";
  450. }
  451. }else if(data.length > 2){
  452. var blob = data.shift();
  453. var content = data.shift();
  454. content = content + "==";
  455. }else if (data.length < 2){
  456. var content = data.shift();
  457. content = content + "==";
  458. }
  459. // Convert to bytearray
  460. var arr = Base64toByteArray(content);
  461. // decompress
  462. var inflate = new Zlib.Inflate(arr,{resize:true,verify:true});
  463. var content = inflate.decompress();
  464. }else{
  465. var content = Base64toByteArray(ele["#text"]);
  466. }
  467. }else{
  468. var content = Base64toByteArray(ele["#text"]);
  469. }
  470. var content = content.buffer;
  471. }else{
  472. if(ele["#text"]){
  473. var content = ele["#text"].replace(/\n/g," ").split(" ").filter(function(el,idx,arr){
  474. if(el != ""){
  475. return el;
  476. }
  477. });
  478. }else{
  479. var content = new Int32Array(0).buffer;
  480. }
  481. }
  482. delete ele["#text"];
  483. // Get the content and optimize it
  484. if(ele.attributes.type == 'Float32'){
  485. var txt = new Float32Array(content);
  486. if(ele.attributes.format == "binary"){
  487. if(!compressed){
  488. txt = txt.filter(function(el,idx,arr){if(idx != 0){return true;}});
  489. }
  490. }
  491. }else if (ele.attributes.type == 'Int64'){
  492. var txt = new Int32Array(content);
  493. if(ele.attributes.format == "binary"){
  494. if(!compressed){
  495. txt = txt.filter(function(el,idx,arr){if(idx!=0){return true;}});
  496. }
  497. txt = txt.filter(function(el,idx,arr){if(idx%2!=1){return true;}});
  498. }
  499. }
  500. //console.log(txt);
  501. return txt;
  502. }
  503. // Main part
  504. // Get Dom
  505. var dom = null;
  506. if (window.DOMParser) {
  507. try {
  508. dom = (new DOMParser()).parseFromString(stringFile, "text/xml");
  509. }catch (e) {
  510. dom = null;
  511. }
  512. }else if (window.ActiveXObject) {
  513. try {
  514. dom = new ActiveXObject('Microsoft.XMLDOM');
  515. dom.async = false;
  516. if (!dom.loadXML(xml)){
  517. throw new Error(dom.parseError.reason + dom.parseError.srcText);
  518. }
  519. }catch (e) {
  520. dom = null;
  521. }
  522. }else{
  523. throw new Error("Cannot parse xml string!");
  524. }
  525. // Get the doc
  526. var doc = dom.documentElement;
  527. // Convert to json
  528. var json = xmlToJson(doc);
  529. var points = [];
  530. var normals = [];
  531. var indices = [];
  532. if(json.PolyData){
  533. var piece = json.PolyData.Piece;
  534. var compressed = json.attributes.hasOwnProperty("compressor");
  535. // Can be optimized
  536. // Loop through the sections
  537. var sections = ["PointData", "Points", "Strips", "Polys"];// +["CellData", "Verts", "Lines"];
  538. var sectionIndex = 0, numberOfSections = sections.length;
  539. while (sectionIndex < numberOfSections){
  540. var section = piece[sections[sectionIndex]];
  541. // If it has a DataArray in it
  542. if(section.DataArray){
  543. // Depending on the number of DataArrays
  544. if(Object.prototype.toString.call( section.DataArray ) === '[object Array]'){
  545. var arr = section.DataArray;
  546. }else{
  547. var arr = [section.DataArray];
  548. }
  549. var dataArrayIndex = 0, numberOfDataArrays = arr.length;
  550. while(dataArrayIndex < numberOfDataArrays){
  551. // Parse the DataArray
  552. arr[dataArrayIndex].text = parseDataArray(arr[dataArrayIndex],compressed);
  553. dataArrayIndex++;
  554. }
  555. switch(sections[sectionIndex]){
  556. // if iti is point data
  557. case "PointData" :
  558. var numberOfPoints = parseInt(piece.attributes.NumberOfPoints);
  559. var normalsName = section.attributes.Normals;
  560. if (numberOfPoints > 0){
  561. for(var i = 0, len = arr.length; i < len; i++){
  562. if(normalsName == arr[i].attributes.Name){
  563. var components = arr[i].attributes.NumberOfComponents;
  564. normals = new Float32Array(numberOfPoints * components);
  565. normals.set(arr[i].text,0);
  566. }
  567. }
  568. }
  569. //console.log("Normals", normals);
  570. break;
  571. // if it is points
  572. case "Points" :
  573. var numberOfPoints = parseInt(piece.attributes.NumberOfPoints);
  574. if (numberOfPoints > 0){
  575. var components = section.DataArray.attributes.NumberOfComponents;
  576. points = new Float32Array( numberOfPoints * components );
  577. points.set(section.DataArray.text, 0);
  578. }
  579. //console.log("Points", points);
  580. break;
  581. // if it is strips
  582. case "Strips" :
  583. var numberOfStrips = parseInt(piece.attributes.NumberOfStrips);
  584. if(numberOfStrips > 0){
  585. var connectivity = new Int32Array(section.DataArray[0].text.length);
  586. var offset = new Int32Array(section.DataArray[1].text.length);
  587. connectivity.set(section.DataArray[0].text, 0);
  588. offset.set(section.DataArray[1].text, 0);
  589. var size = numberOfStrips + connectivity.length;
  590. indices = new Uint32Array( 3 * size - 9 * numberOfStrips );
  591. var indicesIndex = 0;
  592. for (var i = 0,len = numberOfStrips; i < len; i++) {
  593. var strip = [];
  594. for (var s = 0,len1 = offset[i], len0 = 0; s < len1 - len0; s++) {
  595. strip.push (connectivity[s]);
  596. if(i > 0){
  597. len0 = offset[i-1];
  598. }
  599. }
  600. for (var j = 0,len1 = offset[i], len0 = 0; j < len1 - len0 - 2; j++) {
  601. if ( j % 2 ) {
  602. indices[ indicesIndex++ ] = strip[ j ];
  603. indices[ indicesIndex++ ] = strip[ j + 2 ];
  604. indices[ indicesIndex++ ] = strip[ j + 1 ];
  605. }else{
  606. indices[ indicesIndex++ ] = strip[ j ];
  607. indices[ indicesIndex++ ] = strip[ j + 1 ];
  608. indices[ indicesIndex++ ] = strip[ j + 2 ];
  609. }
  610. if(i > 0){
  611. len0 = offset[i-1];
  612. }
  613. }
  614. }
  615. }
  616. //console.log("Strips", indices);
  617. break;
  618. // if it is polys
  619. case "Polys" :
  620. var numberOfPolys = parseInt(piece.attributes.NumberOfPolys);
  621. if(numberOfPolys > 0){
  622. var connectivity = new Int32Array(section.DataArray[0].text.length);
  623. var offset = new Int32Array(section.DataArray[1].text.length);
  624. connectivity.set(section.DataArray[0].text, 0);
  625. offset.set(section.DataArray[1].text, 0);
  626. var size = numberOfPolys + connectivity.length;
  627. indices = new Uint32Array( 3 * size - 9 * numberOfPolys );
  628. var indicesIndex = 0, connectivityIndex = 0;
  629. var i = 0,len = numberOfPolys, len0 = 0;
  630. while(i < len){
  631. var poly = [];
  632. var s = 0, len1 = offset[i];
  633. while(s < len1 - len0){
  634. poly.push (connectivity[connectivityIndex++]);
  635. s++;
  636. }
  637. var j = 1;
  638. while(j < len1 - len0 - 1){
  639. indices[ indicesIndex++ ] = poly[ 0 ];
  640. indices[ indicesIndex++ ] = poly[ j ];
  641. indices[ indicesIndex++ ] = poly[ j + 1 ];
  642. j++;
  643. }
  644. i++;
  645. len0 = offset[i-1];
  646. }
  647. }
  648. //console.log("Polys", indices);
  649. break;
  650. default :
  651. break;
  652. }
  653. }
  654. sectionIndex++;
  655. }
  656. var geometry = new THREE.BufferGeometry();
  657. geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
  658. geometry.addAttribute( 'position', new THREE.BufferAttribute( points, 3 ) );
  659. if ( normals.length == points.length ) {
  660. geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
  661. }
  662. //console.log(json);
  663. return geometry;
  664. }else{
  665. /* TODO for vtu,vti,and other xml formats*/
  666. }
  667. }
  668. function getStringFile(data){
  669. var stringFile = '';
  670. var charArray = new Uint8Array( data );
  671. var i = 0;
  672. var len = charArray.length;
  673. while(len--){
  674. stringFile += String.fromCharCode( charArray[ i++ ] );
  675. }
  676. return stringFile;
  677. }
  678. // get the 5 first lines of the files to check if there is the key word binary
  679. var meta = String.fromCharCode.apply( null, new Uint8Array( data, 0, 250 ) ).split( '\n' );
  680. if (meta[0].indexOf("xml") != -1){
  681. var stringFile = getStringFile(data);
  682. return parseXML(stringFile);
  683. }else if ( meta[ 2 ].includes( 'ASCII' ) ) {
  684. var stringFile = getStringFile(data);
  685. return parseASCII( stringFile );
  686. } else {
  687. return parseBinary( data );
  688. }
  689. }
  690. };
  691. THREE.EventDispatcher.prototype.apply( THREE.VTKLoader.prototype );