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