1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkAVSucdReader.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 // Thanks to Guenole Harel and Emmanuel Colin (Supelec engineering school,
16 // France) and Jean M. Favre (CSCS, Switzerland) who co-developed this class.
17 // Thanks to Isabelle Surin (isabelle.surin at cea.fr, CEA-DAM, France) who
18 // supervised the internship of the first two authors. Thanks to Daniel
19 // Aguilera (daniel.aguilera at cea.fr, CEA-DAM, France) who contributed code
20 // und advice. Please address all comments to Jean Favre (jfavre at cscs.ch)
21
22 #include "vtkAVSucdReader.h"
23 #include "vtkType.h"
24 #include "vtkDataArraySelection.h"
25 #include "vtkErrorCode.h"
26 #include "vtkUnstructuredGrid.h"
27 #include "vtkInformation.h"
28 #include "vtkInformationVector.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkFieldData.h"
31 #include "vtkPointData.h"
32 #include "vtkCellData.h"
33 #include "vtkByteSwap.h"
34 #include "vtkIdTypeArray.h"
35 #include "vtkFloatArray.h"
36 #include "vtkIntArray.h"
37 #include "vtkByteSwap.h"
38 #include "vtkCellArray.h"
39
40 #include <map>
41
42 vtkStandardNewMacro(vtkAVSucdReader);
43
44 // Internal Classes/Structures
45 struct vtkAVSucdReader::idMapping : public std::map<vtkIdType, vtkIdType>
46 {};
47
48 //----------------------------------------------------------------------------
vtkAVSucdReader()49 vtkAVSucdReader::vtkAVSucdReader()
50 {
51 this->FileName = nullptr;
52 this->ByteOrder = FILE_BIG_ENDIAN;
53 this->BinaryFile = 0;
54 this->NumberOfNodeFields = 0;
55 this->NumberOfCellFields = 0;
56 this->NumberOfFields = 0;
57 this->NumberOfNodeComponents = 0;
58 this->NumberOfCellComponents = 0;
59 this->FileStream = nullptr;
60 this->NumberOfNodes = 0;
61 this->NumberOfCells = 0;
62
63 this->NodeDataInfo = nullptr;
64 this->CellDataInfo = nullptr;
65 this->PointDataArraySelection = vtkDataArraySelection::New();
66 this->CellDataArraySelection = vtkDataArraySelection::New();
67
68 this->SetNumberOfInputPorts(0);
69 }
70
71 //----------------------------------------------------------------------------
~vtkAVSucdReader()72 vtkAVSucdReader::~vtkAVSucdReader()
73 {
74 delete [] this->FileName;
75 delete [] this->NodeDataInfo;
76 delete [] this->CellDataInfo;
77
78 this->CellDataArraySelection->Delete();
79 this->PointDataArraySelection->Delete();
80 }
81
82
83 //----------------------------------------------------------------------------
SetByteOrderToBigEndian()84 void vtkAVSucdReader::SetByteOrderToBigEndian()
85 {
86 this->ByteOrder = FILE_BIG_ENDIAN;
87 }
88
89
90 //----------------------------------------------------------------------------
SetByteOrderToLittleEndian()91 void vtkAVSucdReader::SetByteOrderToLittleEndian()
92 {
93 this->ByteOrder = FILE_LITTLE_ENDIAN;
94 }
95
96 //----------------------------------------------------------------------------
GetByteOrderAsString()97 const char *vtkAVSucdReader::GetByteOrderAsString()
98 {
99 if ( this->ByteOrder == FILE_LITTLE_ENDIAN)
100 {
101 return "LittleEndian";
102 }
103 else
104 {
105 return "BigEndian";
106 }
107 }
108
109 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)110 int vtkAVSucdReader::RequestData(
111 vtkInformation *vtkNotUsed(request),
112 vtkInformationVector **vtkNotUsed(inputVector),
113 vtkInformationVector *outputVector)
114 {
115 // get the info object
116 vtkInformation *outInfo = outputVector->GetInformationObject(0);
117
118 // get the output
119 vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
120 outInfo->Get(vtkDataObject::DATA_OBJECT()));
121
122 vtkDebugMacro( << "Reading AVS UCD file");
123
124 // If ExecuteInformation() failed FileStream will be nullptr and
125 // ExecuteInformation() will have spit out an error.
126 if ( this->FileStream )
127 {
128 this->ReadFile(output);
129 }
130
131 return 1;
132 }
133
134 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)135 void vtkAVSucdReader::PrintSelf(ostream& os, vtkIndent indent)
136 {
137 this->Superclass::PrintSelf(os,indent);
138
139 os << indent << "File Name: "
140 << (this->FileName ? this->FileName : "(none)") << "\n";
141
142 os << indent << "Number Of Nodes: " << this->NumberOfNodes << endl;
143 os << indent << "Number Of Node Fields: "
144 << this->NumberOfNodeFields << endl;
145 os << indent << "Number Of Node Components: "
146 << this->NumberOfNodeComponents << endl;
147
148 os << indent << "Number Of Cells: " << this->NumberOfCells << endl;
149 os << indent << "Number Of Cell Fields: "
150 << this->NumberOfCellFields << endl;
151 os << indent << "Number Of Cell Components: "
152 << this->NumberOfCellComponents << endl;
153
154 os << indent << "Byte Order: " << this->ByteOrder << endl;
155 os << indent << "Binary File: " << (this->BinaryFile ? "True\n" : "False\n");
156 os << indent << "Number of Fields: " << this->NumberOfFields << endl;
157 }
158
159
160 //----------------------------------------------------------------------------
ReadFile(vtkUnstructuredGrid * output)161 void vtkAVSucdReader::ReadFile(vtkUnstructuredGrid *output)
162 {
163 idMapping nodeMap, cellMap;
164
165 this->ReadGeometry(output, nodeMap, cellMap);
166
167 if(this->NumberOfNodeFields)
168 {
169 this->ReadNodeData(output, nodeMap);
170 }
171
172 if(this->NumberOfCellFields)
173 {
174 this->ReadCellData(output, cellMap);
175 }
176
177 delete this->FileStream;
178 this->FileStream = nullptr;
179 }
180
181
182 //----------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * vtkNotUsed (outputVector))183 int vtkAVSucdReader::RequestInformation(
184 vtkInformation *vtkNotUsed(request),
185 vtkInformationVector **vtkNotUsed(inputVector),
186 vtkInformationVector *vtkNotUsed(outputVector))
187 {
188 int i, j, k, *ncomp_list;
189
190 // first open file in binary mode to check the first byte.
191 if ( !this->FileName )
192 {
193 vtkErrorMacro("No filename specified");
194 return 0;
195 }
196
197 #ifdef _WIN32
198 this->FileStream = new ifstream(this->FileName, ios::in | ios::binary);
199 #else
200 this->FileStream = new ifstream(this->FileName, ios::in);
201 #endif
202 if (this->FileStream->fail())
203 {
204 this->SetErrorCode(vtkErrorCode::FileNotFoundError);
205 delete this->FileStream;
206 this->FileStream = nullptr;
207 vtkErrorMacro("Specified filename not found");
208 return 0;
209 }
210
211 char magic_number='\0';
212 this->FileStream->get(magic_number);
213 this->FileStream->putback(magic_number);
214 if(magic_number != 7)
215 { // most likely an ASCII file
216 this->BinaryFile = 0;
217 delete this->FileStream; // close file to reopen it later
218 this->FileStream = nullptr;
219
220 this->FileStream = new ifstream(this->FileName, ios::in);
221 char c='\0';
222 while (!FileStream->eof())
223 {
224 // skip leading whitespace
225 while(isspace(FileStream->peek()))
226 {
227 FileStream->get(c);
228 }
229 // skip comment lines
230 if (FileStream->peek() == '#')
231 {
232 while(this->FileStream->get(c))
233 {
234 if (c == '\n')
235 {
236 break;
237 }
238 }
239 }
240 else
241 {
242 break;
243 }
244 }
245
246 *(this->FileStream) >> this->NumberOfNodes;
247 *(this->FileStream) >> this->NumberOfCells;
248 *(this->FileStream) >> this->NumberOfNodeFields;
249 *(this->FileStream) >> this->NumberOfCellFields;
250 *(this->FileStream) >> this->NumberOfFields;
251 }
252 else
253 {
254 this->BinaryFile = 1;
255
256 // Here we first need to check if the file is little-endian or big-endian
257 // We will read the variables once, with the given endian-ness set up in
258 // the class constructor. If trueFileLength does not match
259 // calculatedFileLength, then we will toggle the endian-ness and re-swap
260 // the variables. We try at most twice, since there are only two endian-nesses.
261 this->FileStream->seekg(0L, ios::end);
262 vtkTypeUInt64 trueFileLength = this->FileStream->tellg();
263 vtkTypeUInt64 calculatedFileLength = 0; // not known yet
264
265 unsigned int attempts = 0;
266 while (attempts < 2)
267 {
268 // restart at beginning of file
269 this->FileStream->seekg(0L, ios::beg);
270
271 this->FileStream->read(&magic_number, 1);
272
273 this->ReadIntBlock(1, &this->NumberOfNodes);
274 this->ReadIntBlock(1, &this->NumberOfCells);
275 this->ReadIntBlock(1, &this->NumberOfNodeFields);
276 this->ReadIntBlock(1, &this->NumberOfCellFields);
277 this->ReadIntBlock(1, &this->NumberOfFields);
278 this->ReadIntBlock(1, &this->NlistNodes);
279
280 vtkDebugMacro( << this->NumberOfNodes << " "
281 << this->NumberOfCells << " "
282 << this->NumberOfNodeFields << " "
283 << this->NumberOfCellFields << " "
284 << this->NumberOfFields << " "
285 << this->NlistNodes << endl);
286
287 // If we've guessed the wrong endianness, these values will be nonsense,
288 // and the arithmetic below could easily caused (undefined) signed overflow,
289 // so convert everything into uint64.
290 vtkTypeUInt64 numNodes = this->NumberOfNodes;
291 vtkTypeUInt64 numCells = this->NumberOfCells;
292 vtkTypeUInt64 numNodeFields = this->NumberOfNodeFields;
293 vtkTypeUInt64 numCellFields = this->NumberOfCellFields;
294 vtkTypeUInt64 numFields = this->NumberOfFields;
295 vtkTypeUInt64 numListNodes = this->NlistNodes;
296
297 calculatedFileLength = 1 + 6*4;
298 calculatedFileLength += 16 * numCells + 4 * numListNodes;
299 calculatedFileLength += 3*4 * numNodes;
300 if(numNodeFields)
301 {
302 calculatedFileLength += 2052 + numNodeFields*(12 + 4 * numNodes + 4);
303 }
304
305 if(numCellFields)
306 {
307 calculatedFileLength += 2052 + numCellFields*(12 + 4 * numCells + 4);
308 }
309
310 if(numFields)
311 {
312 calculatedFileLength += 2052 + numFields*(4 * 5);
313 }
314
315 vtkDebugMacro( << "TFL = " << trueFileLength
316 << "\tCFL = " << calculatedFileLength << endl);
317
318 // We tried. Count our tries.
319 attempts++;
320
321 if(trueFileLength == calculatedFileLength)
322 {
323 // Endianness assumption was correct.
324 break;
325 }
326 else
327 {
328 // If the lengths don't match, then either:
329 // we tried the wrong endian-ness or the file is corrupt.
330 // Switch to opposite of what was previously set in constructor.
331 if(this->ByteOrder == FILE_LITTLE_ENDIAN)
332 {
333 this->ByteOrder = FILE_BIG_ENDIAN;
334 }
335 else if(this->ByteOrder == FILE_BIG_ENDIAN)
336 {
337 this->ByteOrder = FILE_LITTLE_ENDIAN;
338 }
339 }
340 } // end of while loop
341
342 if(trueFileLength != calculatedFileLength)
343 {
344 vtkErrorMacro("Calculated file length inconsistent with actual length; file corrupt?");
345 return 0;
346 }
347
348 const long base_offset = 1 + 6*4;
349 char buffer1[1024], buffer2[1024], label[32];
350
351 long offset = base_offset + 16 * this->NumberOfCells +
352 4 * this->NlistNodes + 3 * 4 * this->NumberOfNodes;
353
354 if(this->NumberOfNodeFields)
355 {
356 this->FileStream->seekg(offset,ios::beg);
357 this->FileStream->read(buffer1, sizeof(buffer1));
358 this->FileStream->read(buffer2, sizeof(buffer2)); // read 2nd array of 1024 bytes
359 this->ReadIntBlock(1, &this->NumberOfNodeComponents);
360
361 ncomp_list = new int[this->NumberOfNodeFields];
362 this->ReadIntBlock(this->NumberOfNodeFields, ncomp_list);
363
364 this->NodeDataInfo = new DataInfo[this->NumberOfNodeComponents];
365
366 float *mx = new float[this->NumberOfNodeFields];
367 // read now the minimums for node_data
368 this->ReadFloatBlock(this->NumberOfNodeFields, mx);
369 k=0;
370 for(i=0; i < this->NumberOfNodeComponents; i++)
371 {
372 for(j=0; j < ncomp_list[i]; j++)
373 {
374 this->NodeDataInfo[i].min[j] = mx[k];
375 }
376 k++;
377 }
378 // read now the maximums for node_data
379 this->ReadFloatBlock(this->NumberOfNodeFields, mx);
380 k=0;
381 for(i=0; i < this->NumberOfNodeComponents; i++)
382 {
383 for(j=0; j < ncomp_list[i]; j++)
384 {
385 this->NodeDataInfo[i].max[j] = mx[k];
386 }
387 k++;
388 }
389 delete [] mx;
390
391 offset += 1024 + 1024 + 4 + 3 * 4 * this->NumberOfNodeFields;
392
393 k = 0;
394 for(i=0; i < this->NumberOfNodeComponents; i++)
395 {
396 this->GetLabel(buffer1, i, label);
397 vtkDebugMacro( << i+1 << " :found ND label = " << label
398 << " [" << ncomp_list[i] << "]" <<endl);
399 this->PointDataArraySelection->AddArray(label);
400 this->NodeDataInfo[i].foffset = offset + k * 4 * this->NumberOfNodes;
401 this->NodeDataInfo[i].veclen = ncomp_list[i];
402 k += ncomp_list[i];
403 }
404 delete [] ncomp_list;
405 }
406
407 if(this->NumberOfCellFields)
408 {
409 offset += 4 * this->NumberOfNodes * this->NumberOfNodeFields +
410 4 * this->NumberOfNodeFields;
411 this->FileStream->seekg(offset,ios::beg);
412 this->FileStream->read(buffer1, sizeof(buffer1));
413
414 this->FileStream->read(buffer2, sizeof(buffer2)); // read 2nd array of 1024 bytes
415 this->ReadIntBlock(1, &this->NumberOfCellComponents);
416
417 ncomp_list = new int[this->NumberOfCellFields];
418 this->ReadIntBlock(this->NumberOfCellFields, ncomp_list);
419
420 this->CellDataInfo = new DataInfo[this->NumberOfCellComponents];
421
422 float *mx = new float[this->NumberOfCellFields];
423 // read now the minimums for cell_data
424 this->ReadFloatBlock(this->NumberOfCellFields, mx);
425 k=0;
426 for(i=0; i < this->NumberOfCellFields; i++)
427 {
428 for(j=0; j < ncomp_list[i]; j++)
429 {
430 this->CellDataInfo[i].min[j] = mx[k];
431 };
432 k++;
433 }
434 // read now the maximums for cell_data
435 this->ReadFloatBlock(this->NumberOfCellFields, mx);
436 k=0;
437 for(i=0; i < this->NumberOfCellFields; i++)
438 {
439 for(j=0; j < ncomp_list[i]; j++)
440 {
441 this->CellDataInfo[i].max[j] = mx[k];
442 }
443 k++;
444 }
445 delete [] mx;
446
447 offset += 1024 + 1024 + 4 + 3 * 4 * this->NumberOfCellFields;
448
449 k = 0;
450 for(i=0; i < this->NumberOfCellComponents; i++)
451 {
452 this->GetLabel(buffer1, i, label);
453 vtkDebugMacro( << i+1 << " :found CD label = " << label << " ["
454 << ncomp_list[i] << "]" << endl);
455 this->CellDataArraySelection->AddArray(label);
456 this->CellDataInfo[i].foffset = offset + k * 4 * this->NumberOfCells;
457 this->CellDataInfo[i].veclen = ncomp_list[i];
458 k += ncomp_list[i];
459 }
460 delete [] ncomp_list;
461 }
462
463 if(this->NumberOfFields)
464 {
465 offset += 4 * this->NumberOfCells * this->NumberOfCellFields +
466 4 * this->NumberOfCellFields;
467 this->FileStream->seekg(offset,ios::beg);
468 this->FileStream->read(buffer1, sizeof(buffer1));
469 vtkDebugMacro(<< buffer1 << endl);
470
471 //offset += 1024 + 1024 + 4 + 3 * 4 * this->NumberOfFields;
472
473 for(i=0; i < this->NumberOfFields; i++)
474 {
475 this->GetLabel(buffer1, i, label);
476 vtkDebugMacro( << "found MD label = " << label << endl);
477 }
478 }
479 } // end of Binary part
480 for(i=0; i < this->NumberOfNodeComponents; i++)
481 {
482 vtkDebugMacro( << endl << this->PointDataArraySelection->GetArrayName(i)
483 << endl
484 << "offset = " << this->NodeDataInfo[i].foffset << endl
485 << "load = " << this->PointDataArraySelection->GetArraySetting(i) << endl
486 << "veclen = " << this->NodeDataInfo[i].veclen);
487 }
488
489 for(i=0; i < this->NumberOfCellComponents; i++)
490 {
491 vtkDebugMacro( << endl << this->CellDataArraySelection->GetArrayName(i)
492 << endl
493 << "offset = " << this->CellDataInfo[i].foffset << endl
494 << "load = " << this->CellDataArraySelection->GetArraySetting(i) << endl
495 << "veclen = " << this->CellDataInfo[i].veclen);
496 }
497
498 vtkDebugMacro( << "end of ExecuteInformation\n");
499
500 return 1;
501 }
502
503 //----------------------------------------------------------------------------
GetCellDataRange(int cellComp,int index,float * min,float * max)504 void vtkAVSucdReader::GetCellDataRange(int cellComp, int index, float *min, float *max)
505 {
506 if (index >= this->CellDataInfo[cellComp].veclen || index < 0)
507 {
508 index = 0; // if wrong index, set it to zero
509 }
510 *min = this->CellDataInfo[cellComp].min[index];
511 *max = this->CellDataInfo[cellComp].max[index];
512 }
513
514 //----------------------------------------------------------------------------
GetNodeDataRange(int nodeComp,int index,float * min,float * max)515 void vtkAVSucdReader::GetNodeDataRange(int nodeComp, int index, float *min, float *max)
516 {
517 if (index >= this->NodeDataInfo[nodeComp].veclen || index < 0)
518 {
519 index = 0; // if wrong index, set it to zero
520 }
521 *min = this->NodeDataInfo[nodeComp].min[index];
522 *max = this->NodeDataInfo[nodeComp].max[index];
523 }
524
525 //----------------------------------------------------------------------------
ReadGeometry(vtkUnstructuredGrid * output,idMapping & nodeMap,idMapping & cellMap)526 void vtkAVSucdReader::ReadGeometry(vtkUnstructuredGrid *output,
527 idMapping& nodeMap,
528 idMapping& cellMap)
529 {
530 // add a material array
531 vtkIntArray *materials = vtkIntArray::New();
532 materials->SetNumberOfTuples(this->NumberOfCells);
533 materials->SetName("Material Id");
534
535 vtkFloatArray *coords = vtkFloatArray::New();
536 coords->SetNumberOfComponents(3);
537 coords->SetNumberOfTuples(this->NumberOfNodes);
538
539 if (this->BinaryFile)
540 {
541 int *types = new int[this->NumberOfCells];
542 if(types == nullptr)
543 {
544 vtkErrorMacro(<< "Error allocating types memory\n");
545 }
546
547 vtkIdTypeArray *listcells = vtkIdTypeArray::New();
548 // this array contains a list of NumberOfCells tuples
549 // each tuple is 1 integer, i.e. the number of indices following it (N)
550 // followed by these N integers
551 listcells->SetNumberOfValues(this->NumberOfCells + this->NlistNodes);
552
553 this->ReadBinaryCellTopology(materials, types, listcells);
554 this->ReadXYZCoords(coords, nodeMap);
555
556 vtkCellArray *cells = vtkCellArray::New();
557 cells->SetCells(this->NumberOfCells, listcells);
558 listcells->Delete();
559
560 output->SetCells(types, cells);
561 cells->Delete();
562 delete [] types;
563 }
564 else
565 {
566 this->ReadXYZCoords(coords, nodeMap);
567 this->ReadASCIICellTopology(materials, output, nodeMap, cellMap);
568 }
569
570 vtkPoints *points = vtkPoints::New();
571 points->SetData(coords);
572 coords->Delete();
573
574 output->SetPoints(points);
575 points->Delete();
576
577 // now add the material array
578 output->GetCellData()->AddArray(materials);
579 if (!output->GetCellData()->GetScalars())
580 {
581 output->GetCellData()->SetScalars(materials);
582 }
583 materials->Delete();
584 }
585
586
587 //----------------------------------------------------------------------------
ReadBinaryCellTopology(vtkIntArray * materials,int * types,vtkIdTypeArray * listcells)588 void vtkAVSucdReader::ReadBinaryCellTopology(vtkIntArray *materials,
589 int *types,
590 vtkIdTypeArray *listcells)
591 {
592 int i, j, k2=0;
593 int *mat = materials->GetPointer(0);
594 vtkIdType *list = listcells->GetPointer(0);
595 int *ctype = new int[4 * this->NumberOfCells];
596 if(ctype == nullptr)
597 {
598 vtkErrorMacro(<< "Error allocating ctype memory");
599 return;
600 }
601
602 this->FileStream->seekg(6*4 + 1,ios::beg);
603 this->ReadIntBlock(4 * this->NumberOfCells, ctype);
604
605 int *topology_list = new int[this->NlistNodes];
606 if(topology_list == nullptr)
607 {
608 vtkErrorMacro(<< "Error allocating topology_list memory");
609 return;
610 }
611
612 this->ReadIntBlock(this->NlistNodes, topology_list);
613 this->UpdateProgress(0.25);
614
615 for(i=0; i < this->NumberOfCells; i++)
616 {
617 *list++ = ctype[4*i+2];
618 if(ctype[4*i+3] == vtkAVSucdReader::PYR)
619 { //UCD ordering is 0,1,2,3,4 => VTK ordering is 1,2,3,4,0
620 *list++ = topology_list[++k2] - 1;
621 *list++ = topology_list[++k2] - 1;
622 *list++ = topology_list[++k2] - 1;
623 *list++ = topology_list[++k2] - 1;
624 *list++ = topology_list[k2-4] - 1;
625 k2++;
626 }
627 else
628 {
629 for(j=0; j < ctype[4*i+2]; j++)
630 {
631 *list++ = topology_list[k2++] - 1;
632 }
633 }
634 }
635
636 delete [] topology_list;
637
638 for(i=0; i < this->NumberOfCells; i++)
639 {
640 *mat++ = ctype[4*i+1];
641 switch(ctype[4*i+3])
642 {
643 case vtkAVSucdReader::PT: types[i] = VTK_VERTEX; break;
644 case vtkAVSucdReader::LINE: types[i] = VTK_LINE; break;
645 case vtkAVSucdReader::TRI: types[i] = VTK_TRIANGLE; break;
646 case vtkAVSucdReader::QUAD: types[i] = VTK_QUAD; break;
647 case vtkAVSucdReader::TET: types[i] = VTK_TETRA; break;
648 case vtkAVSucdReader::PYR: types[i] = VTK_PYRAMID; break;
649 case vtkAVSucdReader::PRISM: types[i] = VTK_WEDGE; break;
650 case vtkAVSucdReader::HEX: types[i] = VTK_HEXAHEDRON; break;
651 default:
652 vtkErrorMacro( << "cell type: " << ctype[4*i+3] << "not supported\n");
653 delete [] ctype;
654 return;
655 }
656 }
657 delete [] ctype;
658 }
659
660
661 //----------------------------------------------------------------------------
ReadASCIICellTopology(vtkIntArray * materials,vtkUnstructuredGrid * output,const idMapping & nodeMap,idMapping & cellMap)662 void vtkAVSucdReader::ReadASCIICellTopology(vtkIntArray *materials,
663 vtkUnstructuredGrid *output,
664 const idMapping& nodeMap,
665 idMapping& cellMap)
666 {
667 int i, k;
668 vtkIdType list[8];
669 int *mat = materials->GetPointer(0);
670 std::string ctype;
671
672 output->Allocate();
673 for(i=0; i < this->NumberOfCells; i++)
674 {
675 vtkIdType id;
676 *(this->FileStream) >> id;
677 cellMap.insert(std::make_pair(id, static_cast<vtkIdType>(i)));
678 *(this->FileStream) >> mat[i];
679 *(this->FileStream) >> ctype;
680 vtkDebugMacro( << mat[i] << ", " << ctype );
681 if(ctype == "pt")
682 {
683 for(k=0; k < 1; k++)
684 {
685 *(this->FileStream) >> id;
686 list[k] = nodeMap.find(id)->second;
687 }
688 output->InsertNextCell(VTK_VERTEX, 1, list);
689 }
690 else if(ctype == "line")
691 {
692 for(k=0; k < 2; k++)
693 {
694 *(this->FileStream) >> id;
695 list[k] = nodeMap.find(id)->second;
696 }
697 output->InsertNextCell(VTK_LINE, 2, list);
698 }
699 else if(ctype == "tri")
700 {
701 for(k=0; k < 3; k++)
702 {
703 *(this->FileStream) >> id;
704 list[k] = nodeMap.find(id)->second;
705 }
706 output->InsertNextCell(VTK_TRIANGLE, 3, list);
707 }
708 else if(ctype == "quad")
709 {
710 for(k=0; k < 4; k++)
711 {
712 *(this->FileStream) >> id;
713 list[k] = nodeMap.find(id)->second;
714 }
715 output->InsertNextCell(VTK_QUAD, 4, list);
716 }
717 else if(ctype == "tet")
718 {
719 for(k=0; k < 4; k++)
720 {
721 *(this->FileStream) >> id;
722 list[k] = nodeMap.find(id)->second;
723 }
724 output->InsertNextCell(VTK_TETRA, 4, list);
725 }
726 else if(ctype == "pyr")
727 {
728 for(k=0; k < 5; k++)
729 {
730 *(this->FileStream) >> id;
731 list[k] = nodeMap.find(id)->second;
732 }
733 int tmp;
734 tmp = list[0];
735 list[0] = list[1]; list[1] = list[2]; list[2] = list[3];
736 list[3] = list[4]; list[4] = tmp;
737 output->InsertNextCell(VTK_PYRAMID, 5, list);
738 }
739 else if(ctype == "prism")
740 {
741 for(k=0; k < 6; k++)
742 {
743 *(this->FileStream) >> id;
744 list[k] = nodeMap.find(id)->second;
745 }
746 output->InsertNextCell(VTK_WEDGE, 6, list);
747 }
748 else if(ctype == "hex")
749 {
750 for(k=0; k < 8; k++)
751 {
752 *(this->FileStream) >> id;
753 list[k] = nodeMap.find(id)->second;
754 }
755 output->InsertNextCell(VTK_HEXAHEDRON, 8, list);
756 }
757 else
758 {
759 vtkErrorMacro( << "cell type: " << ctype << " is not supported\n");
760 return;
761 }
762 } // for all cell, read the indices
763 }
764
765
766 //----------------------------------------------------------------------------
ReadXYZCoords(vtkFloatArray * coords,idMapping & nodeMap)767 void vtkAVSucdReader::ReadXYZCoords(vtkFloatArray *coords, idMapping& nodeMap)
768 {
769 int i;
770 float *ptr = coords->GetPointer(0);
771 if (this->BinaryFile)
772 {
773 float *cs = new float[this->NumberOfNodes];
774
775 // read X coordinates from file and stuff into coordinates array
776 this->ReadFloatBlock(this->NumberOfNodes, cs);
777 for(i=0; i < this->NumberOfNodes; i++)
778 {
779 ptr[3*i] = cs[i];
780 }
781
782 // read Y coordinates from file and stuff into coordinates array
783 this->ReadFloatBlock(this->NumberOfNodes, cs);
784 for(i=0; i < this->NumberOfNodes; i++)
785 {
786 ptr[3*i+1] = cs[i];
787 }
788
789 // read Z coordinates from file and stuff into coordinates array
790 this->ReadFloatBlock(this->NumberOfNodes, cs);
791 for(i=0; i < this->NumberOfNodes; i++)
792 {
793 ptr[3*i+2] = cs[i];
794 }
795 // end of stuffing all coordinates
796 delete [] cs;
797 } // end of binary read
798 else
799 {
800 vtkIdType id;
801 for(i=0; i < this->NumberOfNodes; i++)
802 {
803 *(this->FileStream) >> id;
804 *(this->FileStream) >> ptr[3*i] >> ptr[3*i+1] >> ptr[3*i+2];
805 nodeMap.insert(std::make_pair(id, static_cast<vtkIdType>(i)));
806 }
807 } // end of ASCII read
808 }
809
810
811 //----------------------------------------------------------------------------
ReadNodeData(vtkUnstructuredGrid * output,const idMapping & nodeMap)812 void vtkAVSucdReader::ReadNodeData(vtkUnstructuredGrid *output,
813 const idMapping& nodeMap)
814 {
815 int i, j, n;
816 float *ptr;
817 vtkDebugMacro( << "Begin of ReadNodeData()\n");
818 if(this->BinaryFile)
819 {
820 for (i=0; i < this->NumberOfNodeComponents; i++)
821 {
822 if(this->PointDataArraySelection->GetArraySetting(i))
823 {
824 vtkFloatArray *scalars = vtkFloatArray::New();
825 scalars->SetNumberOfComponents(this->NodeDataInfo[i].veclen);
826 scalars->SetNumberOfTuples(this->NumberOfNodes);
827 scalars->SetName(PointDataArraySelection->GetArrayName(i));
828 this->FileStream->seekg(this->NodeDataInfo[i].foffset, ios::beg);
829 ptr = scalars->GetPointer(0);
830 this->ReadFloatBlock(this->NumberOfNodes *
831 this->NodeDataInfo[i].veclen, ptr);
832
833 output->GetPointData()->AddArray(scalars);
834 if (!output->GetPointData()->GetScalars())
835 {
836 output->GetPointData()->SetScalars(scalars);
837 }
838 scalars->Delete();
839 }
840 }
841 //
842 // Don't know how to use the information below, so skip reading it
843 // int *node_active_list = new int[this->NumberOfNodeFields];
844 // this->ReadIntArray(node_active_list, this->NumberOfNodeFields);
845 // delete [] node_active_list;
846 //
847 } // end of binary read
848 else
849 {
850 float value;
851 char buf1[128], c='\0', buf2[128];
852
853 *(this->FileStream) >> this->NumberOfNodeComponents;
854 this->NodeDataInfo = new DataInfo[this->NumberOfNodeComponents];
855 for(i=0; i < this->NumberOfNodeComponents; i++)
856 {
857 *(this->FileStream) >> this->NodeDataInfo[i].veclen;
858 }
859 this->FileStream->get(c); // one more newline to catch
860
861 vtkFloatArray **scalars = new
862 vtkFloatArray * [this->NumberOfNodeComponents];
863 for(i=0; i < this->NumberOfNodeComponents; i++)
864 {
865 j=0;
866 while(this->FileStream->get(c) && c != ',')
867 {
868 buf1[j++] = c;
869 }
870 buf1[j] = '\0';
871 // finish here to read the line
872 this->FileStream->get(buf2, 128, '\n'); this->FileStream->get(c);
873
874 scalars[i] = vtkFloatArray::New();
875 scalars[i]->SetNumberOfComponents(this->NodeDataInfo[i].veclen);
876 scalars[i]->SetNumberOfTuples(this->NumberOfNodes);
877 scalars[i]->SetName(buf1);
878 }
879 for(n=0; n < this->NumberOfNodes; n++)
880 {
881 vtkIdType id;
882 *(this->FileStream) >> id;
883 id = nodeMap.find(id)->second;
884 for(i=0; i < this->NumberOfNodeComponents; i++)
885 {
886 for(j=0; j < this->NodeDataInfo[i].veclen; j++)
887 {
888 *(this->FileStream) >> value;
889 scalars[i]->SetComponent(id, j, value);
890 }
891 }
892 }
893 for(i=0; i < this->NumberOfNodeComponents; i++)
894 {
895 output->GetPointData()->AddArray(scalars[i]);
896 if (!output->GetPointData()->GetScalars())
897 {
898 output->GetPointData()->SetScalars(scalars[i]);
899 }
900 scalars[i]->Delete();
901 }
902 delete[] scalars;
903 } // end of ASCII read
904 vtkDebugMacro( << "End of ReadNodeData()\n");
905 }
906
907
908 //----------------------------------------------------------------------------
ReadCellData(vtkUnstructuredGrid * output,const idMapping & cellMap)909 void vtkAVSucdReader::ReadCellData(vtkUnstructuredGrid *output,
910 const idMapping& cellMap)
911 {
912 int i, j, n;
913 float *ptr;
914 vtkDebugMacro( << "Begin of ReadCellData()\n");
915 if(this->BinaryFile)
916 {
917 for (i=0; i < this->NumberOfCellComponents; i++)
918 {
919 if(this->CellDataArraySelection->GetArraySetting(i))
920 {
921 vtkFloatArray *scalars = vtkFloatArray::New();
922 scalars->SetNumberOfComponents(this->CellDataInfo[i].veclen);
923 scalars->SetNumberOfTuples(this->NumberOfCells);
924 scalars->SetName(CellDataArraySelection->GetArrayName(i));
925 this->FileStream->seekg(this->CellDataInfo[i].foffset, ios::beg);
926 ptr = scalars->GetPointer(0);
927 this->ReadFloatBlock(this->NumberOfCells *
928 this->CellDataInfo[i].veclen, ptr);
929
930 output->GetCellData()->AddArray(scalars);
931 if (!output->GetCellData()->GetScalars())
932 {
933 output->GetCellData()->SetScalars(scalars);
934 }
935 scalars->Delete();
936 }
937 }
938 } // end of binary read
939 else
940 {
941 float value;
942 char buf1[128], c='\0', buf2[128];
943
944 *(this->FileStream) >> this->NumberOfCellComponents;
945 this->CellDataInfo = new DataInfo[this->NumberOfCellComponents];
946
947 for(i=0; i < this->NumberOfCellComponents; i++)
948 {
949 *(this->FileStream) >> this->CellDataInfo[i].veclen;
950 }
951 this->FileStream->get(c); // one more newline to catch
952
953 vtkFloatArray **scalars = new
954 vtkFloatArray * [this->NumberOfCellComponents];
955 for(i=0; i < this->NumberOfCellComponents; i++)
956 {
957 j=0;
958 while(this->FileStream->get(c) && c != ',')
959 {
960 buf1[j++] = c;
961 }
962 buf1[j] = '\0';
963 // finish here to read the line
964 this->FileStream->get(buf2, 128, '\n'); this->FileStream->get(c);
965
966 scalars[i] = vtkFloatArray::New();
967 scalars[i]->SetNumberOfComponents(this->CellDataInfo[i].veclen);
968 scalars[i]->SetNumberOfTuples(this->NumberOfCells);
969 scalars[i]->SetName(buf1);
970 }
971 for(n=0; n < this->NumberOfCells; n++)
972 {
973 vtkIdType id;
974 *(this->FileStream) >> id;
975 id = cellMap.find(id)->second;
976 for(i=0; i < this->NumberOfCellComponents; i++)
977 {
978 for(j=0; j < this->CellDataInfo[i].veclen; j++)
979 {
980 *(this->FileStream) >> value;
981 scalars[i]->SetComponent(id, j, value);
982 }
983 }
984 }
985 for(i=0; i < this->NumberOfCellComponents; i++)
986 {
987 output->GetCellData()->AddArray(scalars[i]);
988 if (!output->GetCellData()->GetScalars())
989 {
990 output->GetCellData()->SetScalars(scalars[i]);
991 }
992 scalars[i]->Delete();
993 }
994 delete[] scalars;
995 } // end of ASCII read
996 vtkDebugMacro( << "End of ReadCellData()\n");
997 }
998
999 //----------------------------------------------------------------------------
GetPointArrayName(int index)1000 const char* vtkAVSucdReader::GetPointArrayName(int index)
1001 {
1002 return this->PointDataArraySelection->GetArrayName(index);
1003 }
1004
1005 //----------------------------------------------------------------------------
GetPointArrayStatus(const char * name)1006 int vtkAVSucdReader::GetPointArrayStatus(const char* name)
1007 {
1008 return this->PointDataArraySelection->ArrayIsEnabled(name);
1009 }
1010
1011 //----------------------------------------------------------------------------
SetPointArrayStatus(const char * name,int status)1012 void vtkAVSucdReader::SetPointArrayStatus(const char* name, int status)
1013 {
1014 if(status)
1015 {
1016 this->PointDataArraySelection->EnableArray(name);
1017 }
1018 else
1019 {
1020 this->PointDataArraySelection->DisableArray(name);
1021 }
1022 }
1023
1024 //----------------------------------------------------------------------------
GetCellArrayName(int index)1025 const char* vtkAVSucdReader::GetCellArrayName(int index)
1026 {
1027 return this->CellDataArraySelection->GetArrayName(index);
1028 }
1029
1030 //----------------------------------------------------------------------------
GetCellArrayStatus(const char * name)1031 int vtkAVSucdReader::GetCellArrayStatus(const char* name)
1032 {
1033 return this->CellDataArraySelection->ArrayIsEnabled(name);
1034 }
1035
1036
1037 //----------------------------------------------------------------------------
SetCellArrayStatus(const char * name,int status)1038 void vtkAVSucdReader::SetCellArrayStatus(const char* name, int status)
1039 {
1040 if(status)
1041 {
1042 this->CellDataArraySelection->EnableArray(name);
1043 }
1044 else
1045 {
1046 this->CellDataArraySelection->DisableArray(name);
1047 }
1048 }
1049
1050 //----------------------------------------------------------------------------
GetNumberOfCellArrays()1051 int vtkAVSucdReader::GetNumberOfCellArrays()
1052 {
1053 return this->CellDataArraySelection->GetNumberOfArrays();
1054 }
1055
1056 //----------------------------------------------------------------------------
GetNumberOfPointArrays()1057 int vtkAVSucdReader::GetNumberOfPointArrays()
1058 {
1059 return this->PointDataArraySelection->GetNumberOfArrays();
1060 }
1061
1062 //----------------------------------------------------------------------------
EnableAllPointArrays()1063 void vtkAVSucdReader::EnableAllPointArrays()
1064 {
1065 this->PointDataArraySelection->EnableAllArrays();
1066 }
1067
1068 //----------------------------------------------------------------------------
DisableAllPointArrays()1069 void vtkAVSucdReader::DisableAllPointArrays()
1070 {
1071 this->PointDataArraySelection->DisableAllArrays();
1072 }
1073
1074 //----------------------------------------------------------------------------
EnableAllCellArrays()1075 void vtkAVSucdReader::EnableAllCellArrays()
1076 {
1077 this->CellDataArraySelection->EnableAllArrays();
1078 }
1079
1080 //----------------------------------------------------------------------------
DisableAllCellArrays()1081 void vtkAVSucdReader::DisableAllCellArrays()
1082 {
1083 this->CellDataArraySelection->DisableAllArrays();
1084 }
1085
1086 //----------------------------------------------------------------------------
GetLabel(char * string,int number,char * label)1087 int vtkAVSucdReader::GetLabel(char *string, int number, char *label)
1088 {
1089 int i, j, k, len;
1090 char current;
1091
1092
1093 // check to make sure that structure is not nullptr
1094 if (string == nullptr)
1095 {
1096 vtkErrorMacro( << "String is null");
1097 return 0;
1098 }
1099
1100 // search for the appropriate label
1101 k = 0;
1102 len = static_cast<int>(strlen(string));
1103 for(i = 0; i <= number; i++)
1104 {
1105 current = string[k++];
1106 j = 0;
1107 while (current != '.')
1108 {
1109 // build the label character by character
1110 label[j++] = current;
1111 current = string[k++];
1112
1113 // the last character was found
1114 if (k > len)
1115 {
1116 // the nth label was not found, where n = number
1117 if (i < number)
1118 {
1119 return 0;
1120 }
1121 current = '.';
1122 }
1123 } // end while
1124 label[j] = '\0';
1125 }
1126 // a valid label was found
1127 return 1;
1128 }
1129
1130
1131 //----------------------------------------------------------------------------
1132 // Read a block of ints (ascii or binary) and return number read.
ReadIntBlock(int n,int * block)1133 int vtkAVSucdReader::ReadIntBlock(int n, int *block)
1134 {
1135 if (this->BinaryFile)
1136 {
1137 this->FileStream->read((char *)block, n * sizeof(int));
1138 int retVal = static_cast<int>(this->FileStream->gcount()) / sizeof(int);
1139
1140 if (this->ByteOrder == FILE_LITTLE_ENDIAN)
1141 {
1142 vtkByteSwap::Swap4LERange(block, n);
1143 }
1144 else
1145 {
1146 vtkByteSwap::Swap4BERange(block, n);
1147 }
1148 return retVal;
1149 }
1150 else
1151 {
1152 int count = 0;
1153 for(int i=0; i<n; i++)
1154 {
1155 if (*(this->FileStream) >> block[i])
1156 {
1157 count++;
1158 }
1159 else
1160 {
1161 return 0;
1162 }
1163 }
1164 return count;
1165 }
1166 }
1167
1168 //----------------------------------------------------------------------------
ReadFloatBlock(int n,float * block)1169 int vtkAVSucdReader::ReadFloatBlock(int n, float* block)
1170 {
1171 if (this->BinaryFile)
1172 {
1173 this->FileStream->read((char *)block, n * sizeof(float));
1174 int retVal = static_cast<int>(this->FileStream->gcount()) / sizeof(int);
1175 if (this->ByteOrder == FILE_LITTLE_ENDIAN)
1176 {
1177 vtkByteSwap::Swap4LERange(block, n);
1178 }
1179 else
1180 {
1181 vtkByteSwap::Swap4BERange(block, n);
1182 }
1183 return retVal;
1184 }
1185 else
1186 {
1187 int count = 0;
1188 for(int i=0; i<n; i++)
1189 {
1190 if (*(this->FileStream) >> block[i])
1191 {
1192 count++;
1193 }
1194 else
1195 {
1196 return 0;
1197 }
1198 }
1199 return count;
1200 }
1201 }
1202