1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkEnSightGoldBinaryReader.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 #include "vtkEnSightGoldBinaryReader.h"
16 
17 #include "vtkByteSwap.h"
18 #include "vtkCellData.h"
19 #include "vtkCharArray.h"
20 #include "vtkFloatArray.h"
21 #include "vtkMultiBlockDataSet.h"
22 #include "vtkIdList.h"
23 #include "vtkImageData.h"
24 #include "vtkObjectFactory.h"
25 #include "vtkPointData.h"
26 #include "vtkPolyData.h"
27 #include "vtkRectilinearGrid.h"
28 #include "vtkStructuredGrid.h"
29 #include "vtkUnstructuredGrid.h"
30 
31 #include <sys/stat.h>
32 #include <cctype>
33 #include <string>
34 #include <vector>
35 #include <map>
36 
37 #if defined(_WIN32)
38 # define VTK_STAT_STRUCT struct _stat64
39 # define VTK_STAT_FUNC _stat64
40 #elif defined _DARWIN_FEATURE_64_BIT_INODE || (defined __FreeBSD__||defined(__DragonFly__))
41 // FreeBSD and OSX use stat
42 # define VTK_STAT_STRUCT struct stat
43 # define VTK_STAT_FUNC stat
44 #else
45 // here, we're relying on _FILE_OFFSET_BITS defined in vtkWin32Header.h to help
46 // us on POSIX without resorting to using stat64.
47 # define VTK_STAT_STRUCT struct stat64
48 # define VTK_STAT_FUNC stat64
49 #endif
50 
51 vtkStandardNewMacro(vtkEnSightGoldBinaryReader);
52 class vtkEnSightGoldBinaryReader::FileOffsetMapInternal
53 {
54   typedef std::string MapKey;
55   typedef std::map<int,vtkTypeInt64> MapValue;
56   public:
57     typedef std::map<MapKey, MapValue>::const_iterator const_iterator;
58     typedef std::map<MapKey, MapValue>::value_type value_type;
59 
60     std::map<MapKey, MapValue> Map;
61 };
62 
63 // This is half the precision of an int.
64 #define MAXIMUM_PART_ID 65536
65 
66 //----------------------------------------------------------------------------
vtkEnSightGoldBinaryReader()67 vtkEnSightGoldBinaryReader::vtkEnSightGoldBinaryReader()
68 {
69   this->FileOffsets = new vtkEnSightGoldBinaryReader::FileOffsetMapInternal;
70 
71   this->GoldIFile = nullptr;
72   this->FileSize = 0;
73   this->SizeOfInt = sizeof(int);
74   this->Fortran = 0;
75   this->NodeIdsListed = 0;
76   this->ElementIdsListed = 0;
77 }
78 
79 //----------------------------------------------------------------------------
~vtkEnSightGoldBinaryReader()80 vtkEnSightGoldBinaryReader::~vtkEnSightGoldBinaryReader()
81 {
82   delete this->FileOffsets;
83 
84   if (this->GoldIFile)
85   {
86     this->GoldIFile->close();
87     delete this->GoldIFile;
88     this->GoldIFile = nullptr;
89   }
90 }
91 
92 //----------------------------------------------------------------------------
OpenFile(const char * filename)93 int vtkEnSightGoldBinaryReader::OpenFile(const char* filename)
94 {
95   if (!filename)
96   {
97     vtkErrorMacro(<<"Missing filename.");
98     return 0;
99   }
100 
101   // Close file from any previous image
102   if (this->GoldIFile)
103   {
104     this->GoldIFile->close();
105     delete this->GoldIFile;
106     this->GoldIFile = nullptr;
107   }
108 
109   // Open the new file
110   vtkDebugMacro(<< "Opening file " << filename);
111   VTK_STAT_STRUCT fs;
112   if ( !VTK_STAT_FUNC( filename, &fs) )
113   {
114     // Find out how big the file is.
115     this->FileSize = static_cast<vtkTypeUInt64>(fs.st_size);
116 
117 #ifdef _WIN32
118     this->GoldIFile = new ifstream(filename, ios::in | ios::binary);
119 #else
120     this->GoldIFile = new ifstream(filename, ios::in);
121 #endif
122   }
123   else
124   {
125     vtkErrorMacro("stat failed.");
126     return 0;
127   }
128   if (! this->GoldIFile || this->GoldIFile->fail())
129   {
130     vtkErrorMacro(<< "Could not open file " << filename);
131     return 0;
132   }
133 
134   //we now need to check for Fortran and byte ordering
135 
136   //we need to look at the first 4 bytes of the file, and the 84-87 bytes
137   //of the file to correctly determine what it is. If we only check the first
138   //4 bytes we can get incorrect detection if it is a property file named "P"
139   //we check the 84-87 bytes as that is the start of the next line on a fortran file
140 
141   char result[88];
142   this->GoldIFile->read(result, 88);
143   if ( this->GoldIFile->eof() || this->GoldIFile->fail() )
144   {
145     vtkErrorMacro(<<filename << " is missing header information");
146     return 0;
147   }
148   this->GoldIFile->seekg (0, ios::beg);  //reset the file to the start
149 
150   // if the first 4 bytes is the length, then this data is no doubt
151   // a fortran data write!, copy the last 76 into the beginning
152   char le_len[4] = {0x50, 0x00, 0x00, 0x00};
153   char be_len[4] = {0x00, 0x00, 0x00, 0x50};
154 
155   // the fortran test here depends on the byte ordering. But if the user didn't
156   // set any byte ordering then, we have to try both byte orderings. There was a
157   // bug here which was resulting in binary-fortran-big-endian files being read
158   // incorrectly on intel machines (BUG #10593). This dual-check avoids that
159   // bug.
160   bool le_isFortran = true;
161   bool be_isFortran = true;
162   for (int c=0; c<4; c++)
163   {
164     le_isFortran = le_isFortran && (result[c] == le_len[c])
165       && (result[c+84] == le_len[c]);
166     be_isFortran = be_isFortran && (result[c] == be_len[c])
167       && (result[c+84] == be_len[c]);
168   }
169 
170   switch (this->ByteOrder)
171   {
172   case FILE_BIG_ENDIAN:
173     this->Fortran = be_isFortran;
174     break;
175 
176   case FILE_LITTLE_ENDIAN:
177     this->Fortran = le_isFortran;
178     break;
179 
180   case FILE_UNKNOWN_ENDIAN:
181     if (le_isFortran)
182     {
183       this->Fortran = true;
184       this->ByteOrder = FILE_LITTLE_ENDIAN;
185     }
186     else if (be_isFortran)
187     {
188       this->Fortran = true;
189       this->ByteOrder = FILE_BIG_ENDIAN;
190     }
191     else
192     {
193       this->Fortran = false;
194     }
195     break;
196   }
197   return 1;
198 }
199 
200 //----------------------------------------------------------------------------
InitializeFile(const char * fileName)201 int vtkEnSightGoldBinaryReader::InitializeFile(const char* fileName)
202 {
203   char line[80], subLine[80];
204 
205   // Initialize
206   //
207   if (!fileName)
208   {
209     vtkErrorMacro("A GeometryFileName must be specified in the case file.");
210     return 0;
211   }
212   std::string sfilename;
213   if (this->FilePath)
214   {
215     sfilename = this->FilePath;
216     if (sfilename.at(sfilename.length()-1) != '/')
217     {
218       sfilename += "/";
219     }
220     sfilename += fileName;
221     vtkDebugMacro("full path to geometry file: " << sfilename.c_str());
222   }
223   else
224   {
225     sfilename = fileName;
226   }
227 
228   if (this->OpenFile(sfilename.c_str()) == 0)
229   {
230     vtkErrorMacro("Unable to open file: " << sfilename.c_str());
231     return 0;
232   }
233 
234   line[0] = '\0';
235   subLine[0] = '\0';
236   if ( this->ReadLine( line ) == 0 )
237   {
238     vtkErrorMacro( "Error with line reading upon file initialization" );
239     return 0;
240   }
241 
242   if ( sscanf( line, " %*s %s", subLine ) != 1 )
243   {
244     vtkErrorMacro( "Error with subline extraction upon file initialization" );
245     return 0;
246   }
247 
248   if (strncmp(subLine, "Binary", 6) != 0 &&
249     strncmp(subLine, "binary", 6) != 0)
250   {
251     vtkErrorMacro("This is not a binary data set. Try "
252       << "vtkEnSightGoldReader.");
253     return 0;
254   }
255   return 1;
256 }
257 
258 //----------------------------------------------------------------------------
ReadGeometryFile(const char * fileName,int timeStep,vtkMultiBlockDataSet * output)259 int vtkEnSightGoldBinaryReader::ReadGeometryFile(const char* fileName, int timeStep,
260   vtkMultiBlockDataSet *output)
261 {
262   char line[80], subLine[80], nameline[80];
263   int partId, realId;
264   int lineRead, i;
265 
266   if (!this->InitializeFile(fileName))
267   {
268     return 0;
269   }
270 
271   //this will close the file, so we need to reinitialize it
272   int numberOfTimeStepsInFile=this->CountTimeSteps();
273 
274   if (!this->InitializeFile(fileName))
275   {
276   return 0;
277   }
278 
279   if (this->UseFileSets)
280   {
281     if (numberOfTimeStepsInFile>1)
282     {
283       this->AddFileIndexToCache(fileName);
284 
285       i = this->SeekToCachedTimeStep(fileName, timeStep-1);
286       // start w/ the number of TS we skipped, not the one we are at
287       // if we are not at the appropriate time step yet, we keep searching
288       for (; i < timeStep - 1; i++)
289       {
290         if (!this->SkipTimeStep())
291         {
292           return 0;
293         }
294       }
295     }
296 
297     // use do-while here to initialize 'line' before 'strncmp' is appllied
298     // Thanks go to Brancois for care of this issue
299     do
300     {
301       this->ReadLine(line);
302     }
303     while ( strncmp(line, "BEGIN TIME STEP", 15) != 0 );
304     // found a time step -> cache it
305     this->AddTimeStepToCache(fileName, timeStep-1, this->GoldIFile->tellg());
306   }
307 
308   // Skip the 2 description lines.
309   this->ReadLine(line);
310   this->ReadLine(line);
311 
312   // Read the node id and element id lines.
313   this->ReadLine(line);
314   sscanf(line, " %*s %*s %s", subLine);
315   if (strncmp(subLine, "given", 5) == 0)
316   {
317     this->NodeIdsListed = 1;
318   }
319   else if (strncmp(subLine, "ignore", 6) == 0)
320   {
321     this->NodeIdsListed = 1;
322   }
323   else
324   {
325     this->NodeIdsListed = 0;
326   }
327 
328   this->ReadLine(line);
329   sscanf(line, " %*s %*s %s", subLine);
330   if (strncmp(subLine, "given", 5) == 0)
331   {
332     this->ElementIdsListed = 1;
333   }
334   else if (strncmp(subLine, "ignore", 6) == 0)
335   {
336     this->ElementIdsListed = 1;
337   }
338   else
339   {
340     this->ElementIdsListed = 0;
341   }
342 
343   lineRead = this->ReadLine(line); // "extents" or "part"
344   if (strncmp(line, "extents", 7) == 0)
345   {
346     // Skipping the extents.
347     this->GoldIFile->seekg(6*sizeof(float), ios::cur);
348     lineRead = this->ReadLine(line); // "part"
349   }
350 
351   while (lineRead > 0 && strncmp(line, "part", 4) == 0)
352   {
353     this->ReadPartId(&partId);
354     partId--; // EnSight starts #ing at 1.
355     if (partId < 0 || partId >= MAXIMUM_PART_ID)
356     {
357       vtkErrorMacro("Invalid part id; check that ByteOrder is set correctly.");
358       return 0;
359     }
360     realId = this->InsertNewPartId(partId);
361 
362     // Increment the number of geometry parts such that the measured geometry,
363     // if any, can be properly combined into a vtkMultiBlockDataSet object.
364     // --- fix to bug #7453
365     this->NumberOfGeometryParts ++;
366 
367     this->ReadLine(line); // part description line
368 
369     strncpy(nameline, line, 80); // 80 characters in line are allowed
370     nameline[79] = '\0'; // Ensure nullptr character at end of part name
371     char *name = strdup(nameline);
372 
373     // fix to bug #0008237
374     // The original "return 1" operation upon "strncmp(line, "interface", 9) == 0"
375     // was removed here as 'interface' is NOT a keyword of an EnSight Gold file.
376 
377     this->ReadLine(line);
378 
379     if (strncmp(line, "block", 5) == 0)
380     {
381       if (sscanf(line, " %*s %s", subLine) == 1)
382       {
383         if (strncmp(subLine, "rectilinear", 11) == 0)
384         {
385           // block rectilinear
386           lineRead = this->CreateRectilinearGridOutput(realId, line, name,
387             output);
388         }
389         else if (strncmp(subLine, "uniform", 7) == 0)
390         {
391           // block uniform
392           lineRead = this->CreateImageDataOutput(realId, line, name,
393             output);
394         }
395         else
396         {
397           // block iblanked
398           lineRead = this->CreateStructuredGridOutput(realId, line, name,
399             output);
400         }
401       }
402       else
403       {
404         // block
405         lineRead = this->CreateStructuredGridOutput(realId, line, name,
406           output);
407       }
408     }
409     else
410     {
411       lineRead = this->CreateUnstructuredGridOutput(realId, line, name,
412         output);
413       if (lineRead < 0)
414       {
415         free(name);
416         if (this->GoldIFile)
417         {
418           this->GoldIFile->close();
419           delete this->GoldIFile;
420           this->GoldIFile = nullptr;
421         }
422         return 0;
423       }
424     }
425     free(name);
426   }
427 
428   if (this->GoldIFile)
429   {
430     this->GoldIFile->close();
431     delete this->GoldIFile;
432     this->GoldIFile = nullptr;
433   }
434   if (lineRead < 0)
435   {
436     return 0;
437   }
438 
439   return 1;
440 }
441 
442 //----------------------------------------------------------------------------
CountTimeSteps()443 int vtkEnSightGoldBinaryReader::CountTimeSteps()
444 {
445   int count=0;
446   while(1)
447   {
448     int result=this->SkipTimeStep();
449     if (result)
450     {
451       count++;
452     }
453     else
454     {
455       break;
456     }
457   }
458   return count;
459 }
460 
461 //----------------------------------------------------------------------------
SkipTimeStep()462 int vtkEnSightGoldBinaryReader::SkipTimeStep()
463 {
464   char line[80], subLine[80];
465   int lineRead;
466 
467   line[0] = '\0';
468   while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
469   {
470     if (!this->ReadLine(line))
471     {
472       return 0;
473     }
474   }
475 
476   // Skip the 2 description lines.
477   this->ReadLine(line);
478   this->ReadLine(line);
479 
480   // Read the node id and element id lines.
481   this->ReadLine(line);
482   sscanf(line, " %*s %*s %s", subLine);
483   if (strncmp(subLine, "given", 5) == 0 ||
484     strncmp(subLine, "ignore", 6) == 0)
485   {
486     this->NodeIdsListed = 1;
487   }
488   else
489   {
490     this->NodeIdsListed = 0;
491   }
492 
493   this->ReadLine(line);
494   sscanf(line, " %*s %*s %s", subLine);
495   if (strncmp(subLine, "given", 5) == 0)
496   {
497     this->ElementIdsListed = 1;
498   }
499   else if (strncmp(subLine, "ignore", 6) == 0)
500   {
501     this->ElementIdsListed = 1;
502   }
503   else
504   {
505     this->ElementIdsListed = 0;
506   }
507 
508   lineRead = this->ReadLine(line); // "extents" or "part"
509   if (strncmp(line, "extents", 7) == 0)
510   {
511     // Skipping the extents.
512     this->GoldIFile->seekg(6*sizeof(float), ios::cur);
513     lineRead = this->ReadLine(line); // "part"
514   }
515 
516   while (lineRead > 0 && strncmp(line, "part", 4) == 0)
517   {
518     int tmpInt;
519     this->ReadPartId(&tmpInt);
520     if (tmpInt < 0 || tmpInt > MAXIMUM_PART_ID)
521     {
522       vtkErrorMacro("Invalid part id; check that ByteOrder is set correctly.");
523       return 0;
524     }
525     this->ReadLine(line); // part description line
526     this->ReadLine(line);
527 
528     if (strncmp(line, "block", 5) == 0)
529     {
530       if (sscanf(line, " %*s %s", subLine) == 1)
531       {
532         if (strncmp(subLine, "rectilinear", 11) == 0)
533         {
534           // block rectilinear
535           lineRead = this->SkipRectilinearGrid(line);
536         }
537         else if (strncmp(subLine, "uniform,", 7) == 0)
538         {
539           // block uniform
540           lineRead = this->SkipImageData(line);
541         }
542         else
543         {
544           // block iblanked
545           lineRead = this->SkipStructuredGrid(line);
546         }
547       }
548       else
549       {
550         // block
551         lineRead = this->SkipStructuredGrid(line);
552       }
553     }
554     else
555     {
556       lineRead = this->SkipUnstructuredGrid(line);
557     }
558   }
559 
560   if (lineRead < 0)
561   {
562     if (this->GoldIFile)
563     {
564       this->GoldIFile->close();
565       delete this->GoldIFile;
566       this->GoldIFile = nullptr;
567     }
568     return 0;
569   }
570 
571   return 1;
572 }
573 
574 //----------------------------------------------------------------------------
SkipStructuredGrid(char line[256])575 int vtkEnSightGoldBinaryReader::SkipStructuredGrid(char line[256])
576 {
577   char subLine[80];
578   int lineRead;
579   int iblanked = 0;
580   int dimensions[3];
581   int numPts;
582 
583   if (sscanf(line, " %*s %s", subLine) == 1)
584   {
585     if (strncmp(subLine, "iblanked", 8) == 0)
586     {
587       iblanked = 1;
588     }
589   }
590 
591   this->ReadIntArray(dimensions, 3);
592   numPts = dimensions[0] * dimensions[1] * dimensions[2];
593   if (dimensions[0] < 0 ||
594     static_cast<unsigned int>(dimensions[0] * this->SizeOfInt) > this->FileSize ||
595     dimensions[1] < 0 ||
596     static_cast<unsigned int>(dimensions[1] * this->SizeOfInt) > this->FileSize ||
597     dimensions[2] < 0 ||
598     static_cast<unsigned int>(dimensions[2] * this->SizeOfInt) > this->FileSize ||
599     numPts < 0 || static_cast<unsigned int>(numPts*this->SizeOfInt) > this->FileSize)
600   {
601     vtkErrorMacro("Invalid dimensions read; check that ByteOrder is set correctly.");
602     return -1;
603   }
604 
605   // Skip xCoords, yCoords and zCoords.
606   this->GoldIFile->seekg(sizeof(float)*numPts*3, ios::cur);
607 
608   if (iblanked)
609   { // skip iblank array.
610     this->GoldIFile->seekg(numPts*sizeof(int), ios::cur);
611   }
612 
613   // reading next line to check for EOF
614   lineRead = this->ReadLine(line);
615   return lineRead;
616 }
617 
618 //----------------------------------------------------------------------------
SkipUnstructuredGrid(char line[256])619 int vtkEnSightGoldBinaryReader::SkipUnstructuredGrid(char line[256])
620 {
621   int lineRead = 1;
622   int i;
623   int numElements;
624   int cellType;
625 
626   while(lineRead && strncmp(line, "part", 4) != 0)
627   {
628     if (strncmp(line, "coordinates", 11) == 0)
629     {
630       vtkDebugMacro("coordinates");
631       int numPts;
632 
633       this->ReadInt(&numPts);
634       if (numPts < 0 ||
635         static_cast<unsigned int>(numPts * this->SizeOfInt) > this->FileSize)
636       {
637         vtkErrorMacro("Invalid number of points; check that ByteOrder is set correctly.");
638         return -1;
639       }
640 
641       vtkDebugMacro("num. points: " << numPts);
642 
643       if (this->NodeIdsListed)
644       { // skip node ids.
645         this->GoldIFile->seekg(sizeof(int)*numPts, ios::cur);
646       }
647 
648       // Skip xCoords, yCoords and zCoords.
649       this->GoldIFile->seekg(sizeof(float)*3*numPts, ios::cur);
650     }
651     else if (strncmp(line, "point", 5) == 0 ||
652       strncmp(line, "g_point", 7) == 0)
653     {
654       vtkDebugMacro("point");
655 
656       this->ReadInt(&numElements);
657       if (numElements < 0 ||
658         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
659       {
660         vtkErrorMacro("Invalid number of point cells; check that ByteOrder is set correctly.");
661         return -1;
662       }
663       if (this->ElementIdsListed)
664       { // skip element ids.
665         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
666       }
667 
668       // Skip nodeIdList.
669       this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
670     }
671     else if (strncmp(line, "bar2", 4) == 0 ||
672       strncmp(line, "g_bar2", 6) == 0)
673     {
674       vtkDebugMacro("bar2");
675 
676       this->ReadInt(&numElements);
677       if (numElements < 0 ||
678         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
679       {
680         vtkErrorMacro("Invalid number of bar2 cells; check that ByteOrder is set correctly.");
681         return -1;
682       }
683       if (this->ElementIdsListed)
684       {
685         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
686       }
687 
688       // Skip nodeIdList.
689       this->GoldIFile->seekg(sizeof(int)*2*numElements, ios::cur);
690     }
691     else if (strncmp(line, "bar3", 4) == 0 ||
692       strncmp(line, "g_bar3", 6) == 0)
693     {
694       vtkDebugMacro("bar3");
695 
696       this->ReadInt(&numElements);
697       if (numElements < 0 ||
698         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
699       {
700         vtkErrorMacro("Invalid number of bar3 cells; check that ByteOrder is set correctly.");
701         return -1;
702       }
703 
704       if (this->ElementIdsListed)
705       {
706         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
707       }
708 
709       // Skip nodeIdList.
710       this->GoldIFile->seekg(sizeof(int)*3*numElements, ios::cur);
711     }
712     else if (strncmp(line, "nsided", 6) == 0 ||
713       strncmp(line, "g_nsided", 8) == 0)
714     {
715       vtkDebugMacro("nsided");
716       int *numNodesPerElement;
717       int numNodes = 0;
718 
719       //cellType = vtkEnSightReader::NSIDED;
720       this->ReadInt(&numElements);
721       if (numElements < 0 ||
722         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
723       {
724         vtkErrorMacro("Invalid number of nsided cells; check that ByteOrder is set correctly.");
725         return -1;
726       }
727 
728       if (this->ElementIdsListed)
729       {
730         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
731       }
732 
733       numNodesPerElement = new int[numElements];
734       this->ReadIntArray(numNodesPerElement, numElements);
735       for (i = 0; i < numElements; i++)
736       {
737         numNodes += numNodesPerElement[i];
738       }
739       // Skip nodeIdList.
740       this->GoldIFile->seekg(sizeof(int)*numNodes, ios::cur);
741       delete [] numNodesPerElement;
742     }
743     else if (strncmp(line, "tria3", 5) == 0 ||
744       strncmp(line, "tria6", 5) == 0 ||
745       strncmp(line, "g_tria3", 7) == 0 ||
746       strncmp(line, "g_tria6", 7) == 0)
747     {
748       if (strncmp(line, "tria6", 5) == 0 ||
749         strncmp(line, "g_tria6", 7) == 0)
750       {
751         vtkDebugMacro("tria6");
752         cellType = vtkEnSightReader::TRIA6;
753       }
754       else
755       {
756         vtkDebugMacro("tria3");
757         cellType = vtkEnSightReader::TRIA3;
758       }
759 
760       this->ReadInt(&numElements);
761       if (numElements < 0 ||
762         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
763       {
764         vtkErrorMacro("Invalid number of triangle cells; check that ByteOrder is set correctly.");
765         return -1;
766       }
767       if (this->ElementIdsListed)
768       {
769         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
770       }
771 
772       if (cellType == vtkEnSightReader::TRIA6)
773       {
774         // Skip nodeIdList.
775         this->GoldIFile->seekg(sizeof(int)*6*numElements, ios::cur);
776       }
777       else
778       {
779         // Skip nodeIdList.
780         this->GoldIFile->seekg(sizeof(int)*3*numElements, ios::cur);
781       }
782     }
783     else if (strncmp(line, "quad4", 5) == 0 ||
784       strncmp(line, "quad8", 5) == 0 ||
785       strncmp(line, "g_quad4", 7) == 0 ||
786       strncmp(line, "g_quad8", 7) == 0)
787     {
788       if (strncmp(line, "quad8", 5) == 0 ||
789         strncmp(line, "g_quad8", 7) == 0)
790       {
791         vtkDebugMacro("quad8");
792         cellType = vtkEnSightReader::QUAD8;
793       }
794       else
795       {
796         vtkDebugMacro("quad4");
797         cellType = vtkEnSightReader::QUAD4;
798       }
799 
800       this->ReadInt(&numElements);
801       if (numElements < 0 ||
802         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
803       {
804         vtkErrorMacro("Invalid number of quad cells; check that ByteOrder is set correctly.");
805         return -1;
806       }
807       if (this->ElementIdsListed)
808       {
809         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
810       }
811 
812       if (cellType == vtkEnSightReader::QUAD8)
813       {
814         // Skip nodeIdList.
815         this->GoldIFile->seekg(sizeof(int)*8*numElements, ios::cur);
816       }
817       else
818       {
819         // Skip nodeIdList.
820         this->GoldIFile->seekg(sizeof(int)*4*numElements, ios::cur);
821       }
822     }
823     else if (strncmp(line, "nfaced", 6) == 0)
824     {
825       vtkDebugMacro("nfaced");
826       int *numFacesPerElement;
827       int *numNodesPerFace;
828       int numFaces = 0;
829       int numNodes = 0;
830 
831       this->ReadInt(&numElements);
832       if (numElements < 0 ||
833         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
834       {
835         vtkErrorMacro("Invalid number of nfaced cells; check that ByteOrder is set correctly.");
836         return -1;
837       }
838 
839       if (this->ElementIdsListed)
840       {
841         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
842       }
843 
844       numFacesPerElement = new int[numElements];
845       this->ReadIntArray(numFacesPerElement, numElements);
846       for (i = 0; i < numElements; i++)
847       {
848         numFaces += numFacesPerElement[i];
849       }
850       delete [] numFacesPerElement;
851       numNodesPerFace = new int[numFaces];
852       this->ReadIntArray(numNodesPerFace, numFaces);
853       for (i = 0; i < numFaces; i++)
854       {
855         numNodes += numNodesPerFace[i];
856       }
857       // Skip nodeIdList.
858       this->GoldIFile->seekg(sizeof(int)*numNodes, ios::cur);
859       delete [] numNodesPerFace;
860     }
861     else if (strncmp(line, "tetra4", 6) == 0 ||
862       strncmp(line, "tetra10", 7) == 0 ||
863       strncmp(line, "g_tetra4", 8) == 0 ||
864       strncmp(line, "g_tetra10", 9) == 0)
865     {
866       if (strncmp(line, "tetra10", 7) == 0 ||
867         strncmp(line, "g_tetra10", 9) == 0)
868       {
869         vtkDebugMacro("tetra10");
870         cellType = vtkEnSightReader::TETRA10;
871       }
872       else
873       {
874         vtkDebugMacro("tetra4");
875         cellType = vtkEnSightReader::TETRA4;
876       }
877 
878       this->ReadInt(&numElements);
879       if (numElements < 0 ||
880         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
881       {
882         vtkErrorMacro("Invalid number of tetrahedral cells; check that ByteOrder is set correctly.");
883         return -1;
884       }
885       if (this->ElementIdsListed)
886       {
887         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
888       }
889 
890       if (cellType == vtkEnSightReader::TETRA10)
891       {
892         // Skip nodeIdList.
893         this->GoldIFile->seekg(sizeof(int)*10*numElements, ios::cur);
894       }
895       else
896       {
897         // Skip nodeIdList.
898         this->GoldIFile->seekg(sizeof(int)*4*numElements, ios::cur);
899       }
900     }
901     else if (strncmp(line, "pyramid5", 8) == 0 ||
902       strncmp(line, "pyramid13", 9) == 0 ||
903       strncmp(line, "g_pyramid5", 10) == 0 ||
904       strncmp(line, "g_pyramid13", 11) == 0)
905     {
906       if (strncmp(line, "pyramid13", 9) == 0 ||
907         strncmp(line, "g_pyramid13", 11) == 0)
908       {
909         vtkDebugMacro("pyramid13");
910         cellType = vtkEnSightReader::PYRAMID13;
911       }
912       else
913       {
914         vtkDebugMacro("pyramid5");
915         cellType = vtkEnSightReader::PYRAMID5;
916       }
917 
918       this->ReadInt(&numElements);
919       if (numElements < 0 ||
920         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
921       {
922         vtkErrorMacro("Invalid number of pyramid cells; check that ByteOrder is set correctly.");
923         return -1;
924       }
925       if (this->ElementIdsListed)
926       {
927         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
928       }
929 
930       if (cellType == vtkEnSightReader::PYRAMID13)
931       {
932         // Skip nodeIdList.
933         this->GoldIFile->seekg(sizeof(int)*13*numElements, ios::cur);
934       }
935       else
936       {
937         // Skip nodeIdList.
938         this->GoldIFile->seekg(sizeof(int)*5*numElements, ios::cur);
939       }
940     }
941     else if (strncmp(line, "hexa8", 5) == 0 ||
942       strncmp(line, "hexa20", 6) == 0 ||
943       strncmp(line, "g_hexa8", 7) == 0 ||
944       strncmp(line, "g_hexa20", 8) == 0)
945     {
946       if (strncmp(line, "hexa20", 6) == 0 ||
947         strncmp(line, "g_hexa20", 8) == 0)
948       {
949         vtkDebugMacro("hexa20");
950         cellType = vtkEnSightReader::HEXA20;
951       }
952       else
953       {
954         vtkDebugMacro("hexa8");
955         cellType = vtkEnSightReader::HEXA8;
956       }
957 
958       this->ReadInt(&numElements);
959       if (numElements < 0 ||
960         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
961       {
962         vtkErrorMacro("Invalid number of hexahedral cells; check that ByteOrder is set correctly.");
963         return -1;
964       }
965       if (this->ElementIdsListed)
966       {
967         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
968       }
969 
970       if (cellType == vtkEnSightReader::HEXA20)
971       {
972         // Skip nodeIdList.
973         this->GoldIFile->seekg(sizeof(int)*20*numElements, ios::cur);
974       }
975       else
976       {
977         // Skip nodeIdList.
978         this->GoldIFile->seekg(sizeof(int)*8*numElements, ios::cur);
979       }
980     }
981     else if (strncmp(line, "penta6", 6) == 0 ||
982       strncmp(line, "penta15", 7) == 0 ||
983       strncmp(line, "g_penta6", 8) == 0 ||
984       strncmp(line, "g_penta15", 9) == 0)
985     {
986       if (strncmp(line, "penta15", 7) == 0 ||
987         strncmp(line, "g_penta15", 9) == 0)
988       {
989         vtkDebugMacro("penta15");
990         cellType = vtkEnSightReader::PENTA15;
991       }
992       else
993       {
994         vtkDebugMacro("penta6");
995         cellType = vtkEnSightReader::PENTA6;
996       }
997 
998       this->ReadInt(&numElements);
999       if (numElements < 0 ||
1000         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
1001       {
1002         vtkErrorMacro("Invalid number of pentagonal cells; check that ByteOrder is set correctly.");
1003         return -1;
1004       }
1005       if (this->ElementIdsListed)
1006       {
1007         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
1008       }
1009 
1010       if (cellType == vtkEnSightReader::PENTA15)
1011       {
1012         // Skip nodeIdList.
1013         this->GoldIFile->seekg(sizeof(int)*15*numElements, ios::cur);
1014       }
1015       else
1016       {
1017         // Skip nodeIdList.
1018         this->GoldIFile->seekg(sizeof(int)*6*numElements, ios::cur);
1019       }
1020     }
1021     else if (strncmp(line, "END TIME STEP", 13) == 0)
1022     {
1023       return 1;
1024     }
1025     else
1026     {
1027       vtkErrorMacro("undefined geometry file line");
1028       return -1;
1029     }
1030     lineRead = this->ReadLine(line);
1031   }
1032   return lineRead;
1033 }
1034 
1035 //----------------------------------------------------------------------------
SkipRectilinearGrid(char line[256])1036 int vtkEnSightGoldBinaryReader::SkipRectilinearGrid(char line[256])
1037 {
1038   char subLine[80];
1039   int lineRead;
1040   int iblanked = 0;
1041   int dimensions[3];
1042   int numPts;
1043 
1044   if (sscanf(line, " %*s %*s %s", subLine) == 1)
1045   {
1046     if (strncmp(subLine, "iblanked", 8) == 0)
1047     {
1048       iblanked = 1;
1049     }
1050   }
1051 
1052   this->ReadIntArray(dimensions, 3);
1053   if (dimensions[0] < 0 ||
1054     static_cast<unsigned int>(dimensions[0] * this->SizeOfInt) > this->FileSize ||
1055     dimensions[1] < 0 ||
1056     static_cast<unsigned int>(dimensions[1] * this->SizeOfInt) > this->FileSize ||
1057     dimensions[2] < 0 ||
1058     static_cast<unsigned int>(dimensions[2] * this->SizeOfInt) > this->FileSize ||
1059     (dimensions[0]+dimensions[1]+dimensions[2]) < 0 ||
1060     static_cast<unsigned int>((dimensions[0] + dimensions[1] + dimensions[2]) * this->SizeOfInt) >
1061       this->FileSize)
1062   {
1063     vtkErrorMacro("Invalid dimensions read; check that BytetOrder is set correctly.");
1064     return -1;
1065   }
1066 
1067   numPts = dimensions[0] * dimensions[1] * dimensions[2];
1068 
1069   // Skip xCoords
1070   this->GoldIFile->seekg(sizeof(float)*dimensions[0], ios::cur);
1071   // Skip yCoords
1072   this->GoldIFile->seekg(sizeof(float)*dimensions[1], ios::cur);
1073   // Skip zCoords
1074   this->GoldIFile->seekg(sizeof(float)*dimensions[2], ios::cur);
1075 
1076   if (iblanked)
1077   {
1078     vtkWarningMacro("VTK does not handle blanking for rectilinear grids.");
1079     this->GoldIFile->seekg(sizeof(int)*numPts, ios::cur);
1080   }
1081 
1082   // reading next line to check for EOF
1083   lineRead = this->ReadLine(line);
1084   return lineRead;
1085 }
1086 
1087 //----------------------------------------------------------------------------
SkipImageData(char line[256])1088 int vtkEnSightGoldBinaryReader::SkipImageData(char line[256])
1089 {
1090   char subLine[80];
1091   int lineRead;
1092   int iblanked = 0;
1093   int dimensions[3];
1094   float origin[3], delta[3];
1095   int numPts;
1096 
1097   if (sscanf(line, " %*s %*s %s", subLine) == 1)
1098   {
1099     if (strncmp(subLine, "iblanked", 8) == 0)
1100     {
1101       iblanked = 1;
1102     }
1103   }
1104 
1105   this->ReadIntArray(dimensions, 3);
1106   this->ReadFloatArray(origin, 3);
1107   this->ReadFloatArray(delta, 3);
1108 
1109   if (iblanked)
1110   {
1111     vtkWarningMacro("VTK does not handle blanking for image data.");
1112     numPts = dimensions[0] * dimensions[1] * dimensions[2];
1113     if (dimensions[0] < 0 ||
1114       static_cast<unsigned int>(dimensions[0] * this->SizeOfInt) > this->FileSize ||
1115       dimensions[1] < 0 ||
1116       static_cast<unsigned int>(dimensions[1] * this->SizeOfInt) > this->FileSize ||
1117       dimensions[2] < 0 ||
1118       static_cast<unsigned int>(dimensions[2] * this->SizeOfInt) > this->FileSize ||
1119       numPts < 0 || static_cast<unsigned int>(numPts * this->SizeOfInt) > this->FileSize)
1120     {
1121       return -1;
1122     }
1123     this->GoldIFile->seekg(sizeof(int)*numPts, ios::cur);
1124   }
1125 
1126   // reading next line to check for EOF
1127   lineRead = this->ReadLine(line);
1128   return lineRead;
1129 }
1130 
1131 //----------------------------------------------------------------------------
ReadMeasuredGeometryFile(const char * fileName,int timeStep,vtkMultiBlockDataSet * output)1132 int vtkEnSightGoldBinaryReader::ReadMeasuredGeometryFile(const char* fileName,
1133   int timeStep,
1134   vtkMultiBlockDataSet *output)
1135 {
1136   char line[80], subLine[80];
1137   vtkIdType i;
1138   int *pointIds;
1139   float *xCoords, *yCoords, *zCoords;
1140   vtkPoints *points = vtkPoints::New();
1141   vtkPolyData *pd = vtkPolyData::New();
1142 
1143   this->NumberOfNewOutputs++;
1144 
1145   // Initialize
1146   //
1147   if (!fileName)
1148   {
1149     vtkErrorMacro("A MeasuredFileName must be specified in the case file.");
1150     return 0;
1151   }
1152   std::string sfilename;
1153   if (this->FilePath)
1154   {
1155     sfilename = this->FilePath;
1156     if (sfilename.at(sfilename.length()-1) != '/')
1157     {
1158       sfilename += "/";
1159     }
1160     sfilename += fileName;
1161     vtkDebugMacro("full path to measured geometry file: "
1162       << sfilename.c_str());
1163   }
1164   else
1165   {
1166     sfilename = fileName;
1167   }
1168 
1169   if (this->OpenFile(sfilename.c_str()) == 0)
1170   {
1171     vtkErrorMacro("Unable to open file: " << sfilename.c_str());
1172     return 0;
1173   }
1174 
1175   this->ReadLine(line);
1176   sscanf(line, " %*s %s", subLine);
1177   if (strncmp(subLine, "Binary", 6) != 0)
1178   {
1179     vtkErrorMacro("This is not a binary data set. Try "
1180       << "vtkEnSightGoldReader.");
1181     return 0;
1182   }
1183 
1184   if (this->UseFileSets)
1185   {
1186     this->AddFileIndexToCache(fileName);
1187 
1188     i = this->SeekToCachedTimeStep(fileName, timeStep-1);
1189     // start w/ the number of TS we skipped, not the one we are at
1190     // if we are not at the appropriate time step yet, we keep searching
1191     for (; i < timeStep - 1; i++)
1192     {
1193       while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1194       {
1195         this->ReadLine(line);
1196       }
1197       // Skip the description line.
1198       this->ReadLine(line);
1199 
1200       this->ReadLine(line); // "particle coordinates"
1201 
1202       this->ReadInt(&this->NumberOfMeasuredPoints);
1203 
1204       // Skip pointIds
1205       //this->GoldIFile->ignore(sizeof(int)*this->NumberOfMeasuredPoints);
1206       // Skip xCoords
1207       //this->GoldIFile->ignore(sizeof(float)*this->NumberOfMeasuredPoints);
1208       // Skip yCoords
1209       //this->GoldIFile->ignore(sizeof(float)*this->NumberOfMeasuredPoints);
1210       // Skip zCoords
1211       //this->GoldIFile->ignore(sizeof(float)*this->NumberOfMeasuredPoints);
1212       this->GoldIFile->seekg(
1213         (sizeof(float)*3 + sizeof(int))*this->NumberOfMeasuredPoints,
1214         ios::cur);
1215       this->ReadLine(line); // END TIME STEP
1216     }
1217     while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1218     {
1219       this->ReadLine(line);
1220     }
1221     // found a time step -> cache it
1222     this->AddTimeStepToCache(fileName, i, this->GoldIFile->tellg());
1223   }
1224 
1225   // Skip the description line.
1226   this->ReadLine(line);
1227 
1228   this->ReadLine(line); // "particle coordinates"
1229 
1230   this->ReadInt(&this->NumberOfMeasuredPoints);
1231 
1232   pointIds = new int[this->NumberOfMeasuredPoints];
1233   xCoords = new float [this->NumberOfMeasuredPoints];
1234   yCoords = new float [this->NumberOfMeasuredPoints];
1235   zCoords = new float [this->NumberOfMeasuredPoints];
1236   points->Allocate(this->NumberOfMeasuredPoints);
1237   pd->Allocate(this->NumberOfMeasuredPoints);
1238 
1239   // Extract the array of point indices. Note EnSight Manual v8.2 (pp. 559,
1240   // http://www-vis.lbl.gov/NERSC/Software/ensight/docs82/UserManual.pdf)
1241   // is wrong in describing the format of binary measured geometry files.
1242   // As opposed to this description, the actual format employs a 'hybrid'
1243   // storage scheme. Specifically, point indices are stored in an array,
1244   // whereas 3D coordinates follow the array in a tuple-by-tuple manner.
1245   // The following code segment (20+ lines) serves as a fix to bug #9245.
1246   this->ReadIntArray( pointIds, this->NumberOfMeasuredPoints );
1247 
1248   // Read point coordinates tuple by tuple while each tuple contains three
1249   // components: (x-cord, y-cord, z-cord)
1250   int  floatSize = sizeof( float );
1251   for ( i = 0; i < this->NumberOfMeasuredPoints; i ++ )
1252   {
1253     this->GoldIFile->read(  ( char * )( xCoords + i ),  floatSize  );
1254     this->GoldIFile->read(  ( char * )( yCoords + i ),  floatSize  );
1255     this->GoldIFile->read(  ( char * )( zCoords + i ),  floatSize  );
1256   }
1257 
1258   if ( this->ByteOrder == FILE_LITTLE_ENDIAN )
1259   {
1260     vtkByteSwap::Swap4LERange( xCoords, this->NumberOfMeasuredPoints );
1261     vtkByteSwap::Swap4LERange( yCoords, this->NumberOfMeasuredPoints );
1262     vtkByteSwap::Swap4LERange( zCoords, this->NumberOfMeasuredPoints );
1263   }
1264   else
1265   {
1266     vtkByteSwap::Swap4BERange( xCoords, this->NumberOfMeasuredPoints );
1267     vtkByteSwap::Swap4BERange( yCoords, this->NumberOfMeasuredPoints );
1268     vtkByteSwap::Swap4BERange( zCoords, this->NumberOfMeasuredPoints );
1269   }
1270 
1271   // NOTE: EnSight always employs a 1-based indexing scheme and therefore
1272   // 'if (this->ParticleCoordinatesByIndex)' was removed here. Otherwise
1273   // the measured geometry could not be proeperly interpreted.
1274   // This bug was noticed while fixing bug #7453.
1275   for (i = 0; i < this->NumberOfMeasuredPoints; i++)
1276   {
1277     points->InsertNextPoint(xCoords[i], yCoords[i], zCoords[i]);
1278     pd->InsertNextCell(VTK_VERTEX, 1, &i);
1279   }
1280 
1281   pd->SetPoints(points);
1282   this->AddToBlock(output, this->NumberOfGeometryParts, pd);
1283 
1284   points->Delete();
1285   pd->Delete();
1286   delete [] pointIds;
1287   delete [] xCoords;
1288   delete [] yCoords;
1289   delete [] zCoords;
1290 
1291   if (this->GoldIFile)
1292   {
1293     this->GoldIFile->close();
1294     delete this->GoldIFile;
1295     this->GoldIFile = nullptr;
1296   }
1297   return 1;
1298 }
1299 
1300 //----------------------------------------------------------------------------
ReadScalarsPerNode(const char * fileName,const char * description,int timeStep,vtkMultiBlockDataSet * compositeOutput,int measured,int numberOfComponents,int component)1301 int vtkEnSightGoldBinaryReader::ReadScalarsPerNode(
1302   const char* fileName, const char* description, int timeStep,
1303   vtkMultiBlockDataSet *compositeOutput, int measured,
1304   int numberOfComponents, int component)
1305 {
1306   char line[80];
1307   int partId, realId, numPts, i, lineRead;
1308   vtkFloatArray *scalars;
1309   float* scalarsRead;
1310   vtkDataSet *output;
1311 
1312   // Initialize
1313   //
1314   if (!fileName)
1315   {
1316     vtkErrorMacro("nullptr ScalarPerNode variable file name");
1317     return 0;
1318   }
1319   std::string sfilename;
1320   if (this->FilePath)
1321   {
1322     sfilename = this->FilePath;
1323     if (sfilename.at(sfilename.length()-1) != '/')
1324     {
1325       sfilename += "/";
1326     }
1327     sfilename += fileName;
1328     vtkDebugMacro("full path to scalar per node file: " << sfilename.c_str());
1329   }
1330   else
1331   {
1332     sfilename = fileName;
1333   }
1334 
1335   if (this->OpenFile(sfilename.c_str()) == 0)
1336   {
1337     vtkErrorMacro("Unable to open file: " << sfilename.c_str());
1338     return 0;
1339   }
1340 
1341   if (this->UseFileSets)
1342   {
1343     this->AddFileIndexToCache(fileName);
1344 
1345     i = this->SeekToCachedTimeStep(fileName, timeStep-1);
1346     // start w/ the number of TS we skipped, not the one we are at
1347     // if we are not at the appropriate time step yet, we keep searching
1348     for (; i < timeStep - 1; i++)
1349     {
1350       this->ReadLine(line);
1351       while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1352       {
1353         this->ReadLine(line);
1354       }
1355       // found a time step -> cache it
1356       this->AddTimeStepToCache(fileName, i, this->GoldIFile->tellg());
1357 
1358       this->ReadLine(line); // skip the description line
1359 
1360       if (measured)
1361       {
1362         output = static_cast<vtkDataSet*>(
1363           this->GetDataSetFromBlock(compositeOutput, this->NumberOfGeometryParts));
1364         numPts = output->GetNumberOfPoints();
1365         if (numPts)
1366         {
1367           this->ReadLine(line);
1368           // Skip sclalars
1369           this->GoldIFile->seekg(sizeof(float)*numPts, ios::cur);
1370         }
1371       }
1372 
1373       while (this->ReadLine(line) &&
1374         strncmp(line, "part", 4) == 0)
1375       {
1376         this->ReadPartId(&partId);
1377         partId--; // EnSight starts #ing with 1.
1378         realId = this->InsertNewPartId(partId);
1379         output = static_cast<vtkDataSet*>(
1380           this->GetDataSetFromBlock(compositeOutput, realId));
1381         numPts = output->GetNumberOfPoints();
1382         if (numPts)
1383         {
1384           this->ReadLine(line); // "coordinates" or "block"
1385           // Skip sclalars
1386           this->GoldIFile->seekg(sizeof(float)*numPts, ios::cur);
1387         }
1388       }
1389     }
1390     this->ReadLine(line);
1391     while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1392     {
1393       this->ReadLine(line);
1394     }
1395   }
1396 
1397   this->ReadLine(line); // skip the description line
1398 
1399   if (measured)
1400   {
1401     output = static_cast<vtkDataSet*>(
1402       this->GetDataSetFromBlock(compositeOutput, this->NumberOfGeometryParts));
1403     numPts = output->GetNumberOfPoints();
1404     if (numPts)
1405     {
1406       // 'this->ReadLine(line)' was removed here, otherwise there would be a
1407       // problem with timestep retrieval of the measured scalars.
1408       // This bug was noticed while fixing bug #7453.
1409       scalars = vtkFloatArray::New();
1410       scalars->SetNumberOfComponents(numberOfComponents);
1411       scalars->SetNumberOfTuples(numPts);
1412       scalarsRead = new float [numPts];
1413       this->ReadFloatArray(scalarsRead, numPts);
1414       // Why are we setting only one component here?
1415       // Only one component is set because scalars are single-component arrays.
1416       // For complex scalars, there is a file for the real part and another
1417       // file for the imaginary part, but we are storing them as a 2-component
1418       // array.
1419       for (i = 0; i < numPts; i++)
1420       {
1421         scalars->SetComponent(i, component, scalarsRead[i]);
1422       }
1423       scalars->SetName(description);
1424       output->GetPointData()->AddArray(scalars);
1425       if (!output->GetPointData()->GetScalars())
1426       {
1427         output->GetPointData()->SetScalars(scalars);
1428       }
1429       scalars->Delete();
1430       delete [] scalarsRead;
1431     }
1432     if (this->GoldIFile)
1433     {
1434       this->GoldIFile->close();
1435       delete this->GoldIFile;
1436       this->GoldIFile = nullptr;
1437     }
1438     return 1;
1439   }
1440 
1441   lineRead = this->ReadLine(line);
1442   while (lineRead && strncmp(line, "part", 4) == 0)
1443   {
1444     this->ReadPartId(&partId);
1445     partId--; // EnSight starts #ing with 1.
1446     realId = this->InsertNewPartId(partId);
1447     output = this->GetDataSetFromBlock(compositeOutput, realId);
1448     numPts = output->GetNumberOfPoints();
1449     // If the part has points, part number is followed by "coordinates" or
1450     // "block" and list of values.
1451     // If the part has no points, only part number is given, which may be
1452     // optionally followed by "coordinates" or "block", without any values.
1453 
1454     lineRead = this->ReadLine(line); // "coordinates", "block" or next part
1455 
1456     if (!numPts)
1457     {
1458       if (lineRead && strncmp(line, "part", 4) == 0)
1459       {
1460         // Part number was not followed by "coordinates" or "block"; we are
1461         // at the start of another part, skip to next iteration to avoid
1462         // reading anything more.
1463         continue;
1464       }
1465     }
1466     else
1467     {
1468       if (component == 0)
1469       {
1470         scalars = vtkFloatArray::New();
1471         scalars->SetNumberOfComponents(numberOfComponents);
1472         scalars->SetNumberOfTuples(numPts);
1473       }
1474       else
1475       {
1476         scalars = (vtkFloatArray*)(output->GetPointData()->
1477           GetArray(description));
1478       }
1479 
1480       scalarsRead = new float[numPts];
1481       this->ReadFloatArray(scalarsRead, numPts);
1482 
1483       for (i = 0; i < numPts; i++)
1484       {
1485         scalars->SetComponent(i, component, scalarsRead[i]);
1486       }
1487       if (component == 0)
1488       {
1489         scalars->SetName(description);
1490         output->GetPointData()->AddArray(scalars);
1491         if (!output->GetPointData()->GetScalars())
1492         {
1493           output->GetPointData()->SetScalars(scalars);
1494         }
1495         scalars->Delete();
1496       }
1497       else
1498       {
1499         output->GetPointData()->AddArray(scalars);
1500       }
1501       delete [] scalarsRead;
1502     }
1503 
1504     this->GoldIFile->peek();
1505     if (this->GoldIFile->eof())
1506     {
1507       lineRead = 0;
1508       continue;
1509     }
1510     lineRead = this->ReadLine(line);
1511   }
1512 
1513   if (this->GoldIFile)
1514   {
1515     this->GoldIFile->close();
1516     delete this->GoldIFile;
1517     this->GoldIFile = nullptr;
1518   }
1519   return 1;
1520 }
1521 
1522 //----------------------------------------------------------------------------
ReadVectorsPerNode(const char * fileName,const char * description,int timeStep,vtkMultiBlockDataSet * compositeOutput,int measured)1523 int vtkEnSightGoldBinaryReader::ReadVectorsPerNode(
1524   const char* fileName, const char* description, int timeStep,
1525   vtkMultiBlockDataSet *compositeOutput, int measured)
1526 {
1527   char line[80];
1528   int partId, realId, numPts, i, lineRead;
1529   vtkFloatArray *vectors;
1530   float tuple[3];
1531   float *comp1, *comp2, *comp3;
1532   float *vectorsRead;
1533   vtkDataSet *output;
1534 
1535   // Initialize
1536   //
1537   if (!fileName)
1538   {
1539     vtkErrorMacro("nullptr VectorPerNode variable file name");
1540     return 0;
1541   }
1542   std::string sfilename;
1543   if (this->FilePath)
1544   {
1545     sfilename = this->FilePath;
1546     if (sfilename.at(sfilename.length()-1) != '/')
1547     {
1548       sfilename += "/";
1549     }
1550     sfilename += fileName;
1551     vtkDebugMacro("full path to vector per node file: " << sfilename.c_str());
1552   }
1553   else
1554   {
1555     sfilename = fileName;
1556   }
1557 
1558   if (this->OpenFile(sfilename.c_str()) == 0)
1559   {
1560     vtkErrorMacro("Unable to open file: " << sfilename.c_str());
1561     return 0;
1562   }
1563 
1564   if (this->UseFileSets)
1565   {
1566     this->AddFileIndexToCache(fileName);
1567 
1568     i = this->SeekToCachedTimeStep(fileName, timeStep-1);
1569     // start w/ the number of TS we skipped, not the one we are at
1570     // if we are not at the appropriate time step yet, we keep searching
1571     for (; i < timeStep - 1; i++)
1572     {
1573       this->ReadLine(line);
1574       while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1575       {
1576         this->ReadLine(line);
1577       }
1578       // found a time step -> cache it
1579       this->AddTimeStepToCache(fileName, i, this->GoldIFile->tellg());
1580 
1581       this->ReadLine(line); // skip the description line
1582 
1583       if (measured)
1584       {
1585         output = static_cast<vtkDataSet*>(
1586           this->GetDataSetFromBlock(compositeOutput, this->NumberOfGeometryParts));
1587         numPts = output->GetNumberOfPoints();
1588         if (numPts)
1589         {
1590           this->ReadLine(line);
1591           // Skip vectors.
1592           this->GoldIFile->seekg(sizeof(float)*3*numPts, ios::cur);
1593         }
1594       }
1595 
1596       while (this->ReadLine(line) &&
1597         strncmp(line, "part", 4) == 0)
1598       {
1599         this->ReadPartId(&partId);
1600         partId--; // EnSight starts #ing with 1.
1601         realId = this->InsertNewPartId(partId);
1602         output = static_cast<vtkDataSet*>(
1603           this->GetDataSetFromBlock(compositeOutput, realId));
1604         numPts = output->GetNumberOfPoints();
1605         if (numPts)
1606         {
1607           this->ReadLine(line); // "coordinates" or "block"
1608           // Skip comp1, comp2 and comp3
1609           this->GoldIFile->seekg(sizeof(float)*3*numPts, ios::cur);
1610         }
1611       }
1612     }
1613     this->ReadLine(line);
1614     while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1615     {
1616       this->ReadLine(line);
1617     }
1618   }
1619 
1620   this->ReadLine(line); // skip the description line
1621 
1622   if (measured)
1623   {
1624     output = static_cast<vtkDataSet*>(
1625       this->GetDataSetFromBlock(compositeOutput, this->NumberOfGeometryParts));
1626     numPts = output->GetNumberOfPoints();
1627     if (numPts)
1628     {
1629       // NOTE: NO ReadLine() here since there is only one description
1630       // line (already read above), immediately followed by the actual data.
1631 
1632       vectors = vtkFloatArray::New();
1633       vectors->SetNumberOfComponents(3);
1634       vectors->SetNumberOfTuples(numPts);
1635       vectorsRead = vectors->GetPointer(0);
1636       this->ReadFloatArray(vectorsRead, numPts*3);
1637       vectors->SetName(description);
1638       output->GetPointData()->AddArray(vectors);
1639       if (!output->GetPointData()->GetVectors())
1640       {
1641         output->GetPointData()->SetVectors(vectors);
1642       }
1643       vectors->Delete();
1644     }
1645     if (this->GoldIFile)
1646     {
1647       this->GoldIFile->close();
1648       delete this->GoldIFile;
1649       this->GoldIFile = nullptr;
1650     }
1651     return 1;
1652   }
1653 
1654   lineRead = this->ReadLine(line);
1655   while (lineRead && strncmp(line, "part", 4) == 0)
1656   {
1657     this->ReadPartId(&partId);
1658     partId--; // EnSight starts #ing with 1.
1659     realId = this->InsertNewPartId(partId);
1660     output = this->GetDataSetFromBlock(compositeOutput, realId);
1661     numPts = output->GetNumberOfPoints();
1662     // If the part has points, part number is followed by "coordinates" or
1663     // "block" and list of values.
1664     // If the part has no points, only part number is given, which may be
1665     // optionally followed by "coordinates" or "block", without any values.
1666 
1667     lineRead = this->ReadLine(line); // "coordinates", "block" or next part
1668 
1669     if (!numPts)
1670     {
1671       if (lineRead && strncmp(line, "part", 4) == 0)
1672       {
1673         // Part number was not followed by "coordinates" or "block"; we are
1674         // at the start of another part, skip to next iteration to avoid
1675         // reading anything more.
1676         continue;
1677       }
1678     }
1679     else
1680     {
1681       vectors = vtkFloatArray::New();
1682       vectors->SetNumberOfComponents(3);
1683       vectors->SetNumberOfTuples(numPts);
1684       comp1 = new float[numPts];
1685       comp2 = new float[numPts];
1686       comp3 = new float[numPts];
1687       this->ReadFloatArray(comp1, numPts);
1688       this->ReadFloatArray(comp2, numPts);
1689       this->ReadFloatArray(comp3, numPts);
1690       for (i = 0; i < numPts; i++)
1691       {
1692         tuple[0] = comp1[i];
1693         tuple[1] = comp2[i];
1694         tuple[2] = comp3[i];
1695         vectors->SetTuple(i, tuple);
1696       }
1697       vectors->SetName(description);
1698       output->GetPointData()->AddArray(vectors);
1699       if (!output->GetPointData()->GetVectors())
1700       {
1701         output->GetPointData()->SetVectors(vectors);
1702       }
1703       vectors->Delete();
1704       delete [] comp1;
1705       delete [] comp2;
1706       delete [] comp3;
1707     }
1708 
1709     this->GoldIFile->peek();
1710     if (this->GoldIFile->eof())
1711     {
1712       lineRead = 0;
1713       continue;
1714     }
1715     lineRead = this->ReadLine(line);
1716   }
1717 
1718   if (this->GoldIFile)
1719   {
1720     this->GoldIFile->close();
1721     delete this->GoldIFile;
1722     this->GoldIFile = nullptr;
1723   }
1724 
1725   return 1;
1726 }
1727 
1728 //----------------------------------------------------------------------------
ReadTensorsPerNode(const char * fileName,const char * description,int timeStep,vtkMultiBlockDataSet * compositeOutput)1729 int vtkEnSightGoldBinaryReader::ReadTensorsPerNode(
1730   const char* fileName, const char* description, int timeStep,
1731   vtkMultiBlockDataSet *compositeOutput)
1732 {
1733   char line[80];
1734   int partId, realId, numPts, i, lineRead;
1735   vtkFloatArray *tensors;
1736   float *comp1, *comp2, *comp3, *comp4, *comp5, *comp6;
1737   float tuple[6];
1738   vtkDataSet *output;
1739 
1740   // Initialize
1741   //
1742   if (!fileName)
1743   {
1744     vtkErrorMacro("nullptr TensorPerNode variable file name");
1745     return 0;
1746   }
1747   std::string sfilename;
1748   if (this->FilePath)
1749   {
1750     sfilename = this->FilePath;
1751     if (sfilename.at(sfilename.length()-1) != '/')
1752     {
1753       sfilename += "/";
1754     }
1755     sfilename += fileName;
1756     vtkDebugMacro("full path to tensor per node file: " << sfilename.c_str());
1757   }
1758   else
1759   {
1760     sfilename = fileName;
1761   }
1762 
1763   if (this->OpenFile(sfilename.c_str()) == 0)
1764   {
1765     vtkErrorMacro("Unable to open file: " << sfilename.c_str());
1766     return 0;
1767   }
1768 
1769   if (this->UseFileSets)
1770   {
1771     this->AddFileIndexToCache(fileName);
1772 
1773     i = this->SeekToCachedTimeStep(fileName, timeStep-1);
1774     // start w/ the number of TS we skipped, not the one we are at
1775     // if we are not at the appropriate time step yet, we keep searching
1776     for (; i < timeStep - 1; i++)
1777     {
1778       this->ReadLine(line);
1779       while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1780       {
1781         this->ReadLine(line);
1782       }
1783       // found a time step -> cache it
1784       this->AddTimeStepToCache(fileName, i, this->GoldIFile->tellg());
1785 
1786       this->ReadLine(line); // skip the description line
1787 
1788       while (this->ReadLine(line) &&
1789         strncmp(line, "part", 4) == 0)
1790       {
1791         this->ReadPartId(&partId);
1792         partId--; // EnSight starts #ing with 1.
1793         realId = this->InsertNewPartId(partId);
1794         output = this->GetDataSetFromBlock(compositeOutput, realId);
1795         numPts = output->GetNumberOfPoints();
1796         if (numPts)
1797         {
1798           this->ReadLine(line); // "coordinates" or "block"
1799           // Skip over comp1, comp2, ... comp6
1800           this->GoldIFile->seekg(sizeof(float)*6*numPts, ios::cur);
1801         }
1802       }
1803     }
1804     this->ReadLine(line);
1805     while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1806     {
1807       this->ReadLine(line);
1808     }
1809   }
1810 
1811   this->ReadLine(line); // skip the description line
1812   lineRead = this->ReadLine(line);
1813 
1814   while (lineRead && strncmp(line, "part", 4) == 0)
1815   {
1816     this->ReadPartId(&partId);
1817     partId--; // EnSight starts #ing with 1.
1818     realId = this->InsertNewPartId(partId);
1819     output = this->GetDataSetFromBlock(compositeOutput, realId);
1820     numPts = output->GetNumberOfPoints();
1821     if (numPts)
1822     {
1823       tensors = vtkFloatArray::New();
1824       this->ReadLine(line); // "coordinates" or "block"
1825       tensors->SetNumberOfComponents(6);
1826       tensors->SetNumberOfTuples(numPts);
1827       comp1 = new float[numPts];
1828       comp2 = new float[numPts];
1829       comp3 = new float[numPts];
1830       comp4 = new float[numPts];
1831       comp5 = new float[numPts];
1832       comp6 = new float[numPts];
1833       this->ReadFloatArray(comp1, numPts);
1834       this->ReadFloatArray(comp2, numPts);
1835       this->ReadFloatArray(comp3, numPts);
1836       this->ReadFloatArray(comp4, numPts);
1837       this->ReadFloatArray(comp6, numPts);
1838       this->ReadFloatArray(comp5, numPts);
1839       for (i = 0; i < numPts; i++)
1840       {
1841         tuple[0] = comp1[i];
1842         tuple[1] = comp2[i];
1843         tuple[2] = comp3[i];
1844         tuple[3] = comp4[i];
1845         tuple[4] = comp5[i];
1846         tuple[5] = comp6[i];
1847         tensors->InsertTuple(i, tuple);
1848       }
1849       tensors->SetName(description);
1850       output->GetPointData()->AddArray(tensors);
1851       tensors->Delete();
1852       delete [] comp1;
1853       delete [] comp2;
1854       delete [] comp3;
1855       delete [] comp4;
1856       delete [] comp5;
1857       delete [] comp6;
1858     }
1859 
1860     this->GoldIFile->peek();
1861     if (this->GoldIFile->eof())
1862     {
1863       lineRead = 0;
1864       continue;
1865     }
1866     lineRead = this->ReadLine(line);
1867   }
1868 
1869   if (this->GoldIFile)
1870   {
1871     this->GoldIFile->close();
1872     delete this->GoldIFile;
1873     this->GoldIFile = nullptr;
1874   }
1875 
1876   return 1;
1877 }
1878 
1879 //----------------------------------------------------------------------------
ReadScalarsPerElement(const char * fileName,const char * description,int timeStep,vtkMultiBlockDataSet * compositeOutput,int numberOfComponents,int component)1880 int vtkEnSightGoldBinaryReader::ReadScalarsPerElement(
1881   const char* fileName, const char* description, int timeStep,
1882   vtkMultiBlockDataSet *compositeOutput, int numberOfComponents,
1883   int component)
1884 {
1885   char line[80];
1886   int partId, realId, numCells, numCellsPerElement, i, idx;
1887   vtkFloatArray *scalars;
1888   float *scalarsRead;
1889   int lineRead, elementType;
1890   vtkDataSet *output;
1891 
1892   // Initialize
1893   //
1894   if (!fileName)
1895   {
1896     vtkErrorMacro("nullptr ScalarPerElement variable file name");
1897     return 0;
1898   }
1899   std::string sfilename;
1900   if (this->FilePath)
1901   {
1902     sfilename = this->FilePath;
1903     if (sfilename.at(sfilename.length()-1) != '/')
1904     {
1905       sfilename += "/";
1906     }
1907     sfilename += fileName;
1908     vtkDebugMacro("full path to scalar per element file: "
1909       << sfilename.c_str());
1910   }
1911   else
1912   {
1913     sfilename = fileName;
1914   }
1915 
1916   if (this->OpenFile(sfilename.c_str()) == 0)
1917   {
1918     vtkErrorMacro("Unable to open file: " << sfilename.c_str());
1919     return 0;
1920   }
1921 
1922   if (this->UseFileSets)
1923   {
1924     this->AddFileIndexToCache(fileName);
1925 
1926     i = this->SeekToCachedTimeStep(fileName, timeStep-1);
1927     // start w/ the number of TS we skipped, not the one we are at
1928     // if we are not at the appropriate time step yet, we keep searching
1929     for (; i < timeStep - 1; i++)
1930     {
1931       this->ReadLine(line);
1932       while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1933       {
1934         this->ReadLine(line);
1935       }
1936        // found a time step -> cache it
1937       this->AddTimeStepToCache(fileName, i, this->GoldIFile->tellg());
1938 
1939       this->ReadLine(line); // skip the description line
1940       lineRead = this->ReadLine(line); // "part"
1941 
1942       while (lineRead && strncmp(line, "part", 4) == 0)
1943       {
1944         this->ReadPartId(&partId);
1945         partId--; // EnSight starts #ing with 1.
1946         realId = this->InsertNewPartId(partId);
1947         output = this->GetDataSetFromBlock(compositeOutput, realId);
1948         numCells = output->GetNumberOfCells();
1949         if (numCells)
1950         {
1951           this->ReadLine(line); // element type or "block"
1952 
1953           // need to find out from CellIds how many cells we have of this
1954           // element type (and what their ids are) -- IF THIS IS NOT A BLOCK
1955           // SECTION
1956           if (strncmp(line, "block", 5) == 0)
1957           {
1958             // Skip over float scalars.
1959             this->GoldIFile->seekg(sizeof(float)*numCells, ios::cur);
1960             lineRead = this->ReadLine(line);
1961           }
1962           else
1963           {
1964             while (lineRead && strncmp(line, "part", 4) != 0 &&
1965               strncmp(line, "END TIME STEP", 13) != 0)
1966             {
1967               elementType = this->GetElementType(line);
1968               if (elementType == -1)
1969               {
1970                 vtkErrorMacro("Unknown element type \"" << line << "\"");
1971                 if (this->GoldIFile)
1972                 {
1973                   this->GoldIFile->close();
1974                   delete this->GoldIFile;
1975                   this->GoldIFile = nullptr;
1976                 }
1977                 return 0;
1978               }
1979               idx = this->UnstructuredPartIds->IsId(realId);
1980               numCellsPerElement = this->GetCellIds(idx, elementType)->
1981                 GetNumberOfIds();
1982               this->GoldIFile->seekg(sizeof(float)*numCellsPerElement, ios::cur);
1983               lineRead = this->ReadLine(line);
1984             }
1985           } // end while
1986         } // end if (numCells)
1987         else
1988         {
1989           lineRead = this->ReadLine(line);
1990         }
1991       } // end while
1992     } // end for
1993     this->ReadLine(line);
1994     while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
1995     {
1996       this->ReadLine(line);
1997     }
1998   }
1999 
2000   this->ReadLine(line); // skip the description line
2001   lineRead = this->ReadLine(line); // "part"
2002 
2003   while (lineRead && strncmp(line, "part", 4) == 0)
2004   {
2005     this->ReadPartId(&partId);
2006     partId--; // EnSight starts #ing with 1.
2007     realId = this->InsertNewPartId(partId);
2008     output = this->GetDataSetFromBlock(compositeOutput, realId);
2009     numCells = output->GetNumberOfCells();
2010     if (numCells)
2011     {
2012       this->ReadLine(line); // element type or "block"
2013       if (component == 0)
2014       {
2015         scalars = vtkFloatArray::New();
2016         scalars->SetNumberOfComponents(numberOfComponents);
2017         scalars->SetNumberOfTuples(numCells);
2018       }
2019       else
2020       {
2021         scalars = (vtkFloatArray*)(output->GetCellData()->GetArray(description));
2022       }
2023 
2024       // need to find out from CellIds how many cells we have of this element
2025       // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION
2026       if (strncmp(line, "block", 5) == 0)
2027       {
2028         scalarsRead = new float[numCells];
2029         this->ReadFloatArray(scalarsRead, numCells);
2030         for (i = 0; i < numCells; i++)
2031         {
2032           scalars->SetComponent(i, component, scalarsRead[i]);
2033         }
2034         if (this->GoldIFile->eof())
2035         {
2036           lineRead = 0;
2037         }
2038         else
2039         {
2040           lineRead = this->ReadLine(line);
2041         }
2042         delete [] scalarsRead;
2043       }
2044       else
2045       {
2046         while (lineRead && strncmp(line, "part", 4) != 0 &&
2047           strncmp(line, "END TIME STEP", 13) != 0)
2048         {
2049           elementType = this->GetElementType(line);
2050           if (elementType == -1)
2051           {
2052             vtkErrorMacro("Unknown element type \"" << line << "\"");
2053             if (this->GoldIFile)
2054             {
2055               this->GoldIFile->close();
2056               delete this->GoldIFile;
2057               this->GoldIFile = nullptr;
2058             }
2059             if (component == 0)
2060             {
2061               scalars->Delete();
2062             }
2063             return 0;
2064           }
2065           idx = this->UnstructuredPartIds->IsId(realId);
2066           numCellsPerElement =
2067             this->GetCellIds(idx, elementType)->GetNumberOfIds();
2068           scalarsRead = new float[numCellsPerElement];
2069           this->ReadFloatArray(scalarsRead, numCellsPerElement);
2070           for (i = 0; i < numCellsPerElement; i++)
2071           {
2072             scalars->SetComponent(this->GetCellIds(idx, elementType)->GetId(i),
2073               component, scalarsRead[i]);
2074           }
2075           this->GoldIFile->peek();
2076           if (this->GoldIFile->eof())
2077           {
2078             lineRead = 0;
2079           }
2080           else
2081           {
2082             lineRead = this->ReadLine(line);
2083           }
2084           delete [] scalarsRead;
2085         } // end while
2086       } // end else
2087       if (component == 0)
2088       {
2089         scalars->SetName(description);
2090         output->GetCellData()->AddArray(scalars);
2091         if (!output->GetCellData()->GetScalars())
2092         {
2093           output->GetCellData()->SetScalars(scalars);
2094         }
2095         scalars->Delete();
2096       }
2097       else
2098       {
2099         output->GetCellData()->AddArray(scalars);
2100       }
2101     }
2102     else
2103     {
2104       this->GoldIFile->peek();
2105       if (this->GoldIFile->eof())
2106       {
2107         lineRead = 0;
2108       }
2109       else
2110       {
2111         lineRead = this->ReadLine(line);
2112       }
2113     }
2114   }
2115 
2116   if (this->GoldIFile)
2117   {
2118     this->GoldIFile->close();
2119     delete this->GoldIFile;
2120     this->GoldIFile = nullptr;
2121   }
2122   return 1;
2123 }
2124 
2125 //----------------------------------------------------------------------------
ReadVectorsPerElement(const char * fileName,const char * description,int timeStep,vtkMultiBlockDataSet * compositeOutput)2126 int vtkEnSightGoldBinaryReader::ReadVectorsPerElement(
2127   const char* fileName, const char* description, int timeStep,
2128   vtkMultiBlockDataSet *compositeOutput)
2129 {
2130   char line[80];
2131   int partId, realId, numCells, numCellsPerElement, i, idx;
2132   vtkFloatArray *vectors;
2133   float *comp1, *comp2, *comp3;
2134   int lineRead, elementType;
2135   float tuple[3];
2136   vtkDataSet *output;
2137 
2138   // Initialize
2139   //
2140   if (!fileName)
2141   {
2142     vtkErrorMacro("nullptr VectorPerElement variable file name");
2143     return 0;
2144   }
2145   std::string sfilename;
2146   if (this->FilePath)
2147   {
2148     sfilename = this->FilePath;
2149     if (sfilename.at(sfilename.length()-1) != '/')
2150     {
2151       sfilename += "/";
2152     }
2153     sfilename += fileName;
2154     vtkDebugMacro("full path to vector per element file: "
2155       << sfilename.c_str());
2156   }
2157   else
2158   {
2159     sfilename = fileName;
2160   }
2161 
2162   if (this->OpenFile(sfilename.c_str()) == 0)
2163   {
2164     vtkErrorMacro("Unable to open file: " << sfilename.c_str());
2165     return 0;
2166   }
2167 
2168   if (this->UseFileSets)
2169   {
2170     this->AddFileIndexToCache(fileName);
2171 
2172     i = this->SeekToCachedTimeStep(fileName, timeStep-1);
2173     // start w/ the number of TS we skipped, not the one we are at
2174     // if we are not at the appropriate time step yet, we keep searching
2175     for (; i < timeStep - 1; i++)
2176     {
2177       this->ReadLine(line);
2178       while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
2179       {
2180         this->ReadLine(line);
2181       }
2182        // found a time step -> cache it
2183       this->AddTimeStepToCache(fileName, i, this->GoldIFile->tellg());
2184 
2185       this->ReadLine(line); // skip the description line
2186       lineRead = this->ReadLine(line); // "part"
2187 
2188       while (lineRead && strncmp(line, "part", 4) == 0)
2189       {
2190         this->ReadPartId(&partId);
2191         partId--; // EnSight starts #ing with 1.
2192         realId = this->InsertNewPartId(partId);
2193         output = this->GetDataSetFromBlock(compositeOutput, realId);
2194         numCells = output->GetNumberOfCells();
2195         if (numCells)
2196         {
2197           this->ReadLine(line); // element type or "block"
2198 
2199           // need to find out from CellIds how many cells we have of this
2200           // element type (and what their ids are) -- IF THIS IS NOT A BLOCK
2201           // SECTION
2202           if (strncmp(line, "block", 5) == 0)
2203           {
2204             // Skip over comp1, comp2 and comp3
2205             this->GoldIFile->seekg(sizeof(float)*3*numCells, ios::cur);
2206             lineRead = this->ReadLine(line);
2207           }
2208           else
2209           {
2210             while (lineRead && strncmp(line, "part", 4) != 0 &&
2211               strncmp(line, "END TIME STEP", 13) != 0)
2212             {
2213               elementType = this->GetElementType(line);
2214               if (elementType == -1)
2215               {
2216                 vtkErrorMacro("Unknown element type \"" << line << "\"");
2217                 delete this->IS;
2218                 this->IS = nullptr;
2219                 return 0;
2220               }
2221               idx = this->UnstructuredPartIds->IsId(realId);
2222               numCellsPerElement = this->GetCellIds(idx, elementType)->
2223                 GetNumberOfIds();
2224               // Skip over comp1, comp2 and comp3
2225               this->GoldIFile->seekg(sizeof(float)*3*numCellsPerElement, ios::cur);
2226               lineRead = this->ReadLine(line);
2227             } // end while
2228           } // end else
2229         }
2230         else
2231         {
2232           lineRead = this->ReadLine(line);
2233         }
2234       }
2235     }
2236     this->ReadLine(line);
2237     while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
2238     {
2239       this->ReadLine(line);
2240     }
2241   }
2242 
2243   this->ReadLine(line); // skip the description line
2244   lineRead = this->ReadLine(line); // "part"
2245 
2246   while (lineRead && strncmp(line, "part", 4) == 0)
2247   {
2248     this->ReadPartId(&partId);
2249     partId--; // EnSight starts #ing with 1.
2250     realId = this->InsertNewPartId(partId);
2251     output = this->GetDataSetFromBlock(compositeOutput, realId);
2252     numCells = output->GetNumberOfCells();
2253     if (numCells)
2254     {
2255       vectors = vtkFloatArray::New();
2256       this->ReadLine(line); // element type or "block"
2257       vectors->SetNumberOfComponents(3);
2258       vectors->SetNumberOfTuples(numCells);
2259       // need to find out from CellIds how many cells we have of this element
2260       // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION
2261       if (strncmp(line, "block", 5) == 0)
2262       {
2263         comp1 = new float[numCells];
2264         comp2 = new float[numCells];
2265         comp3 = new float[numCells];
2266         this->ReadFloatArray(comp1, numCells);
2267         this->ReadFloatArray(comp2, numCells);
2268         this->ReadFloatArray(comp3, numCells);
2269         for (i = 0; i < numCells; i++)
2270         {
2271           tuple[0] = comp1[i];
2272           tuple[1] = comp2[i];
2273           tuple[2] = comp3[i];
2274           vectors->SetTuple(i, tuple);
2275         }
2276         this->GoldIFile->peek();
2277         if (this->GoldIFile->eof())
2278         {
2279           lineRead = 0;
2280         }
2281         else
2282         {
2283           lineRead = this->ReadLine(line);
2284         }
2285         delete [] comp1;
2286         delete [] comp2;
2287         delete [] comp3;
2288       }
2289       else
2290       {
2291         while (lineRead && strncmp(line, "part", 4) != 0 &&
2292           strncmp(line, "END TIME STEP", 13) != 0)
2293         {
2294           elementType = this->GetElementType(line);
2295           if (elementType == -1)
2296           {
2297             vtkErrorMacro("Unknown element type \"" << line << "\"");
2298             delete this->IS;
2299             this->IS = nullptr;
2300             vectors->Delete();
2301             return 0;
2302           }
2303           idx = this->UnstructuredPartIds->IsId(realId);
2304           numCellsPerElement =
2305             this->GetCellIds(idx, elementType)->GetNumberOfIds();
2306           comp1 = new float[numCellsPerElement];
2307           comp2 = new float[numCellsPerElement];
2308           comp3 = new float[numCellsPerElement];
2309           this->ReadFloatArray(comp1, numCellsPerElement);
2310           this->ReadFloatArray(comp2, numCellsPerElement);
2311           this->ReadFloatArray(comp3, numCellsPerElement);
2312           for (i = 0; i < numCellsPerElement; i++)
2313           {
2314             tuple[0] = comp1[i];
2315             tuple[1] = comp2[i];
2316             tuple[2] = comp3[i];
2317             vectors->SetTuple(this->GetCellIds(idx, elementType)->GetId(i),
2318               tuple);
2319           }
2320           this->GoldIFile->peek();
2321           if (this->GoldIFile->eof())
2322           {
2323             lineRead = 0;
2324           }
2325           else
2326           {
2327             lineRead = this->ReadLine(line);
2328           }
2329           delete [] comp1;
2330           delete [] comp2;
2331           delete [] comp3;
2332         } // end while
2333       } // end else
2334       vectors->SetName(description);
2335       output->GetCellData()->AddArray(vectors);
2336       if (!output->GetCellData()->GetVectors())
2337       {
2338         output->GetCellData()->SetVectors(vectors);
2339       }
2340       vectors->Delete();
2341     }
2342     else
2343     {
2344       this->GoldIFile->peek();
2345       if (this->GoldIFile->eof())
2346       {
2347         lineRead = 0;
2348       }
2349       else
2350       {
2351         lineRead = this->ReadLine(line);
2352       }
2353     }
2354   }
2355 
2356   if (this->GoldIFile)
2357   {
2358     this->GoldIFile->close();
2359     delete this->GoldIFile;
2360     this->GoldIFile = nullptr;
2361   }
2362   return 1;
2363 }
2364 
2365 //----------------------------------------------------------------------------
ReadTensorsPerElement(const char * fileName,const char * description,int timeStep,vtkMultiBlockDataSet * compositeOutput)2366 int vtkEnSightGoldBinaryReader::ReadTensorsPerElement(
2367   const char* fileName, const char* description, int timeStep,
2368   vtkMultiBlockDataSet *compositeOutput)
2369 {
2370   char line[80];
2371   int partId, realId, numCells, numCellsPerElement, i, idx;
2372   vtkFloatArray *tensors;
2373   int lineRead, elementType;
2374   float *comp1, *comp2, *comp3, *comp4, *comp5, *comp6;
2375   float tuple[6];
2376   vtkDataSet *output;
2377 
2378   // Initialize
2379   //
2380   if (!fileName)
2381   {
2382     vtkErrorMacro("nullptr TensorPerElement variable file name");
2383     return 0;
2384   }
2385   std::string sfilename;
2386   if (this->FilePath)
2387   {
2388     sfilename = this->FilePath;
2389     if (sfilename.at(sfilename.length()-1) != '/')
2390     {
2391       sfilename += "/";
2392     }
2393     sfilename += fileName;
2394     vtkDebugMacro("full path to  tensor per element file: "
2395       << sfilename.c_str());
2396   }
2397   else
2398   {
2399     sfilename = fileName;
2400   }
2401 
2402   if (this->OpenFile(sfilename.c_str()) == 0)
2403   {
2404     vtkErrorMacro("Unable to open file: " << sfilename.c_str());
2405     return 0;
2406   }
2407 
2408   if (this->UseFileSets)
2409   {
2410     this->AddFileIndexToCache(fileName);
2411 
2412     i = this->SeekToCachedTimeStep(fileName, timeStep-1);
2413     // start w/ the number of TS we skipped, not the one we are at
2414     // if we are not at the appropriate time step yet, we keep searching
2415     for (; i < timeStep - 1; i++)
2416     {
2417       this->ReadLine(line);
2418       while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
2419       {
2420         this->ReadLine(line);
2421       }
2422       // found a time step -> cache it
2423       this->AddTimeStepToCache(fileName, i, this->GoldIFile->tellg());
2424 
2425       this->ReadLine(line); // skip the description line
2426       lineRead = this->ReadLine(line); // "part"
2427 
2428       while (lineRead && strncmp(line, "part", 4) == 0)
2429       {
2430         this->ReadPartId(&partId);
2431         partId--; // EnSight starts #ing with 1.
2432         realId = this->InsertNewPartId(partId);
2433         output = this->GetDataSetFromBlock(compositeOutput, realId);
2434         numCells = output->GetNumberOfCells();
2435         if (numCells)
2436         {
2437           this->ReadLine(line); // element type or "block"
2438 
2439           // need to find out from CellIds how many cells we have of this
2440           // element type (and what their ids are) -- IF THIS IS NOT A BLOCK
2441           // SECTION
2442           if (strncmp(line, "block", 5) == 0)
2443           {
2444             // Skip comp1 - comp6
2445             this->GoldIFile->seekg(sizeof(float)*6*numCells, ios::cur);
2446             lineRead = this->ReadLine(line);
2447           }
2448           else
2449           {
2450             while (lineRead && strncmp(line, "part", 4) != 0 &&
2451               strncmp(line, "END TIME STEP", 13) != 0)
2452             {
2453               elementType = this->GetElementType(line);
2454               if (elementType == -1)
2455               {
2456                 vtkErrorMacro("Unknown element type \"" << line << "\"");
2457                 delete this->IS;
2458                 this->IS = nullptr;
2459                 return 0;
2460               }
2461               idx = this->UnstructuredPartIds->IsId(realId);
2462               numCellsPerElement = this->GetCellIds(idx, elementType)->
2463                 GetNumberOfIds();
2464               // Skip over comp1->comp6
2465               this->GoldIFile->seekg(sizeof(float)*6*numCellsPerElement, ios::cur);
2466               lineRead = this->ReadLine(line);
2467             } // end while
2468           } // end else
2469         } // end if (numCells)
2470         else
2471         {
2472           lineRead = this->ReadLine(line);
2473         }
2474       }
2475     }
2476     this->ReadLine(line);
2477     while (strncmp(line, "BEGIN TIME STEP", 15) != 0)
2478     {
2479       this->ReadLine(line);
2480     }
2481   }
2482 
2483   this->ReadLine(line); // skip the description line
2484   lineRead = this->ReadLine(line); // "part"
2485 
2486   while (lineRead && strncmp(line, "part", 4) == 0)
2487   {
2488     this->ReadPartId(&partId);
2489     partId--; // EnSight starts #ing with 1.
2490     realId = this->InsertNewPartId(partId);
2491     output = this->GetDataSetFromBlock(compositeOutput, realId);
2492     numCells = output->GetNumberOfCells();
2493     if (numCells)
2494     {
2495       tensors = vtkFloatArray::New();
2496       this->ReadLine(line); // element type or "block"
2497       tensors->SetNumberOfComponents(6);
2498       tensors->SetNumberOfTuples(numCells);
2499 
2500       // need to find out from CellIds how many cells we have of this element
2501       // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION
2502       if (strncmp(line, "block", 5) == 0)
2503       {
2504         comp1 = new float[numCells];
2505         comp2 = new float[numCells];
2506         comp3 = new float[numCells];
2507         comp4 = new float[numCells];
2508         comp5 = new float[numCells];
2509         comp6 = new float[numCells];
2510         this->ReadFloatArray(comp1, numCells);
2511         this->ReadFloatArray(comp2, numCells);
2512         this->ReadFloatArray(comp3, numCells);
2513         this->ReadFloatArray(comp4, numCells);
2514         this->ReadFloatArray(comp6, numCells);
2515         this->ReadFloatArray(comp5, numCells);
2516         for (i = 0; i < numCells; i++)
2517         {
2518           tuple[0] = comp1[i];
2519           tuple[1] = comp2[i];
2520           tuple[2] = comp3[i];
2521           tuple[3] = comp4[i];
2522           tuple[4] = comp5[i];
2523           tuple[5] = comp6[i];
2524           tensors->InsertTuple(i, tuple);
2525         }
2526         this->GoldIFile->peek();
2527         if (this->GoldIFile->eof())
2528         {
2529           lineRead = 0;
2530         }
2531         else
2532         {
2533           lineRead = this->ReadLine(line);
2534         }
2535         delete [] comp1;
2536         delete [] comp2;
2537         delete [] comp3;
2538         delete [] comp4;
2539         delete [] comp5;
2540         delete [] comp6;
2541       }
2542       else
2543       {
2544         while (lineRead && strncmp(line, "part", 4) != 0 &&
2545           strncmp(line, "END TIME STEP", 13) != 0)
2546         {
2547           elementType = this->GetElementType(line);
2548           if (elementType == -1)
2549           {
2550             vtkErrorMacro("Unknown element type \"" << line << "\"");
2551             delete this->IS;
2552             this->IS = nullptr;
2553             tensors->Delete();
2554             return 0;
2555           }
2556           idx = this->UnstructuredPartIds->IsId(realId);
2557           numCellsPerElement =
2558             this->GetCellIds(idx, elementType)->GetNumberOfIds();
2559           comp1 = new float[numCellsPerElement];
2560           comp2 = new float[numCellsPerElement];
2561           comp3 = new float[numCellsPerElement];
2562           comp4 = new float[numCellsPerElement];
2563           comp5 = new float[numCellsPerElement];
2564           comp6 = new float[numCellsPerElement];
2565           this->ReadFloatArray(comp1, numCellsPerElement);
2566           this->ReadFloatArray(comp2, numCellsPerElement);
2567           this->ReadFloatArray(comp3, numCellsPerElement);
2568           this->ReadFloatArray(comp4, numCellsPerElement);
2569           this->ReadFloatArray(comp6, numCellsPerElement);
2570           this->ReadFloatArray(comp5, numCellsPerElement);
2571           for (i = 0; i < numCellsPerElement; i++)
2572           {
2573             tuple[0] = comp1[i];
2574             tuple[1] = comp2[i];
2575             tuple[2] = comp3[i];
2576             tuple[3] = comp4[i];
2577             tuple[4] = comp5[i];
2578             tuple[5] = comp6[i];
2579             tensors->InsertTuple(this->GetCellIds(idx, elementType)->GetId(i),
2580               tuple);
2581           }
2582           this->GoldIFile->peek();
2583           if (this->GoldIFile->eof())
2584           {
2585             lineRead = 0;
2586           }
2587           else
2588           {
2589             lineRead = this->ReadLine(line);
2590           }
2591           delete [] comp1;
2592           delete [] comp2;
2593           delete [] comp3;
2594           delete [] comp4;
2595           delete [] comp5;
2596           delete [] comp6;
2597         } // end while
2598       } // end else
2599       tensors->SetName(description);
2600       output->GetCellData()->AddArray(tensors);
2601       tensors->Delete();
2602     }
2603     else
2604     {
2605       this->GoldIFile->peek();
2606       if (this->GoldIFile->eof())
2607       {
2608         lineRead = 0;
2609       }
2610       else
2611       {
2612         lineRead = this->ReadLine(line);
2613       }
2614     }
2615   }
2616 
2617   if (this->GoldIFile)
2618   {
2619     this->GoldIFile->close();
2620     delete this->GoldIFile;
2621     this->GoldIFile = nullptr;
2622   }
2623   return 1;
2624 }
2625 
2626 //----------------------------------------------------------------------------
CreateUnstructuredGridOutput(int partId,char line[80],const char * name,vtkMultiBlockDataSet * compositeOutput)2627 int vtkEnSightGoldBinaryReader::CreateUnstructuredGridOutput(
2628   int partId, char line[80], const char* name,
2629   vtkMultiBlockDataSet *compositeOutput)
2630 {
2631   int lineRead = 1;
2632   int i, j;
2633   vtkIdType *nodeIds;
2634   int *nodeIdList;
2635   int numElements;
2636   int idx, cellId, cellType;
2637   float *xCoords, *yCoords, *zCoords;
2638 
2639   this->NumberOfNewOutputs++;
2640 
2641   if (this->GetDataSetFromBlock(compositeOutput, partId) == nullptr ||
2642     !this->GetDataSetFromBlock(compositeOutput, partId)->IsA("vtkUnstructuredGrid"))
2643   {
2644     vtkDebugMacro("creating new unstructured output");
2645     vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
2646     this->AddToBlock(compositeOutput, partId, ugrid);
2647     ugrid->Delete();
2648 
2649     this->UnstructuredPartIds->InsertNextId(partId);
2650   }
2651 
2652   vtkUnstructuredGrid* output = vtkUnstructuredGrid::SafeDownCast(
2653     this->GetDataSetFromBlock(compositeOutput, partId));
2654   this->SetBlockName(compositeOutput, partId, name);
2655 
2656   // Clear all cell ids from the last execution, if any.
2657   idx = this->UnstructuredPartIds->IsId(partId);
2658   for (i = 0; i < vtkEnSightReader::NUMBER_OF_ELEMENT_TYPES; i++)
2659   {
2660     this->GetCellIds(idx, i)->Reset();
2661   }
2662 
2663   output->Allocate(1000);
2664 
2665   while(lineRead && strncmp(line, "part", 4) != 0)
2666   {
2667     if (strncmp(line, "coordinates", 11) == 0)
2668     {
2669       vtkDebugMacro("coordinates");
2670       int numPts;
2671 
2672       this->ReadInt(&numPts);
2673       if (numPts < 0 || static_cast<unsigned int>(numPts * this->SizeOfInt) > this->FileSize)
2674       {
2675         vtkErrorMacro("Invalid number of unstructured points read; check that ByteOrder is set correctly.");
2676         return -1;
2677       }
2678 
2679       vtkPoints *points = vtkPoints::New();
2680       vtkDebugMacro("num. points: " << numPts);
2681 
2682       points->Allocate(numPts);
2683 
2684       if (this->NodeIdsListed)
2685       {
2686         this->GoldIFile->seekg(sizeof(int)*numPts, ios::cur);
2687       }
2688 
2689       xCoords = new float[numPts];
2690       yCoords = new float[numPts];
2691       zCoords = new float[numPts];
2692       this->ReadFloatArray(xCoords, numPts);
2693       this->ReadFloatArray(yCoords, numPts);
2694       this->ReadFloatArray(zCoords, numPts);
2695 
2696       for (i = 0; i < numPts; i++)
2697       {
2698         points->InsertNextPoint(xCoords[i], yCoords[i], zCoords[i]);
2699       }
2700 
2701       output->SetPoints(points);
2702       points->Delete();
2703       delete [] xCoords;
2704       delete [] yCoords;
2705       delete [] zCoords;
2706     }
2707     else if (strncmp(line, "point", 5) == 0)
2708     {
2709       vtkDebugMacro("point");
2710 
2711       this->ReadInt(&numElements);
2712       if (numElements < 0 ||
2713         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
2714       {
2715         vtkErrorMacro("Invalid number of point cells; check that ByteOrder is set correctly.");
2716         return -1;
2717       }
2718 
2719       nodeIds = new vtkIdType[1];
2720 
2721       if (this->ElementIdsListed)
2722       {
2723         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2724       }
2725 
2726       nodeIdList = new int[numElements];
2727       this->ReadIntArray(nodeIdList, numElements);
2728 
2729       for (i = 0; i < numElements; i++)
2730       {
2731         nodeIds[0] = nodeIdList[i] - 1;
2732         cellId = output->InsertNextCell(VTK_VERTEX, 1, nodeIds);
2733         this->GetCellIds(idx, vtkEnSightReader::POINT)->InsertNextId(cellId);
2734       }
2735 
2736       delete [] nodeIds;
2737       delete [] nodeIdList;
2738     }
2739     else if (strncmp(line, "g_point", 7) == 0)
2740     {
2741       // skipping ghost cells
2742       vtkDebugMacro("g_point");
2743 
2744       this->ReadInt(&numElements);
2745       if (numElements < 0 ||
2746         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
2747       {
2748         vtkErrorMacro("Invalid number of g_point cells; check that ByteOrder is set correctly.");
2749         return -1;
2750       }
2751       if (this->ElementIdsListed)
2752       { // skip element ids.
2753         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2754       }
2755 
2756       // Skip nodeIdList.
2757       this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2758     }
2759     else if (strncmp(line, "bar2", 4) == 0)
2760     {
2761       vtkDebugMacro("bar2");
2762 
2763       this->ReadInt(&numElements);
2764       if (numElements < 0 ||
2765         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
2766       {
2767         vtkErrorMacro("Invalid number of bar2 cells; check that ByteOrder is set correctly.");
2768         return -1;
2769       }
2770       nodeIds = new vtkIdType[2];
2771       if (this->ElementIdsListed)
2772       {
2773         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2774       }
2775 
2776       nodeIdList = new int[numElements * 2];
2777       this->ReadIntArray(nodeIdList, numElements * 2);
2778 
2779       for (i = 0; i < numElements; i++)
2780       {
2781         for (j = 0; j < 2; j++)
2782         {
2783           nodeIds[j] = nodeIdList[2*i+j] - 1;
2784         }
2785         cellId = output->InsertNextCell(VTK_LINE, 2, nodeIds);
2786         this->GetCellIds(idx, vtkEnSightReader::BAR2)->InsertNextId(cellId);
2787       }
2788 
2789       delete [] nodeIds;
2790       delete [] nodeIdList;
2791     }
2792     else if (strncmp(line, "g_bar2", 6) == 0)
2793     {
2794       // skipping ghost cells
2795       vtkDebugMacro("g_bar2");
2796 
2797       this->ReadInt(&numElements);
2798       if (numElements < 0 ||
2799         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
2800       {
2801         vtkErrorMacro("Invalid number of g_bar2 cells; check that ByteOrder is set correctly.");
2802         return -1;
2803       }
2804       if (this->ElementIdsListed)
2805       {
2806         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2807       }
2808 
2809       // Skip nodeIdList.
2810       this->GoldIFile->seekg(sizeof(int)*2*numElements, ios::cur);
2811     }
2812     else if (strncmp(line, "bar3", 4) == 0)
2813     {
2814       vtkDebugMacro("bar3");
2815 
2816       this->ReadInt(&numElements);
2817       if (numElements < 0 ||
2818         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
2819       {
2820         vtkErrorMacro("Invalid number of bar3 cells; check that ByteOrder is set correctly.");
2821         return -1;
2822       }
2823       nodeIds = new vtkIdType[3];
2824 
2825       if (this->ElementIdsListed)
2826       {
2827         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2828       }
2829 
2830       nodeIdList = new int[numElements*3];
2831       this->ReadIntArray(nodeIdList, numElements*3);
2832 
2833       for (i = 0; i < numElements; i++)
2834       {
2835         nodeIds[0] = nodeIdList[3*i]-1;
2836         nodeIds[1] = nodeIdList[3*i+2]-1;
2837         nodeIds[2] = nodeIdList[3*i+1]-1;
2838 
2839         cellId = output->InsertNextCell(VTK_QUADRATIC_EDGE, 3, nodeIds);
2840         this->GetCellIds(idx, vtkEnSightReader::BAR3)->InsertNextId(cellId);
2841       }
2842 
2843       delete [] nodeIds;
2844       delete [] nodeIdList;
2845     }
2846     else if (strncmp(line, "g_bar3", 6) == 0)
2847     {
2848       // skipping ghost cells
2849       vtkDebugMacro("g_bar3");
2850 
2851       this->ReadInt(&numElements);
2852       if (numElements < 0 ||
2853         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
2854       {
2855         vtkErrorMacro("Invalid number of g_bar3 cells; check that ByteOrder is set correctly.");
2856         return -1;
2857       }
2858 
2859       if (this->ElementIdsListed)
2860       {
2861         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2862       }
2863 
2864       // Skip nodeIdList.
2865       this->GoldIFile->seekg(sizeof(int)*2*numElements, ios::cur);
2866     }
2867     else if (strncmp(line, "nsided", 6) == 0)
2868     {
2869       vtkDebugMacro("nsided");
2870       int *numNodesPerElement;
2871       int numNodes = 0;
2872       int nodeCount = 0;
2873 
2874       cellType = vtkEnSightReader::NSIDED;
2875       this->ReadInt(&numElements);
2876       if (numElements < 0 ||
2877         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
2878       {
2879         vtkErrorMacro("Invalid number of nsided cells; check that ByteOrder is set correctly.");
2880         return -1;
2881       }
2882 
2883       if (this->ElementIdsListed)
2884       {
2885         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2886       }
2887 
2888       numNodesPerElement = new int[numElements];
2889       this->ReadIntArray(numNodesPerElement, numElements);
2890       for (i = 0; i < numElements; i++)
2891       {
2892         numNodes += numNodesPerElement[i];
2893       }
2894       nodeIdList = new int[numNodes];
2895       this->ReadIntArray(nodeIdList, numNodes);
2896 
2897       for (i = 0; i < numElements; i++)
2898       {
2899         nodeIds = new vtkIdType[numNodesPerElement[i]];
2900         for (j = 0; j < numNodesPerElement[i]; j++)
2901         {
2902           nodeIds[j] = nodeIdList[nodeCount] - 1;
2903           nodeCount++;
2904         }
2905         cellId = output->InsertNextCell(VTK_POLYGON,
2906           numNodesPerElement[i],
2907           nodeIds);
2908         this->GetCellIds(idx, cellType)->InsertNextId(cellId);
2909 
2910         delete [] nodeIds;
2911       }
2912 
2913       delete [] nodeIdList;
2914       delete [] numNodesPerElement;
2915     }
2916     else if (strncmp(line, "g_nsided", 8) == 0)
2917     {
2918       // skipping ghost cells
2919       vtkDebugMacro("g_nsided");
2920       int *numNodesPerElement;
2921       int numNodes = 0;
2922 
2923       //cellType = vtkEnSightReader::NSIDED;
2924       this->ReadInt(&numElements);
2925       if (numElements < 0 ||
2926         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
2927       {
2928         vtkErrorMacro("Invalid number of g_nsided cells; check that ByteOrder is set correctly.");
2929         return -1;
2930       }
2931 
2932       if (this->ElementIdsListed)
2933       {
2934         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2935       }
2936 
2937       numNodesPerElement = new int[numElements];
2938       this->ReadIntArray(numNodesPerElement, numElements);
2939       for (i = 0; i < numElements; i++)
2940       {
2941         numNodes += numNodesPerElement[i];
2942       }
2943       // Skip nodeIdList.
2944       this->GoldIFile->seekg(sizeof(int)*numNodes, ios::cur);
2945       delete [] numNodesPerElement;
2946     }
2947     else if (strncmp(line, "tria3", 5) == 0 ||
2948       strncmp(line, "tria6", 5) == 0)
2949     {
2950       if (strncmp(line, "tria6", 5) == 0)
2951       {
2952         vtkDebugMacro("tria6");
2953         cellType = vtkEnSightReader::TRIA6;
2954       }
2955       else
2956       {
2957         vtkDebugMacro("tria3");
2958         cellType = vtkEnSightReader::TRIA3;
2959       }
2960 
2961       this->ReadInt(&numElements);
2962       if (numElements < 0 ||
2963         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
2964       {
2965         vtkErrorMacro("Invalid number of triangle cells; check that ByteOrder is set correctly.");
2966         return -1;
2967       }
2968 
2969       if (this->ElementIdsListed)
2970       {
2971         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
2972       }
2973 
2974       if (cellType == vtkEnSightReader::TRIA6)
2975       {
2976         nodeIds = new vtkIdType[6];
2977         nodeIdList = new int[numElements*6];
2978         this->ReadIntArray(nodeIdList, numElements*6);
2979       }
2980       else
2981       {
2982         nodeIds = new vtkIdType[3];
2983         nodeIdList = new int[numElements*3];
2984         this->ReadIntArray(nodeIdList, numElements*3);
2985       }
2986 
2987       for (i = 0; i < numElements; i++)
2988       {
2989         if (cellType == vtkEnSightReader::TRIA6)
2990         {
2991           for (j = 0; j < 6; j++)
2992           {
2993             nodeIds[j] = nodeIdList[6*i+j] - 1;
2994           }
2995           cellId = output->InsertNextCell(VTK_QUADRATIC_TRIANGLE, 6, nodeIds);
2996         }
2997         else
2998         {
2999           for (j = 0; j < 3; j++)
3000           {
3001             nodeIds[j] = nodeIdList[3*i+j] - 1;
3002           }
3003           cellId = output->InsertNextCell(VTK_TRIANGLE, 3, nodeIds);
3004         }
3005         this->GetCellIds(idx, cellType)->InsertNextId(cellId);
3006       }
3007 
3008       delete [] nodeIds;
3009       delete [] nodeIdList;
3010     }
3011     else if (strncmp(line, "g_tria3", 7) == 0 ||
3012       strncmp(line, "g_tria6", 7) == 0)
3013     {
3014       // skipping ghost cells
3015       if (strncmp(line, "g_tria6", 7) == 0)
3016       {
3017         vtkDebugMacro("g_tria6");
3018         cellType = vtkEnSightReader::TRIA6;
3019       }
3020       else
3021       {
3022         vtkDebugMacro("g_tria3");
3023         cellType = vtkEnSightReader::TRIA3;
3024       }
3025 
3026       this->ReadInt(&numElements);
3027       if (numElements < 0 ||
3028         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3029       {
3030         vtkErrorMacro("Invalid number of triangle cells; check that ByteOrder is set correctly.");
3031         return -1;
3032       }
3033       if (this->ElementIdsListed)
3034       {
3035         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3036       }
3037 
3038       if (cellType == vtkEnSightReader::TRIA6)
3039       {
3040         // Skip nodeIdList.
3041         this->GoldIFile->seekg(sizeof(int)*6*numElements, ios::cur);
3042       }
3043       else
3044       {
3045         // Skip nodeIdList.
3046         this->GoldIFile->seekg(sizeof(int)*3*numElements, ios::cur);
3047       }
3048     }
3049     else if (strncmp(line, "quad4", 5) == 0 ||
3050       strncmp(line, "quad8", 5) == 0)
3051     {
3052       if (strncmp(line, "quad8", 5) == 0)
3053       {
3054         vtkDebugMacro("quad8");
3055         cellType = vtkEnSightReader::QUAD8;
3056       }
3057       else
3058       {
3059         vtkDebugMacro("quad4");
3060         cellType = vtkEnSightReader::QUAD4;
3061       }
3062 
3063       this->ReadInt(&numElements);
3064       if (numElements < 0 ||
3065         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3066       {
3067         vtkErrorMacro("Invalid number of quad cells; check that ByteOrder is set correctly.");
3068         return -1;
3069       }
3070 
3071       if (this->ElementIdsListed)
3072       {
3073         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3074       }
3075 
3076       if (cellType == vtkEnSightReader::QUAD8)
3077       {
3078         nodeIds = new vtkIdType[8];
3079         nodeIdList = new int[numElements*8];
3080         this->ReadIntArray(nodeIdList, numElements*8);
3081       }
3082       else
3083       {
3084         nodeIds = new vtkIdType[4];
3085         nodeIdList = new int[numElements*4];
3086         this->ReadIntArray(nodeIdList, numElements*4);
3087       }
3088 
3089       for (i = 0; i < numElements; i++)
3090       {
3091         if (cellType == vtkEnSightReader::QUAD8)
3092         {
3093           for (j = 0; j < 8; j++)
3094           {
3095             nodeIds[j] = nodeIdList[8*i+j] - 1;
3096           }
3097           cellId = output->InsertNextCell(VTK_QUADRATIC_QUAD, 8, nodeIds);
3098         }
3099         else
3100         {
3101           for (j = 0; j < 4; j++)
3102           {
3103             nodeIds[j] = nodeIdList[4*i+j] - 1;
3104           }
3105           cellId = output->InsertNextCell(VTK_QUAD, 4, nodeIds);
3106         }
3107         this->GetCellIds(idx, cellType)->InsertNextId(cellId);
3108       }
3109 
3110       delete [] nodeIds;
3111       delete [] nodeIdList;
3112     }
3113     else if (strncmp(line, "g_quad4", 7) == 0 ||
3114       strncmp(line, "g_quad8", 7) == 0)
3115     {
3116       // skipping ghost cells
3117       if (strncmp(line, "g_quad8", 7) == 0)
3118       {
3119         vtkDebugMacro("g_quad8");
3120         cellType = vtkEnSightReader::QUAD8;
3121       }
3122       else
3123       {
3124         vtkDebugMacro("g_quad4");
3125         cellType = vtkEnSightReader::QUAD4;
3126       }
3127 
3128       this->ReadInt(&numElements);
3129       if (numElements < 0 ||
3130         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3131       {
3132         vtkErrorMacro("Invalid number of quad cells; check that ByteOrder is set correctly.");
3133         return -1;
3134       }
3135       if (this->ElementIdsListed)
3136       {
3137         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3138       }
3139 
3140       if (cellType == vtkEnSightReader::QUAD8)
3141       {
3142         // Skip nodeIdList.
3143         this->GoldIFile->seekg(sizeof(int)*8*numElements, ios::cur);
3144       }
3145       else
3146       {
3147         // Skip nodeIdList.
3148         this->GoldIFile->seekg(sizeof(int)*4*numElements, ios::cur);
3149       }
3150     }
3151 
3152     else if (strncmp(line, "nfaced", 6) == 0)
3153     {
3154       vtkDebugMacro("nfaced");
3155       int *numFacesPerElement;
3156       int *numNodesPerFace;
3157       int *numNodesPerElement;
3158       int *nodeMarker;
3159       int numPts = 0;
3160       int numFaces = 0;
3161       int numNodes = 0;
3162       int faceCount = 0;
3163       int nodeCount = 0;
3164       int elementNodeCount = 0;
3165 
3166       cellType = vtkEnSightReader::NFACED;
3167       this->ReadInt(&numElements);
3168       if (numElements < 0 ||
3169         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3170       {
3171         vtkErrorMacro("Invalid number of nfaced cells; check that ByteOrder is set correctly.");
3172         return -1;
3173       }
3174 
3175       if (this->ElementIdsListed)
3176       {
3177         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3178       }
3179 
3180       // array: number of faces per element
3181       numFacesPerElement = new int[numElements];
3182       this->ReadIntArray(numFacesPerElement, numElements);
3183 
3184       // array: number of nodes per face
3185       for (i = 0; i < numElements; i++)
3186       {
3187         numFaces += numFacesPerElement[i];
3188       }
3189       numNodesPerFace = new int[numFaces];
3190       this->ReadIntArray(numNodesPerFace, numFaces);
3191 
3192       // array: number of nodes per element
3193       // number of faces of all elements
3194       numNodesPerElement = new int[numElements];
3195       for (i = 0; i < numElements; i++)
3196       {
3197         numNodesPerElement[i] = 0;
3198         for (j = 0; j < numFacesPerElement[i]; j++)
3199         {
3200           numNodesPerElement[i] += numNodesPerFace[faceCount + j];
3201         }
3202         faceCount += numFacesPerElement[i];
3203       }
3204 
3205       //xxx begin
3206       //delete [] numFacesPerElement;
3207       //delete [] numNodesPerFace;
3208       //xxx end
3209 
3210       // number of nodes of all elements
3211       for (i = 0; i < numElements; i++)
3212       {
3213         numNodes += numNodesPerElement[i];
3214       }
3215 
3216       // allocate and init markers to determine unique points
3217       numPts = output->GetNumberOfPoints();
3218       nodeMarker = new int[numPts];
3219       for (i = 0; i < numPts; i++)
3220       {
3221         nodeMarker[i] = -1;
3222       }
3223 
3224       // array: node Ids of all elements
3225       // NOTE:  each node Id is usually referenced multiple times in a
3226       //        polyhedron and therefore nodeIdList is not a set of
3227       //        UNIQUE point Ids (instead it an RAW list)
3228       nodeIdList = new int[numNodes];
3229       this->ReadIntArray(nodeIdList, numNodes);
3230 
3231       // yyy begin
3232       int         k;              // indexing each node Id of a face
3233       int         faceIdx = 0;    // indexing faces throughout all polyhedra
3234       int         nodeIdx = 0;    // indexing nodes throughout all polyhedra
3235       int         arayIdx = 0;    // indexing the array of Ids (info of faces)
3236       vtkIdType * faceAry = nullptr; // array of Ids describing a vtkPolyhedron
3237       // yyy end
3238 
3239       for (i = 0; i < numElements; i++)
3240       {
3241         elementNodeCount = 0;
3242         nodeIds = new vtkIdType[numNodesPerElement[i]];
3243 
3244         // yyy begin
3245         arayIdx = 0;
3246         faceAry = new vtkIdType[ numFacesPerElement[i] +
3247                                  numNodesPerElement[i] ];
3248         for ( j = 0; j < numFacesPerElement[i]; j ++, faceIdx ++ )
3249         {
3250           faceAry[ arayIdx ++ ] = numNodesPerFace[ faceIdx ];
3251 
3252           for (  k = 0;  k < numNodesPerFace[ faceIdx ];  k ++  )
3253           {
3254             faceAry[ arayIdx ++ ] = nodeIdList[ nodeIdx ++ ] - 1;
3255           }
3256         }
3257         //yyy end
3258 
3259         for (j = 0; j < numNodesPerElement[i]; j++)
3260         {
3261           if (nodeMarker[nodeIdList[nodeCount] - 1] < i)
3262           {
3263             nodeIds[elementNodeCount] = nodeIdList[nodeCount] - 1;
3264             nodeMarker[nodeIdList[nodeCount] - 1] = i;
3265             elementNodeCount += 1;
3266           }
3267           nodeCount++;
3268         }
3269 
3270         // xxx begin
3271         //cellId = output->InsertNextCell( VTK_CONVEX_POINT_SET,
3272         //                                 elementNodeCount, nodeIds );
3273         // xxx end
3274 
3275         // yyy begin
3276         cellId = output->InsertNextCell( VTK_POLYHEDRON, elementNodeCount,
3277                                          nodeIds, numFacesPerElement[i],
3278                                          faceAry );
3279         delete [] faceAry;
3280         faceAry = nullptr;
3281         //yyy end
3282 
3283         this->GetCellIds(idx, cellType)->InsertNextId(cellId);
3284 
3285         delete [] nodeIds;
3286       }
3287 
3288       // yyy begin
3289       delete [] numNodesPerFace;
3290       delete [] numFacesPerElement;
3291       numNodesPerFace    = nullptr;
3292       numFacesPerElement = nullptr;
3293       // yyy end
3294 
3295       delete [] nodeMarker;
3296       delete [] nodeIdList;
3297       delete [] numNodesPerElement;
3298     }
3299     else if (strncmp(line, "tetra4", 6) == 0 ||
3300       strncmp(line, "tetra10", 7) == 0)
3301     {
3302       if (strncmp(line, "tetra10", 7) == 0)
3303       {
3304         vtkDebugMacro("tetra10");
3305         cellType = vtkEnSightReader::TETRA10;
3306       }
3307       else
3308       {
3309         vtkDebugMacro("tetra4");
3310         cellType = vtkEnSightReader::TETRA4;
3311       }
3312 
3313       this->ReadInt(&numElements);
3314       if (numElements < 0 ||
3315         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3316       {
3317         vtkErrorMacro("Invalid number of tetrahedral cells; check that ByteOrder is set correctly.");
3318         return -1;
3319       }
3320 
3321       if (this->ElementIdsListed)
3322       {
3323         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3324       }
3325 
3326       if (cellType == vtkEnSightReader::TETRA10)
3327       {
3328         nodeIds = new vtkIdType[10];
3329         nodeIdList = new int[numElements*10];
3330         this->ReadIntArray(nodeIdList, numElements*10);
3331       }
3332       else
3333       {
3334         nodeIds = new vtkIdType[4];
3335         nodeIdList = new int[numElements*4];
3336         this->ReadIntArray(nodeIdList, numElements*4);
3337       }
3338 
3339       for (i = 0; i < numElements; i++)
3340       {
3341         if (cellType == vtkEnSightReader::TETRA10)
3342         {
3343           for (j = 0; j < 10; j++)
3344           {
3345             nodeIds[j] = nodeIdList[10*i+j] - 1;
3346           }
3347           cellId = output->InsertNextCell(VTK_QUADRATIC_TETRA, 10, nodeIds);
3348         }
3349         else
3350         {
3351           for (j = 0; j < 4; j++)
3352           {
3353             nodeIds[j] = nodeIdList[4*i+j] - 1;
3354           }
3355           cellId = output->InsertNextCell(VTK_TETRA, 4, nodeIds);
3356         }
3357         this->GetCellIds(idx, cellType)->InsertNextId(cellId);
3358       }
3359 
3360       delete [] nodeIds;
3361       delete [] nodeIdList;
3362     }
3363     else if (strncmp(line, "g_tetra4", 8) == 0 ||
3364       strncmp(line, "g_tetra10", 9) == 0)
3365     {
3366       // skipping ghost cells
3367       if (strncmp(line, "g_tetra10", 9) == 0)
3368       {
3369         vtkDebugMacro("g_tetra10");
3370         cellType = vtkEnSightReader::TETRA10;
3371       }
3372       else
3373       {
3374         vtkDebugMacro("g_tetra4");
3375         cellType = vtkEnSightReader::TETRA4;
3376       }
3377 
3378       this->ReadInt(&numElements);
3379       if (numElements < 0 ||
3380         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3381       {
3382         vtkErrorMacro("Invalid number of tetrahedral cells; check that ByteOrder is set correctly.");
3383         return -1;
3384       }
3385       if (this->ElementIdsListed)
3386       {
3387         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3388       }
3389 
3390       if (cellType == vtkEnSightReader::TETRA10)
3391       {
3392         // Skip nodeIdList.
3393         this->GoldIFile->seekg(sizeof(int)*10*numElements, ios::cur);
3394       }
3395       else
3396       {
3397         // Skip nodeIdList.
3398         this->GoldIFile->seekg(sizeof(int)*4*numElements, ios::cur);
3399       }
3400     }
3401     else if (strncmp(line, "pyramid5", 8) == 0 ||
3402       strncmp(line, "pyramid13", 9) == 0)
3403     {
3404       if (strncmp(line, "pyramid13", 9) == 0)
3405       {
3406         vtkDebugMacro("pyramid13");
3407         cellType = vtkEnSightReader::PYRAMID13;
3408       }
3409       else
3410       {
3411         vtkDebugMacro("pyramid5");
3412         cellType = vtkEnSightReader::PYRAMID5;
3413       }
3414 
3415       this->ReadInt(&numElements);
3416       if (numElements < 0 ||
3417         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3418       {
3419         vtkErrorMacro("Invalid number of pyramid cells; check that ByteOrder is set correctly.");
3420         return -1;
3421       }
3422 
3423       if (this->ElementIdsListed)
3424       {
3425         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3426       }
3427 
3428       if (cellType == vtkEnSightReader::PYRAMID13)
3429       {
3430         nodeIds = new vtkIdType[13];
3431         nodeIdList = new int[numElements*13];
3432         this->ReadIntArray(nodeIdList, numElements*13);
3433       }
3434       else
3435       {
3436         nodeIds = new vtkIdType[5];
3437         nodeIdList = new int[numElements*5];
3438         this->ReadIntArray(nodeIdList, numElements*5);
3439       }
3440 
3441       for (i = 0; i < numElements; i++)
3442       {
3443         if (cellType == vtkEnSightReader::PYRAMID13)
3444         {
3445           for (j = 0; j < 13; j++)
3446           {
3447             nodeIds[j] = nodeIdList[13*i+j] - 1;
3448           }
3449           cellId = output->InsertNextCell(VTK_QUADRATIC_PYRAMID, 13, nodeIds);
3450         }
3451         else
3452         {
3453           for (j = 0; j < 5; j++)
3454           {
3455             nodeIds[j] = nodeIdList[5*i+j] - 1;
3456           }
3457           cellId = output->InsertNextCell(VTK_PYRAMID, 5, nodeIds);
3458         }
3459         this->GetCellIds(idx, cellType)->InsertNextId(cellId);
3460       }
3461 
3462       delete [] nodeIds;
3463       delete [] nodeIdList;
3464     }
3465     else if (strncmp(line, "g_pyramid5", 10) == 0 ||
3466       strncmp(line, "g_pyramid13", 11) == 0)
3467     {
3468       // skipping ghost cells
3469       if (strncmp(line, "g_pyramid13", 11) == 0)
3470       {
3471         vtkDebugMacro("g_pyramid13");
3472         cellType = vtkEnSightReader::PYRAMID13;
3473       }
3474       else
3475       {
3476         vtkDebugMacro("g_pyramid5");
3477         cellType = vtkEnSightReader::PYRAMID5;
3478       }
3479 
3480       this->ReadInt(&numElements);
3481       if (numElements < 0 ||
3482         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3483       {
3484         vtkErrorMacro("Invalid number of pyramid cells; check that ByteOrder is set correctly.");
3485         return -1;
3486       }
3487       if (this->ElementIdsListed)
3488       {
3489         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3490       }
3491 
3492       if (cellType == vtkEnSightReader::PYRAMID13)
3493       {
3494         // Skip nodeIdList.
3495         this->GoldIFile->seekg(sizeof(int)*13*numElements, ios::cur);
3496       }
3497       else
3498       {
3499         // Skip nodeIdList.
3500         this->GoldIFile->seekg(sizeof(int)*5*numElements, ios::cur);
3501       }
3502     }
3503     else if (strncmp(line, "hexa8", 5) == 0 ||
3504       strncmp(line, "hexa20", 6) == 0)
3505     {
3506       if (strncmp(line, "hexa20", 6) == 0)
3507       {
3508         vtkDebugMacro("hexa20");
3509         cellType = vtkEnSightReader::HEXA20;
3510       }
3511       else
3512       {
3513         vtkDebugMacro("hexa8");
3514         cellType = vtkEnSightReader::HEXA8;
3515       }
3516 
3517       this->ReadInt(&numElements);
3518       if (numElements < 0 ||
3519         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3520       {
3521         vtkErrorMacro("Invalid number of hexahedral cells; check that ByteOrder is set correctly.");
3522         return -1;
3523       }
3524 
3525       if (this->ElementIdsListed)
3526       {
3527         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3528       }
3529 
3530       if (cellType == vtkEnSightReader::HEXA20)
3531       {
3532         nodeIds = new vtkIdType[20];
3533         nodeIdList = new int[numElements*20];
3534         this->ReadIntArray(nodeIdList, numElements*20);
3535       }
3536       else
3537       {
3538         nodeIds = new vtkIdType[8];
3539         nodeIdList = new int[numElements*8];
3540         this->ReadIntArray(nodeIdList, numElements*8);
3541       }
3542 
3543       for (i = 0; i < numElements; i++)
3544       {
3545         if (cellType == vtkEnSightReader::HEXA20)
3546         {
3547           for (j = 0; j < 20; j++)
3548           {
3549             nodeIds[j] = nodeIdList[20*i+j] - 1;
3550           }
3551           cellId = output->InsertNextCell(VTK_QUADRATIC_HEXAHEDRON, 20, nodeIds);
3552         }
3553         else
3554         {
3555           for (j = 0; j < 8; j++)
3556           {
3557             nodeIds[j] = nodeIdList[8*i+j] - 1;
3558           }
3559           cellId = output->InsertNextCell(VTK_HEXAHEDRON, 8, nodeIds);
3560         }
3561         this->GetCellIds(idx, cellType)->InsertNextId(cellId);
3562       }
3563 
3564       delete [] nodeIds;
3565       delete [] nodeIdList;
3566     }
3567     else if (strncmp(line, "g_hexa8", 7) == 0 ||
3568       strncmp(line, "g_hexa20", 8) == 0)
3569     {
3570       // skipping ghost cells
3571       if (strncmp(line, "g_hexa20", 8) == 0)
3572       {
3573         vtkDebugMacro("g_hexa20");
3574         cellType = vtkEnSightReader::HEXA20;
3575       }
3576       else
3577       {
3578         vtkDebugMacro("g_hexa8");
3579         cellType = vtkEnSightReader::HEXA8;
3580       }
3581 
3582       this->ReadInt(&numElements);
3583       if (numElements < 0 ||
3584         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3585       {
3586         vtkErrorMacro("Invalid number of hexahedral cells; check that ByteOrder is set correctly.");
3587         return -1;
3588       }
3589       if (this->ElementIdsListed)
3590       {
3591         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3592       }
3593 
3594       if (cellType == vtkEnSightReader::HEXA20)
3595       {
3596         // Skip nodeIdList.
3597         this->GoldIFile->seekg(sizeof(int)*20*numElements, ios::cur);
3598       }
3599       else
3600       {
3601         // Skip nodeIdList.
3602         this->GoldIFile->seekg(sizeof(int)*8*numElements, ios::cur);
3603       }
3604     }
3605     else if (strncmp(line, "penta6", 6) == 0 ||
3606       strncmp(line, "penta15", 7) == 0)
3607     {
3608       if (strncmp(line, "penta15", 7) == 0)
3609       {
3610         vtkDebugMacro("penta15");
3611         cellType = vtkEnSightReader::PENTA15;
3612       }
3613       else
3614       {
3615         vtkDebugMacro("penta6");
3616         cellType = vtkEnSightReader::PENTA6;
3617       }
3618 
3619       this->ReadInt(&numElements);
3620       if (numElements < 0 ||
3621         static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3622       {
3623         vtkErrorMacro("Invalid number of pentagonal cells; check that ByteOrder is set correctly.");
3624         return -1;
3625       }
3626 
3627       if (this->ElementIdsListed)
3628       {
3629         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3630       }
3631 
3632       if (cellType == vtkEnSightReader::PENTA15)
3633       {
3634         nodeIds = new vtkIdType[15];
3635         nodeIdList = new int[numElements*15];
3636         this->ReadIntArray(nodeIdList, numElements*15);
3637       }
3638       else
3639       {
3640         nodeIds = new vtkIdType[6];
3641         nodeIdList = new int[numElements*6];
3642         this->ReadIntArray(nodeIdList, numElements*6);
3643       }
3644 
3645       const unsigned char penta6Map[6] = {0, 2, 1, 3, 5, 4};
3646       const unsigned char penta15Map[15] = {0, 2, 1, 3, 5, 4, 8, 7, 6, 11, 10, 9, 12, 14, 13};
3647 
3648       for (i = 0; i < numElements; i++)
3649       {
3650         if (cellType == vtkEnSightReader::PENTA15)
3651         {
3652           for (j = 0; j < 15; j++)
3653           {
3654             nodeIds[penta15Map[j]] = nodeIdList[15*i+j] - 1;
3655           }
3656           cellId = output->InsertNextCell(VTK_QUADRATIC_WEDGE, 15, nodeIds);
3657         }
3658         else
3659         {
3660           for (j = 0; j < 6; j++)
3661           {
3662             nodeIds[penta6Map[j]] = nodeIdList[6*i+j] - 1;
3663           }
3664           cellId = output->InsertNextCell(VTK_WEDGE, 6, nodeIds);
3665         }
3666         this->GetCellIds(idx, cellType)->InsertNextId(cellId);
3667       }
3668 
3669       delete [] nodeIds;
3670       delete [] nodeIdList;
3671     }
3672     else if (strncmp(line, "g_penta6", 8) == 0 ||
3673       strncmp(line, "g_penta15", 9) == 0)
3674     {
3675       // skipping ghost cells
3676       if (strncmp(line, "g_penta15", 9) == 0)
3677       {
3678         vtkDebugMacro("g_penta15");
3679         cellType = vtkEnSightReader::PENTA15;
3680       }
3681       else
3682       {
3683         vtkDebugMacro("g_penta6");
3684         cellType = vtkEnSightReader::PENTA6;
3685       }
3686 
3687       this->ReadInt(&numElements);
3688       if (numElements < 0 ||
3689        static_cast<unsigned int>(numElements * this->SizeOfInt) > this->FileSize)
3690       {
3691         vtkErrorMacro("Invalid number of pentagonal cells; check that ByteOrder is set correctly.");
3692         return -1;
3693       }
3694       if (this->ElementIdsListed)
3695       {
3696         this->GoldIFile->seekg(sizeof(int)*numElements, ios::cur);
3697       }
3698 
3699       if (cellType == vtkEnSightReader::PENTA15)
3700       {
3701         // Skip nodeIdList.
3702         this->GoldIFile->seekg(sizeof(int)*15*numElements, ios::cur);
3703       }
3704       else
3705       {
3706         // Skip nodeIdList.
3707         this->GoldIFile->seekg(sizeof(int)*6*numElements, ios::cur);
3708       }
3709     }
3710     else if (strncmp(line, "END TIME STEP", 13) == 0)
3711     {
3712       return 1;
3713     }
3714     else if (this->IS->fail())
3715     {
3716       //May want consistency check here?
3717       //vtkWarningMacro("EOF on geometry file");
3718       return 1;
3719     }
3720     else
3721     {
3722       vtkErrorMacro("undefined geometry file line");
3723       return -1;
3724     }
3725     this->GoldIFile->peek();
3726     if (this->GoldIFile->eof())
3727     {
3728       lineRead = 0;
3729       continue;
3730     }
3731     lineRead = this->ReadLine(line);
3732   }
3733   return lineRead;
3734 }
3735 
3736 //----------------------------------------------------------------------------
CreateStructuredGridOutput(int partId,char line[80],const char * name,vtkMultiBlockDataSet * compositeOutput)3737 int vtkEnSightGoldBinaryReader::CreateStructuredGridOutput(
3738   int partId, char line[80], const char* name,
3739   vtkMultiBlockDataSet *compositeOutput)
3740 {
3741   char subLine[80];
3742   int lineRead;
3743   int iblanked = 0;
3744   int dimensions[3];
3745   int i;
3746   vtkPoints *points = vtkPoints::New();
3747   int numPts;
3748   float *xCoords, *yCoords, *zCoords;
3749 
3750   this->NumberOfNewOutputs++;
3751 
3752   vtkDataSet* ds = this->GetDataSetFromBlock(compositeOutput, partId);
3753   if (ds == nullptr || ! ds->IsA("vtkStructuredGrid"))
3754   {
3755     vtkDebugMacro("creating new structured grid output");
3756     vtkStructuredGrid* sgrid = vtkStructuredGrid::New();
3757     this->AddToBlock(compositeOutput, partId, sgrid);
3758     sgrid->Delete();
3759     ds = sgrid;
3760   }
3761 
3762   vtkStructuredGrid* output = vtkStructuredGrid::SafeDownCast(ds);
3763   this->SetBlockName(compositeOutput, partId, name);
3764 
3765   if (sscanf(line, " %*s %s", subLine) == 1)
3766   {
3767     if (strncmp(subLine, "iblanked", 8) == 0)
3768     {
3769       iblanked = 1;
3770     }
3771   }
3772 
3773   this->ReadIntArray(dimensions, 3);
3774   numPts = dimensions[0] * dimensions[1] * dimensions[2];
3775   if (dimensions[0] < 0 ||
3776     static_cast<unsigned int>(dimensions[0] * this->SizeOfInt) > this->FileSize ||
3777     dimensions[1] < 0 ||
3778     static_cast<unsigned int>(dimensions[1] * this->SizeOfInt) > this->FileSize ||
3779     dimensions[2] < 0 ||
3780     static_cast<unsigned int>(dimensions[2] * this->SizeOfInt) > this->FileSize ||
3781     numPts < 0 || static_cast<unsigned int>(numPts*this->SizeOfInt) > this->FileSize)
3782   {
3783     vtkErrorMacro("Invalid dimensions read; check that ByteOrder is set correctly.");
3784     points->Delete();
3785     return -1;
3786   }
3787   output->SetDimensions(dimensions);
3788   points->Allocate(numPts);
3789 
3790   xCoords = new float[numPts];
3791   yCoords = new float[numPts];
3792   zCoords = new float[numPts];
3793   this->ReadFloatArray(xCoords, numPts);
3794   this->ReadFloatArray(yCoords, numPts);
3795   this->ReadFloatArray(zCoords, numPts);
3796 
3797   for (i = 0; i < numPts; i++)
3798   {
3799     points->InsertNextPoint(xCoords[i], yCoords[i], zCoords[i]);
3800   }
3801   output->SetPoints(points);
3802   if (iblanked)
3803   {
3804     int *iblanks = new int[numPts];
3805     this->ReadIntArray(iblanks, numPts);
3806 
3807     for (i = 0; i < numPts; i++)
3808     {
3809       if (!iblanks[i])
3810       {
3811         output->BlankPoint(i);
3812       }
3813     }
3814     delete [] iblanks;
3815   }
3816 
3817   points->Delete();
3818   delete [] xCoords;
3819   delete [] yCoords;
3820   delete [] zCoords;
3821 
3822   this->GoldIFile->peek();
3823   if (this->GoldIFile->eof())
3824   {
3825     lineRead = 0;
3826   }
3827   else
3828   {
3829     lineRead = this->ReadLine(line);
3830   }
3831 
3832   if (strncmp(line, "node_ids", 8) == 0)
3833   {
3834     int *nodeIds = new int[numPts];
3835     this->ReadIntArray(nodeIds, numPts);
3836     lineRead = this->ReadLine(line);
3837     delete [] nodeIds;
3838   }
3839   if (strncmp(line, "element_ids", 11) == 0)
3840   {
3841     int numElements = (dimensions[0] - 1) * (dimensions[1] - 1) *
3842       (dimensions[2] - 1);
3843     int *elementIds = new int[numElements];
3844     this->ReadIntArray(elementIds, numElements);
3845     lineRead = this->ReadLine(line);
3846     delete [] elementIds;
3847   }
3848 
3849   return lineRead;
3850 }
3851 
3852 //----------------------------------------------------------------------------
CreateRectilinearGridOutput(int partId,char line[80],const char * name,vtkMultiBlockDataSet * compositeOutput)3853 int vtkEnSightGoldBinaryReader::CreateRectilinearGridOutput(
3854   int partId, char line[80], const char* name,
3855   vtkMultiBlockDataSet *compositeOutput)
3856 {
3857   char subLine[80];
3858   int lineRead;
3859   int iblanked = 0;
3860   int dimensions[3];
3861   int i;
3862   vtkFloatArray *xCoords = vtkFloatArray::New();
3863   vtkFloatArray *yCoords = vtkFloatArray::New();
3864   vtkFloatArray *zCoords = vtkFloatArray::New();
3865   float *tempCoords;
3866   int numPts;
3867 
3868   this->NumberOfNewOutputs++;
3869 
3870   vtkDataSet* ds = this->GetDataSetFromBlock(compositeOutput, partId);
3871   if (ds == nullptr || !ds->IsA("vtkRectilinearGrid"))
3872   {
3873     vtkDebugMacro("creating new rectilinear grid output");
3874     vtkRectilinearGrid* rgrid = vtkRectilinearGrid::New();
3875     this->AddToBlock(compositeOutput, partId, rgrid);
3876     rgrid->Delete();
3877     ds = rgrid;
3878   }
3879 
3880   vtkRectilinearGrid* output = vtkRectilinearGrid::SafeDownCast(ds);
3881 
3882   this->SetBlockName(compositeOutput, partId, name);
3883 
3884   if (sscanf(line, " %*s %*s %s", subLine) == 1)
3885   {
3886     if (strncmp(subLine, "iblanked", 8) == 0)
3887     {
3888       iblanked = 1;
3889     }
3890   }
3891 
3892   this->ReadIntArray(dimensions, 3);
3893   if (dimensions[0] < 0 ||
3894     static_cast<unsigned int>(dimensions[0] * this->SizeOfInt) > this->FileSize ||
3895     dimensions[1] < 0 ||
3896     static_cast<unsigned int>(dimensions[1] * this->SizeOfInt) > this->FileSize ||
3897     dimensions[2] < 0 ||
3898     static_cast<unsigned int>(dimensions[2] * this->SizeOfInt) > this->FileSize ||
3899     (dimensions[0]+dimensions[1]+dimensions[2]) < 0 ||
3900     static_cast<unsigned int>((dimensions[0] + dimensions[1] + dimensions[2]) * this->SizeOfInt) >
3901       this->FileSize)
3902   {
3903     vtkErrorMacro("Invalid dimensions read; check that BytetOrder is set correctly.");
3904     xCoords->Delete();
3905     yCoords->Delete();
3906     zCoords->Delete();
3907     return -1;
3908   }
3909 
3910   output->SetDimensions(dimensions);
3911   xCoords->Allocate(dimensions[0]);
3912   yCoords->Allocate(dimensions[1]);
3913   zCoords->Allocate(dimensions[2]);
3914 
3915   tempCoords = new float[dimensions[0]];
3916   this->ReadFloatArray(tempCoords, dimensions[0]);
3917   for (i = 0; i < dimensions[0]; i++)
3918   {
3919     xCoords->InsertNextTuple(&tempCoords[i]);
3920   }
3921   delete [] tempCoords;
3922   tempCoords = new float[dimensions[1]];
3923   this->ReadFloatArray(tempCoords, dimensions[1]);
3924   for (i = 0; i < dimensions[1]; i++)
3925   {
3926     yCoords->InsertNextTuple(&tempCoords[i]);
3927   }
3928   delete [] tempCoords;
3929   tempCoords = new float[dimensions[2]];
3930   this->ReadFloatArray(tempCoords, dimensions[2]);
3931   for (i = 0; i < dimensions[2]; i++)
3932   {
3933     zCoords->InsertNextTuple(&tempCoords[i]);
3934   }
3935   delete [] tempCoords;
3936   if (iblanked)
3937   {
3938     vtkWarningMacro("VTK does not handle blanking for rectilinear grids.");
3939     numPts = dimensions[0] * dimensions[1] * dimensions[2];
3940     int *tempArray = new int[numPts];
3941     this->ReadIntArray(tempArray, numPts);
3942     delete [] tempArray;
3943   }
3944 
3945   output->SetXCoordinates(xCoords);
3946   output->SetYCoordinates(yCoords);
3947   output->SetZCoordinates(zCoords);
3948 
3949   xCoords->Delete();
3950   yCoords->Delete();
3951   zCoords->Delete();
3952 
3953   // reading next line to check for EOF
3954   lineRead = this->ReadLine(line);
3955   return lineRead;
3956 }
3957 
3958 //----------------------------------------------------------------------------
CreateImageDataOutput(int partId,char line[80],const char * name,vtkMultiBlockDataSet * compositeOutput)3959 int vtkEnSightGoldBinaryReader::CreateImageDataOutput(
3960   int partId, char line[80], const char* name,
3961   vtkMultiBlockDataSet *compositeOutput)
3962 {
3963   char subLine[80];
3964   int lineRead;
3965   int iblanked = 0;
3966   int dimensions[3];
3967   float origin[3], delta[3];
3968   int numPts;
3969 
3970   this->NumberOfNewOutputs++;
3971 
3972   vtkDataSet* ds = this->GetDataSetFromBlock(compositeOutput, partId);
3973   if (ds == nullptr || !ds->IsA("vtkImageData"))
3974   {
3975     vtkDebugMacro("creating new image data output");
3976     vtkImageData* idata = vtkImageData::New();
3977     this->AddToBlock(compositeOutput, partId, idata);
3978     idata->Delete();
3979     ds = idata;
3980   }
3981 
3982   vtkImageData* output = vtkImageData::SafeDownCast(ds);
3983 
3984   this->SetBlockName(compositeOutput, partId, name);
3985 
3986   if (sscanf(line, " %*s %*s %s", subLine) == 1)
3987   {
3988     if (strncmp(subLine, "iblanked", 8) == 0)
3989     {
3990       iblanked = 1;
3991     }
3992   }
3993 
3994   this->ReadIntArray(dimensions, 3);
3995   output->SetDimensions(dimensions);
3996   this->ReadFloatArray(origin, 3);
3997   output->SetOrigin(origin[0], origin[1], origin[2]);
3998   this->ReadFloatArray(delta, 3);
3999   output->SetSpacing(delta[0], delta[1], delta[2]);
4000 
4001   if (iblanked)
4002   {
4003     vtkWarningMacro("VTK does not handle blanking for image data.");
4004     numPts = dimensions[0]*dimensions[1]*dimensions[2];
4005     if (dimensions[0] < 0 ||
4006       static_cast<unsigned int>(dimensions[0] * this->SizeOfInt) > this->FileSize ||
4007       dimensions[1] < 0 ||
4008       static_cast<unsigned int>(dimensions[1] * this->SizeOfInt) > this->FileSize ||
4009       dimensions[2] < 0 ||
4010       static_cast<unsigned int>(dimensions[2] * this->SizeOfInt) > this->FileSize ||
4011       numPts < 0 || static_cast<unsigned int>(numPts*this->SizeOfInt) > this->FileSize)
4012     {
4013       return -1;
4014     }
4015     int *tempArray = new int[numPts];
4016     this->ReadIntArray(tempArray, numPts);
4017     delete [] tempArray;
4018   }
4019 
4020   // reading next line to check for EOF
4021   lineRead = this->ReadLine(line);
4022   return lineRead;
4023 }
4024 
4025 // Internal function to read in a line up to 80 characters.
4026 // Returns zero if there was an error.
ReadLine(char result[80])4027 int vtkEnSightGoldBinaryReader::ReadLine(char result[80])
4028 {
4029   if (!this->GoldIFile->read(result, 80))
4030   {
4031     // The read fails when reading the last part/array when there are no points.
4032     // I took out the error macro as a temporary fix.
4033     // We need to determine what EnSight does when the part with zero point
4034     // is not the last, and change the read array method.
4035     //int fixme; // I do not have a file to test with yet.
4036     vtkDebugMacro("Read failed");
4037     return 0;
4038   }
4039   // fix to the memory leakage problem detected by Valgrind
4040   result[79] = '\0';
4041 
4042   if (this->Fortran)
4043   {
4044     // strncpy cannot be used for overlapping buffers
4045     int i = 0;
4046     for ( ; i < 76 && result[i+4] != '\0'; ++i)
4047     {
4048       result[i] = result[i+4];
4049     }
4050     for ( ; i < 76; ++i)
4051     {
4052       result[i] = '\0';
4053     }
4054     result[76] = 0;
4055     // better read an extra 8 bytes to prevent error next time
4056     char dummy[8];
4057     if (!this->GoldIFile->read(dummy, 8))
4058     {
4059       vtkDebugMacro("Read (fortran) failed");
4060       return 0;
4061     }
4062   }
4063 
4064   return 1;
4065 }
4066 
4067 // Internal function to read a single integer.
4068 // Returns zero if there was an error.
4069 // Sets byte order so that part id is reasonable.
ReadPartId(int * result)4070 int vtkEnSightGoldBinaryReader::ReadPartId(int *result)
4071 {
4072   // first swap like normal.
4073   if (this->ReadInt(result) == 0)
4074   {
4075     vtkErrorMacro("Read failed");
4076     return 0;
4077   }
4078 
4079   // second: try an experimental byte swap.
4080   // Only experiment if byte order is not set.
4081   if (this->ByteOrder == FILE_UNKNOWN_ENDIAN)
4082   {
4083     int tmpLE = *result;
4084     int tmpBE = *result;
4085     vtkByteSwap::Swap4LE(&tmpLE);
4086     vtkByteSwap::Swap4BE(&tmpBE);
4087 
4088     if (tmpLE >= 0 && tmpLE < MAXIMUM_PART_ID)
4089     {
4090       this->ByteOrder = FILE_LITTLE_ENDIAN;
4091       *result = tmpLE;
4092       return 1;
4093     }
4094     if (tmpBE >= 0 && tmpBE < MAXIMUM_PART_ID)
4095     {
4096       this->ByteOrder = FILE_BIG_ENDIAN;
4097       *result = tmpBE;
4098       return 1;
4099     }
4100     vtkErrorMacro("Byte order could not be determined.");
4101     return 0;
4102   }
4103 
4104   return 1;
4105 }
4106 
4107 // Internal function to read a single integer.
4108 // Returns zero if there was an error.
ReadInt(int * result)4109 int vtkEnSightGoldBinaryReader::ReadInt(int *result)
4110 {
4111   char dummy[4];
4112   if (this->Fortran)
4113   {
4114     if (!this->GoldIFile->read(dummy, 4))
4115     {
4116       vtkErrorMacro("Read (fortran) failed.");
4117       return 0;
4118     }
4119   }
4120 
4121   if (!this->GoldIFile->read((char*)result, sizeof(int)))
4122   {
4123     vtkErrorMacro("Read failed");
4124     return 0;
4125   }
4126 
4127   if (this->ByteOrder == FILE_LITTLE_ENDIAN)
4128   {
4129     vtkByteSwap::Swap4LE(result);
4130   }
4131   else if (this->ByteOrder == FILE_BIG_ENDIAN)
4132   {
4133     vtkByteSwap::Swap4BE(result);
4134   }
4135 
4136   if (this->Fortran)
4137   {
4138     if (!this->GoldIFile->read(dummy, 4))
4139     {
4140       vtkErrorMacro("Read (fortran) failed.");
4141       return 0;
4142     }
4143   }
4144 
4145   return 1;
4146 }
4147 
4148 // Internal function to read an integer array.
4149 // Returns zero if there was an error.
ReadIntArray(int * result,int numInts)4150 int vtkEnSightGoldBinaryReader::ReadIntArray(int *result,
4151   int numInts)
4152 {
4153   if (numInts <= 0)
4154   {
4155     return 1;
4156   }
4157 
4158   char dummy[4];
4159   if (this->Fortran)
4160   {
4161     if (!this->GoldIFile->read(dummy, 4))
4162     {
4163       vtkErrorMacro("Read (fortran) failed.");
4164       return 0;
4165     }
4166   }
4167 
4168   if (!this->GoldIFile->read((char*)result, sizeof(int)*numInts))
4169   {
4170     vtkErrorMacro("Read failed.");
4171     return 0;
4172   }
4173 
4174   if (this->ByteOrder == FILE_LITTLE_ENDIAN)
4175   {
4176     vtkByteSwap::Swap4LERange(result, numInts);
4177   }
4178   else
4179   {
4180     vtkByteSwap::Swap4BERange(result, numInts);
4181   }
4182 
4183   if (this->Fortran)
4184   {
4185     if (!this->GoldIFile->read(dummy, 4))
4186     {
4187       vtkErrorMacro("Read (fortran) failed.");
4188       return 0;
4189     }
4190   }
4191 
4192   return 1;
4193 }
4194 
4195 // Internal function to read a single vtkTypeInt64.
4196 // Returns zero if there was an error.
ReadLong(vtkTypeInt64 * result)4197 int vtkEnSightGoldBinaryReader::ReadLong(vtkTypeInt64 *result)
4198 {
4199   char dummy[4];
4200   if (this->Fortran)
4201   {
4202     if (!this->GoldIFile->read(dummy, 4))
4203     {
4204       vtkErrorMacro("Read (fortran) failed.");
4205       return 0;
4206     }
4207   }
4208 
4209   if (!this->GoldIFile->read((char*)result, sizeof(vtkTypeInt64)))
4210   {
4211     vtkErrorMacro("Read failed");
4212     return 0;
4213   }
4214 
4215   if (this->ByteOrder == FILE_LITTLE_ENDIAN)
4216   {
4217     vtkByteSwap::Swap8LE(result);
4218   }
4219   else if (this->ByteOrder == FILE_BIG_ENDIAN)
4220   {
4221     vtkByteSwap::Swap8BE(result);
4222   }
4223 
4224   if (this->Fortran)
4225   {
4226     if (!this->GoldIFile->read(dummy, 4))
4227     {
4228       vtkErrorMacro("Read (fortran) failed.");
4229       return 0;
4230     }
4231   }
4232 
4233   return 1;
4234 }
4235 
4236 // Internal function to read a float array.
4237 // Returns zero if there was an error.
ReadFloatArray(float * result,int numFloats)4238 int vtkEnSightGoldBinaryReader::ReadFloatArray(float *result,
4239   int numFloats)
4240 {
4241   if (numFloats <= 0)
4242   {
4243     return 1;
4244   }
4245 
4246   char dummy[4];
4247   if (this->Fortran)
4248   {
4249     if (!this->GoldIFile->read(dummy, 4))
4250     {
4251       vtkErrorMacro("Read (fortran) failed.");
4252       return 0;
4253     }
4254   }
4255 
4256   if (!this->GoldIFile->read((char*)result, sizeof(float)*numFloats))
4257   {
4258     vtkErrorMacro("Read failed");
4259     return 0;
4260   }
4261 
4262   if (this->ByteOrder == FILE_LITTLE_ENDIAN)
4263   {
4264     vtkByteSwap::Swap4LERange(result, numFloats);
4265   }
4266   else
4267   {
4268     vtkByteSwap::Swap4BERange(result, numFloats);
4269   }
4270 
4271   if (this->Fortran)
4272   {
4273     if (!this->GoldIFile->read(dummy, 4))
4274     {
4275       vtkErrorMacro("Read (fortran) failed.");
4276       return 0;
4277     }
4278   }
4279   return 1;
4280 }
4281 
4282 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)4283 void vtkEnSightGoldBinaryReader::PrintSelf(ostream& os, vtkIndent indent)
4284 {
4285   this->Superclass::PrintSelf(os,indent);
4286 }
4287 
4288 // Seeks the IFile to the cached timestep nearest the target timestep.
4289 // Returns the actually sought to timestep
4290 //----------------------------------------------------------------------------
SeekToCachedTimeStep(const char * fileName,int realTimeStep)4291 int vtkEnSightGoldBinaryReader::SeekToCachedTimeStep(const char* fileName,
4292                                                      int realTimeStep)
4293 {
4294   typedef vtkEnSightGoldBinaryReader::FileOffsetMapInternal MapType;
4295   typedef MapType::const_iterator MapNameIterator;
4296   typedef MapType::value_type::second_type::const_iterator FileOffsetIterator;
4297 
4298   int j = 0;
4299 
4300   MapNameIterator nameIterator = this->FileOffsets->Map.find(fileName);
4301   if(nameIterator == this->FileOffsets->Map.end())
4302   {
4303     return j;
4304   }
4305 
4306   // Try to find the nearest time step for which we know the offset
4307   for (int i = realTimeStep; i >= 0; i--)
4308   {
4309     FileOffsetIterator fileOffsetIterator = nameIterator->second.find(i);
4310     if (fileOffsetIterator != nameIterator->second.end())
4311     {
4312       //we need to account for the last 80 characters as where we need to seek,
4313       //as we need to be at the BEGIN TIMESTEP keyword and not
4314       //the description line
4315       this->GoldIFile->seekg(fileOffsetIterator->second - 80l, ios::beg);
4316       j = i;
4317       break;
4318     }
4319   }
4320   return j;
4321 }
4322 
4323 //----------------------------------------------------------------------------
4324 // Add a cached file offset
AddTimeStepToCache(const char * fileName,int realTimeStep,vtkTypeInt64 address)4325 void vtkEnSightGoldBinaryReader::AddTimeStepToCache(const char* fileName,
4326                                                     int realTimeStep,
4327                                                     vtkTypeInt64 address)
4328 {
4329   if (this->FileOffsets->Map.find(fileName) == this->FileOffsets->Map.end())
4330   {
4331     std::map<int, vtkTypeInt64> tsMap;
4332     this->FileOffsets->Map[fileName] = tsMap;
4333   }
4334   this->FileOffsets->Map[fileName][realTimeStep] = address;
4335 }
4336 
4337 //----------------------------------------------------------------------------
AddFileIndexToCache(const char * fileName)4338 void vtkEnSightGoldBinaryReader::AddFileIndexToCache(const char* fileName)
4339 {
4340   // only read the file index if we have not searched for the file index before
4341   if (this->FileOffsets->Map.find(fileName) == this->FileOffsets->Map.end())
4342   {
4343     char line[80];
4344     vtkTypeInt64 addr;
4345     int  numTS;
4346 
4347     // We add an empty map to prevent further attempts at reading the file index
4348     std::map<int, vtkTypeInt64> tsMap;
4349     this->FileOffsets->Map[fileName] = tsMap;
4350 
4351     // Read the last 80 characters (+ a vtkTypeInt64) of the file and check for FILE_INDEX
4352     vtkIdType seekOffset =
4353       ( vtkIdType(-80) * static_cast<vtkIdType>(sizeof(char)) ) -
4354                          static_cast<vtkIdType>(sizeof(vtkTypeInt64));
4355     this->GoldIFile->seekg(seekOffset, ios::end);
4356 
4357     // right before the FILE_INDEX entry we might find the address of the index start
4358     this->ReadLong(&addr);
4359     this->ReadLine(line);
4360 
4361     if (strncmp(line, "FILE_INDEX", 10) == 0)
4362     {
4363       // jump to beginning of the index and add all time steps
4364       this->GoldIFile->seekg(addr, ios::beg);
4365       this->ReadInt(&numTS);
4366 
4367       for (int i = 0; i < numTS; ++i)
4368       {
4369         this->ReadLong(&addr);
4370         // The file index points at the description line, while VTK points at BEGIN TIMESTEP
4371         this->FileOffsets->Map[fileName][i] = addr;
4372       }
4373     }
4374   }
4375   this->GoldIFile->seekg(0l, ios::beg);
4376 }
4377