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