ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
filereaderutils.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "filereaderutils.h"
9 
10 #include <vtkCellData.h>
11 #include <vtkUnstructuredGrid.h>
12 
13 #include <QDebug>
14 
16 
17 #define USE_POINT_INDICES_TO_INSERT
18 #define ALL_LINES -1
19 #define INVALID_MAT_ID -INT_MAX
20 
21 #if defined(_WIN32)
22 // for _strnicmp
23 #include <string.h>
24 #define STRNCASECMP _strnicmp
25 #else
26 // for strcasecmp
27 #include <strings.h>
28 #define STRNCASECMP strncasecmp
29 #endif
30 
31 namespace VtkUtils {
32 
33 static float Getf(const char *s) {
34  char *ends;
35  double val = 0.0;
36 
37  // Check for one of these funky 'NASTRAN exponential format' strings.
38  // This is where a value like '1.2345e-5' is actually represented in the
39  // file as '1.2345-5' with the 'e' character missing. It is awkward but
40  // apparently a NASTRAN standard. I guess the rationale is that given
41  // an 8 character field width limit, removing the 'e' character gives them
42  // one additional digit of precision. This logic is basically looking for
43  // the condition of encountering a sign character, '-' or '+', AFTER having
44  // seen characters that could represent part of a number. In such a case,
45  // it MUST be the sign of the exponent.
46  const char *p = s;
47  char tmps[32];
48  char *q = tmps;
49  bool haveSeenNumChars = false;
50  while (!haveSeenNumChars || (*p != '-' && *p != '+' && *p != '\0')) {
51  if ('0' <= *p && *p <= '9' || *p == '.' || *p == '+' || *p == '-')
52  haveSeenNumChars = true;
53  *q++ = *p++;
54  }
55 
56  if (haveSeenNumChars && (*p == '-' || *p == '+')) {
57  *q++ = 'e';
58  while (*p != '\0') *q++ = *p++;
59  *q++ = '\0';
60  errno = 0;
61  val = strtod(tmps, &ends);
62  } else {
63  errno = 0;
64  val = strtod(s, &ends);
65  }
66 
67  if (errno != 0) {
68  qDebug() << "Error occured at " << __FUNCTION__;
69  return 0.0;
70  }
71 
72  return (float)val;
73 }
74 
75 // ****************************************************************************
76 // Function: Geti
77 //
78 // Purpose: Robust way of reading string for integer value
79 //
80 // Programmer: Mark C. Miller, Thu Apr 3 16:27:01 PDT 2008
81 //
82 // Modifications:
83 // Jeremy Meredith, Thu Aug 7 13:43:03 EDT 2008
84 // Format %s doesn't use space modifier.
85 //
86 // ****************************************************************************
87 static int Geti(const char *s) {
88  char *ends;
89 
90  errno = 0;
91  long val = strtol(s, &ends, 10);
92 
93  if (errno != 0) {
94  qDebug() << "Error occured at " << __FUNCTION__;
95  return 0;
96  }
97 
98  return (int)val;
99 }
100 AbstractFileReader::AbstractFileReader(QObject *parent) : QObject(parent) {}
101 
102 void AbstractFileReader::setFileName(const QString &file) {
103  if (m_fileName != file) m_fileName = file;
104 }
105 
106 QString AbstractFileReader::fileName() const { return m_fileName; }
107 
108 void AbstractFileReader::setTitle(const QString &title) {
109  if (m_title != title) m_title = title;
110 }
111 
112 QString AbstractFileReader::title() const { return m_title; }
113 
115 
118  m_reader->ReadAllScalarsOn();
119  m_reader->ReadAllVectorsOn();
120  m_reader->SetFileName(fileName().toLocal8Bit());
121  m_reader->Update();
122  emit finished();
123 }
124 
126 
129  m_reader->SetFileName(fileName().toLocal8Bit());
130  m_reader->Update();
131 
132  emit finished();
133 }
134 
136 
139  m_reader->SetFileName(fileName().toLocal8Bit());
140  m_reader->Update();
141  emit finished();
142 }
143 
145 
148 
149  m_reader->SetFileName(fileName().toLocal8Bit());
150  m_reader->Update();
151 
152  emit finished();
153 }
154 
156  : AbstractFileReader(parent) {}
157 
159  std::ifstream ifile(fileName().toLocal8Bit());
160  if (ifile.fail()) return;
161 
162  // Determine the file size and come up with an estimate of the
163  // number of vertices and cells so we can size the points and cells.
164  int nPoints = 100;
165  int nCells = 100;
166  int matCountOpt = 0;
167 
168 #if !defined(MDSERVER)
169 
170  vtkPoints *pts = vtkPoints::New();
171  pts->Allocate(nPoints);
172 #ifdef USE_POINT_INDICES_TO_INSERT
173  pts->SetNumberOfPoints(nPoints);
174 #endif
175 
176  vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::New();
177  ugrid->SetPoints(pts);
178  ugrid->Allocate(nCells);
179  pts->Delete();
180  pts = ugrid->GetPoints();
181 
182 #endif // if !defined(MDSERVER)
183 
184  char line[1024];
185  float pt[3];
186  vtkIdType verts[8];
187  bool recognized = false;
188  bool titleRead = false;
189  for (int lineIndex = 0; !ifile.eof(); ++lineIndex) {
190  int matid = INVALID_MAT_ID;
191 
192  // Get the line
193  ifile.getline(line, 1024);
194 
195  // Determine what the line is for.
196  if (line[0] == '$' && !recognized) {
197  if (!titleRead) m_title += line;
198  } else if (strncmp(line, "GRID*", 5) == 0) {
199  recognized = true;
200 
201  // These GRID* lines need a second line of data. Read it into
202  // the same buffer at the end.
203  ifile.getline(line + 72, 1024 - 72);
204 
205 #define LONG_FIELD_WIDTH 16
206  char *valstart = line + 81 - 1;
207  pt[2] = Getf(valstart);
208 
209  valstart = line + 72 - LONG_FIELD_WIDTH + 1 - 1;
210  char *valend = line + 72;
211  *valend = '\0';
212  pt[1] = Getf(valstart);
213 
214  valstart -= LONG_FIELD_WIDTH;
215  valend -= LONG_FIELD_WIDTH;
216  *valend = '\0';
217  pt[0] = Getf(valstart);
218 
219 #ifdef USE_POINT_INDICES_TO_INSERT
220  valstart -= (2 * LONG_FIELD_WIDTH);
221  valend -= (2 * LONG_FIELD_WIDTH);
222  *valend = '\0';
223  int psi = Geti(valstart) - 1;
224 
225 #if !defined(MDSERVER)
226 
227  if (psi < nPoints)
228  pts->SetPoint(psi, pt);
229  else {
230  int newSize = int(float(nPoints) * 1.1f);
231  if (newSize < psi) newSize = int(float(psi) * 1.1f);
232  if (newSize <= nPoints) newSize = nPoints + 1;
233 
234  qDebug() << "Resizing point array from " << nPoints
235  << " points to " << newSize
236  << " points because we need to insert point index "
237  << psi;
238  nPoints = newSize;
239  pts->GetData()->Resize(nPoints);
240  pts->SetNumberOfPoints(nPoints);
241  pts->SetPoint(psi, pt);
242  }
243 
244 #endif // if !defined(MDSERVER)
245 
246 #else
247 #if !defined(MDSERVER)
248  pts->InsertNextPoint(pt);
249 #endif
250 #endif
251 
252  } else if (strncmp(line, "GRID", 4) == 0) {
253  recognized = true;
254 
255 #define SHORT_FIELD_WIDTH 8
256  char *valstart = line + 48 - SHORT_FIELD_WIDTH;
257  char *valend = line + 48;
258 
259  *valend = '\0';
260  pt[2] = Getf(valstart);
261 
262  valstart -= SHORT_FIELD_WIDTH;
263  valend -= SHORT_FIELD_WIDTH;
264  *valend = '\0';
265  pt[1] = Getf(valstart);
266 
267  valstart -= SHORT_FIELD_WIDTH;
268  valend -= SHORT_FIELD_WIDTH;
269  *valend = '\0';
270  pt[0] = Getf(valstart);
271 
272 #ifdef USE_POINT_INDICES_TO_INSERT
273  valstart -= (2 * SHORT_FIELD_WIDTH);
274  valend -= (2 * SHORT_FIELD_WIDTH);
275  *valend = '\0';
276  int psi = Geti(valstart) - 1;
277 
278 #if !defined(MDSERVER)
279 
280  if (psi < nPoints)
281  pts->SetPoint(psi, pt);
282  else {
283  int newSize = int(float(nPoints) * 1.1f);
284  if (newSize < psi) newSize = int(float(psi) * 1.1f);
285  if (newSize <= nPoints) newSize = nPoints + 1;
286 
287  qDebug() << "Resizing point array from " << nPoints
288  << " points to " << newSize
289  << " points because we need to insert point index "
290  << psi;
291  nPoints = newSize;
292  pts->GetData()->Resize(nPoints);
293  pts->SetNumberOfPoints(nPoints);
294  pts->SetPoint(psi, pt);
295  }
296 
297 #endif // if !defined(MDSERVER)
298 
299 #else
300 
301 #if !defined(MDSERVER)
302  pts->InsertNextPoint(pt);
303 #endif // if !defined(MDSERVER)
304 
305 #endif
306 
307  } else if (strncmp(line, "CHEXA", 5) == 0) {
308 #define INDEX_FIELD_WIDTH 8
309  // CHEXA requires more point indices so read another line.
310  ifile.getline(line + 72, 1024 - 72);
311 
312  char *valstart = line + 88;
313  char *valend = valstart;
314  verts[7] = Geti(valstart) - 1;
315 
316  valstart -= INDEX_FIELD_WIDTH;
317  *valend = '\0';
318  verts[6] = Geti(valstart) - 1;
319 
320  // Skip the blank
321  valstart -= INDEX_FIELD_WIDTH;
322  valend -= INDEX_FIELD_WIDTH;
323 
324  valstart -= INDEX_FIELD_WIDTH;
325  valend -= INDEX_FIELD_WIDTH;
326  *valend = '\0';
327  verts[5] = Geti(valstart) - 1;
328 
329  valstart -= INDEX_FIELD_WIDTH;
330  valend -= INDEX_FIELD_WIDTH;
331  *valend = '\0';
332  verts[4] = Geti(valstart) - 1;
333 
334  valstart -= INDEX_FIELD_WIDTH;
335  valend -= INDEX_FIELD_WIDTH;
336  *valend = '\0';
337  verts[3] = Geti(valstart) - 1;
338 
339  valstart -= INDEX_FIELD_WIDTH;
340  valend -= INDEX_FIELD_WIDTH;
341  *valend = '\0';
342  verts[2] = Geti(valstart) - 1;
343 
344  valstart -= INDEX_FIELD_WIDTH;
345  valend -= INDEX_FIELD_WIDTH;
346  *valend = '\0';
347  verts[1] = Geti(valstart) - 1;
348 
349  valstart -= INDEX_FIELD_WIDTH;
350  valend -= INDEX_FIELD_WIDTH;
351  *valend = '\0';
352  verts[0] = Geti(valstart) - 1;
353 
354  if (matCountOpt) {
355  valstart -= INDEX_FIELD_WIDTH;
356  valend -= INDEX_FIELD_WIDTH;
357  *valend = '\0';
358  matid = Geti(valstart);
359  }
360 
361 #if !defined(MDSERVER)
362  ugrid->InsertNextCell(VTK_HEXAHEDRON, 8, verts);
363  if (matCountOpt) m_matList.push_back(matid);
364 #endif
365  } else if (strncmp(line, "CTETRA", 6) == 0) {
366  char *valstart = line + 48;
367  char *valend = valstart;
368  verts[3] = Geti(valstart) - 1;
369 
370  valstart -= INDEX_FIELD_WIDTH;
371  *valend = '\0';
372  verts[2] = Geti(valstart) - 1;
373 
374  valstart -= INDEX_FIELD_WIDTH;
375  valend -= INDEX_FIELD_WIDTH;
376  *valend = '\0';
377  verts[1] = Geti(valstart) - 1;
378 
379  valstart -= INDEX_FIELD_WIDTH;
380  valend -= INDEX_FIELD_WIDTH;
381  *valend = '\0';
382  verts[0] = Geti(valstart) - 1;
383 
384  if (matCountOpt) {
385  valstart -= INDEX_FIELD_WIDTH;
386  valend -= INDEX_FIELD_WIDTH;
387  *valend = '\0';
388  matid = Geti(valstart);
389  }
390 
391 #if !defined(MDSERVER)
392  ugrid->InsertNextCell(VTK_TETRA, 4, verts);
393  if (matCountOpt) m_matList.push_back(matid);
394 #endif
395  } else if (strncmp(line, "CPYRAM", 6) == 0) {
396  char *valstart = line + 56;
397  char *valend = valstart;
398  verts[4] = Geti(valstart) - 1;
399 
400  valstart -= INDEX_FIELD_WIDTH;
401  *valend = '\0';
402  verts[3] = Geti(valstart) - 1;
403 
404  valstart -= INDEX_FIELD_WIDTH;
405  valend -= INDEX_FIELD_WIDTH;
406  *valend = '\0';
407  verts[2] = Geti(valstart) - 1;
408 
409  valstart -= INDEX_FIELD_WIDTH;
410  valend -= INDEX_FIELD_WIDTH;
411  *valend = '\0';
412  verts[1] = Geti(valstart) - 1;
413 
414  valstart -= INDEX_FIELD_WIDTH;
415  valend -= INDEX_FIELD_WIDTH;
416  *valend = '\0';
417  verts[0] = Geti(valstart) - 1;
418 
419  if (matCountOpt) {
420  valstart -= INDEX_FIELD_WIDTH;
421  valend -= INDEX_FIELD_WIDTH;
422  *valend = '\0';
423  matid = Geti(valstart);
424  }
425 
426 #if !defined(MDSERVER)
427  ugrid->InsertNextCell(VTK_PYRAMID, 5, verts);
428  if (matCountOpt) m_matList.push_back(matid);
429 #endif
430  } else if (strncmp(line, "CPENTA", 6) == 0) {
431  char *valstart = line + 64;
432  char *valend = valstart;
433  verts[5] = Geti(valstart) - 1;
434 
435  valstart -= INDEX_FIELD_WIDTH;
436  *valend = '\0';
437  verts[4] = Geti(valstart) - 1;
438 
439  valstart -= INDEX_FIELD_WIDTH;
440  valend -= INDEX_FIELD_WIDTH;
441  *valend = '\0';
442  verts[3] = Geti(valstart) - 1;
443 
444  valstart -= INDEX_FIELD_WIDTH;
445  valend -= INDEX_FIELD_WIDTH;
446  *valend = '\0';
447  verts[2] = Geti(valstart) - 1;
448 
449  valstart -= INDEX_FIELD_WIDTH;
450  valend -= INDEX_FIELD_WIDTH;
451  *valend = '\0';
452  verts[1] = Geti(valstart) - 1;
453 
454  valstart -= INDEX_FIELD_WIDTH;
455  valend -= INDEX_FIELD_WIDTH;
456  *valend = '\0';
457  verts[0] = Geti(valstart) - 1;
458 
459  if (matCountOpt) {
460  valstart -= INDEX_FIELD_WIDTH;
461  valend -= INDEX_FIELD_WIDTH;
462  *valend = '\0';
463  matid = Geti(valstart);
464  }
465  //
466  // http://www.simcenter.msstate.edu/docs/ug_io/3d_grid_file_type_nastran.html
467  // says that if 5th and 6th nodes are identical, then its really a 5
468  // noded pyramid.
469  //
470 #if !defined(MDSERVER)
471  if (verts[4] == verts[5])
472  ugrid->InsertNextCell(VTK_PYRAMID, 5, verts);
473  else
474  ugrid->InsertNextCell(VTK_WEDGE, 6, verts);
475  if (matCountOpt) m_matList.push_back(matid);
476 #endif
477  } else if (strncmp(line, "CQUAD4", 6) == 0) {
478  char *valstart = line + 48;
479  char *valend = valstart;
480  verts[3] = Geti(valstart) - 1;
481 
482  valstart -= INDEX_FIELD_WIDTH;
483  *valend = '\0';
484  verts[2] = Geti(valstart) - 1;
485 
486  valstart -= INDEX_FIELD_WIDTH;
487  valend -= INDEX_FIELD_WIDTH;
488  *valend = '\0';
489  verts[1] = Geti(valstart) - 1;
490 
491  valstart -= INDEX_FIELD_WIDTH;
492  valend -= INDEX_FIELD_WIDTH;
493  *valend = '\0';
494  verts[0] = Geti(valstart) - 1;
495 
496  if (matCountOpt) {
497  valstart -= INDEX_FIELD_WIDTH;
498  valend -= INDEX_FIELD_WIDTH;
499  *valend = '\0';
500  matid = Geti(valstart);
501  }
502 
503 #if !defined(MDSERVER)
504  ugrid->InsertNextCell(VTK_QUAD, 4, verts);
505  if (matCountOpt) m_matList.push_back(matid);
506 #endif
507  } else if (strncmp(line, "CTRIA2", 6) == 0 ||
508  strncmp(line, "CTRIA3", 6) == 0) {
509  char *valstart = line + 40;
510  char *valend = valstart;
511  verts[2] = Geti(valstart) - 1;
512 
513  valstart -= INDEX_FIELD_WIDTH;
514  *valend = '\0';
515  verts[1] = Geti(valstart) - 1;
516 
517  valstart -= INDEX_FIELD_WIDTH;
518  valend -= INDEX_FIELD_WIDTH;
519  *valend = '\0';
520  verts[0] = Geti(valstart) - 1;
521 
522  if (matCountOpt) {
523  valstart -= INDEX_FIELD_WIDTH;
524  valend -= INDEX_FIELD_WIDTH;
525  *valend = '\0';
526  matid = Geti(valstart);
527  }
528 
529 #if !defined(MDSERVER)
530  ugrid->InsertNextCell(VTK_TRIANGLE, 3, verts);
531  if (matCountOpt) m_matList.push_back(matid);
532 #endif
533  } else if (strncmp(line, "CBAR", 4) == 0) {
534  char *valstart = line + 32;
535  char *valend = valstart;
536  verts[1] = Geti(valstart) - 1;
537 
538  valstart -= INDEX_FIELD_WIDTH;
539  *valend = '\0';
540  verts[0] = Geti(valstart) - 1;
541 
542  if (matCountOpt) {
543  valstart -= INDEX_FIELD_WIDTH;
544  valend -= INDEX_FIELD_WIDTH;
545  *valend = '\0';
546  matid = Geti(valstart);
547  }
548 
549 #if !defined(MDSERVER)
550  ugrid->InsertNextCell(VTK_LINE, 2, verts);
551  if (matCountOpt) m_matList.push_back(matid);
552 #endif
553  } else if (strncmp(line, "TITLE", 5) == 0) {
554  titleRead = true;
555  char *ptr = 0;
556  if ((ptr = strstr(line, "=")) != 0)
557  m_title = /*std::string(*/ ++ptr /*)*/;
558  else
559  m_title = /*std::string(*/ line + 5 /*)*/;
560  } else if (strncmp(line, "CEND", 4) == 0 ||
561  strncmp(line, "BEGIN BULK", 10) == 0 ||
562  strncmp(line, "NASTRAN", 7) == 0) {
563  recognized = true;
564  }
565 
566  if (matid != INVALID_MAT_ID) m_uniqMatIds[matid] = 1;
567  }
568 
569  if (recognized) {
572  rpf->SetInputData(ugrid);
573  rpf->Update();
574 
575  m_dataObject = vtkUnstructuredGrid::New();
576  m_dataObject->ShallowCopy(rpf->GetOutput());
577  ugrid->Delete();
578  rpf->Delete();
579  }
580 
581  emit finished();
582 }
583 
585  : AbstractFileReader(parent) {}
586 
589 
590  m_reader->SetFileName(fileName().toLocal8Bit());
591  m_reader->Update();
592 
593  vtkUnstructuredGrid *grid = vtkUnstructuredGrid::SafeDownCast(
594  m_reader->GetOutput()->GetBlock(0));
595  int num = m_reader->GetNumberOfCellArrays();
596  for (int i = 0; i < num; ++i) {
597  QString name(m_reader->GetCellArrayName(i));
598  m_dataMap.insert(name, grid->GetCellData()->GetArray(
599  m_reader->GetCellArrayName(i)));
600  }
601 
602  emit finished();
603 }
604 
606  : AbstractFileReader(parent) {}
607 
609  // Open the file.
610  std::ifstream ifile(fileName().toLocal8Bit());
611  if (ifile.fail()) return;
612 
613  // Determine the file size and come up with an estimate of the
614  // number of vertices and cells so we can size the points and cells.
615  int nPoints = 100;
616  int nCells = 100;
617  vtkPoints *pts = vtkPoints::New();
618  pts->Allocate(nPoints);
619 
620  vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::New();
621  ugrid->SetPoints(pts);
622  ugrid->Allocate(nCells);
623  pts->Delete();
624 
625 #define MAX_ANSYS_LINE 200
626  char line[MAX_ANSYS_LINE];
627  float pt[3];
628  vtkIdType verts[8];
629  bool recognized = false;
630  bool fatalError = false;
631  bool readingCoordinates = false;
632  bool readingConnectivity = false;
633  int expectedLineLength = 0;
634 
635  int firstFieldWidth = 8;
636  int fieldWidth = 16;
637  int fieldStart = 56;
638 
639  for (int lineIndex = 0; !ifile.eof(); ++lineIndex) {
640  // Get the line
641  ifile.getline(line, MAX_ANSYS_LINE);
642 #if defined(_WIN32)
643  int linelen = static_cast<int>(strlen(line));
644 #else
645  int linelen = strlen(line) - 1; // account for the end of line char.
646 #endif
647  // If the line length is less than expected then pad with NULLs.
648  if (expectedLineLength > 0 && linelen < expectedLineLength) {
649  memset(line + linelen + 1, 0,
650  (MAX_ANSYS_LINE - linelen - 1) * sizeof(char));
651 #if 0
652  debug5 << "Padding line with NULLs" << endl;
653  debug5 << line << endl;
654 #endif
655  }
656 
657  // Give it a chance to break out of coordinate reading.
658  if (readingCoordinates) {
659  bool valid = true;
660  for (int i = 0; i < firstFieldWidth && valid; ++i)
661  valid &= (line[i] == ' ' || (line[i] >= '0' && line[i] <= '9'));
662 
663  if (!valid) {
664  expectedLineLength = 0;
665  readingCoordinates = false;
666  continue;
667  }
668  }
669 
670  if (readingCoordinates) {
671  char *valstart = line + fieldStart;
672  char *valend = valstart + fieldWidth;
673  pt[2] = atof(valstart);
674 
675  valstart -= fieldWidth;
676  valend -= fieldWidth;
677  *valend = '\0';
678  pt[1] = atof(valstart);
679 
680  valstart -= fieldWidth;
681  valend -= fieldWidth;
682  *valend = '\0';
683  pt[0] = atof(valstart);
684 
685 #if 0
686  debug4 << pt[0] << ", " << pt[1] << ", " << pt[2] << endl;
687 #endif
688  pts->InsertNextPoint(pt);
689  } else if (readingConnectivity) {
690  // Get whether this cell is real from column 0
691  line[fieldWidth] = '\0';
692  bool realCell = atoi(line) > 0;
693  if (!realCell) {
694  expectedLineLength = 0;
695  readingConnectivity = false;
696  continue;
697  }
698 
699  // Get the number of vertices in this cell from column 9.
700  static const int ncellsColumn = 9;
701  line[ncellsColumn * fieldWidth] = '\0';
702  int nverts = atoi(line + (ncellsColumn - 1) * fieldWidth);
703 
704  if (nverts == 8) {
705  char *valstart = line + fieldStart;
706  char *valend = valstart + fieldWidth;
707  for (int i = 0; i < 8; ++i) {
708  int ivalue = atoi(valstart);
709  verts[7 - i] = (ivalue > 0) ? (ivalue - 1) : ivalue;
710  valstart -= fieldWidth;
711  valend -= fieldWidth;
712  *valend = '\0';
713  }
714 
715 #if 0
716  for(int j = 0; j < 8; ++j)
717  debug4 << ", " << verts[j];
718  debug4 << endl;
719 #endif
720  ugrid->InsertNextCell(VTK_HEXAHEDRON, 8, verts);
721  } else {
722  qDebug() << "The file " << fileName()
723  << " contained cells "
724  "that are not hexes.";
725 
726  fatalError = true;
727  break;
728  }
729  } else if (STRNCASECMP(line, "NBLOCK", 6) == 0) {
730  char *comma = strstr(line, ",");
731  if (comma != 0) {
732  char *comma2 = strstr(comma + 1, ",");
733  if (comma2 != 0) {
734  *comma2 = '\0';
735  char *cols = comma + 1;
736  qDebug() << "Coordinate data stored in " << atoi(cols)
737  << " columns.";
738  recognized = true;
739  }
740  }
741 
742  // Get the field format string. Use it to set expectedLineLength,
743  // fieldWidth, and fieldStart.
744  ifile.getline(line, 1024);
745  if (line[0] == '(') {
746  interpretFormatStringEx(line, firstFieldWidth, fieldStart,
747  fieldWidth, expectedLineLength);
748  qDebug() << "firstFieldWidth=" << firstFieldWidth
749  << ", fieldStart=" << fieldStart
750  << ", fieldWidth=" << fieldWidth
751  << ", expectedLineLength=" << expectedLineLength;
752  readingCoordinates = true;
753  } else {
754  qDebug() << "Malformed format string: " << line;
755  fatalError = true;
756  }
757  } else if (STRNCASECMP(line, "EBLOCK", 6) == 0) {
758  char *comma = strstr(line, ",");
759  if (comma != 0) {
760  char *comma2 = strstr(comma + 1, ",");
761  if (comma2 != 0) {
762  *comma2 = '\0';
763  char *cols = comma + 1;
764  qDebug() << "Connectivity data stored in " << atoi(cols)
765  << " columns.";
766  recognized = true;
767  }
768  }
769 
770  // Get the field format string. Use it to set expectedLineLength,
771  // fieldWidth, and fieldStart.
772  ifile.getline(line, 1024);
773  if (line[0] == '(') {
774  interpretFormatStringEx(line, firstFieldWidth, fieldStart,
775  fieldWidth, expectedLineLength);
776  qDebug() << "firstFieldWidth=" << firstFieldWidth
777  << ", fieldStart=" << fieldStart
778  << ", fieldWidth=" << fieldWidth
779  << ", expectedLineLength=" << expectedLineLength;
780  readingConnectivity = true;
781  } else {
782  qDebug() << "Malformed format string: " << line;
783  fatalError = true;
784  }
785  } else if (STRNCASECMP(line, "/COM", 4) == 0) {
786  if (m_title.toStdString() == "")
787  m_title = /*std::string(*/ line + 6 /*)*/;
788  recognized = true;
789  } else if (STRNCASECMP(line, "/TITLE", 6) == 0) {
790  m_title = /*std::string(*/ line + 8 /*)*/;
791  recognized = true;
792  } else if (STRNCASECMP(line, "/BATCH", 6) == 0 ||
793  STRNCASECMP(line, "/NOPR", 5) == 0 ||
794  STRNCASECMP(line, "/CONFIG", 7) == 0 ||
795  STRNCASECMP(line, "/NOLIST", 7) == 0) {
796  recognized = true;
797  } else {
798  expectedLineLength = 0;
799  readingCoordinates = false;
800  readingConnectivity = false;
801  }
802  }
803 
804  if (recognized && !fatalError)
805  m_dataObject = ugrid;
806  else
807  ugrid->Delete();
808 
809  emit finished();
810 }
811 
813  int &fieldStart,
814  int &fieldWidth,
815  int &expectedLineLength) const {
816  char *fmt = line + 1;
817  char *ptr = 0;
818 
819  expectedLineLength = 0;
820  bool keepGoing = true;
821  while (keepGoing) {
822  int linelen = 0;
823 
824  if ((ptr = strstr(fmt, ",")) != 0) {
825  *ptr = '\0';
826  interpret(fmt, fieldWidth, linelen);
827  expectedLineLength += linelen;
828  fmt = ptr + 1;
829  } else if ((ptr = strstr(fmt, ")")) != 0) {
830  *ptr = '\0';
831  interpret(fmt, fieldWidth, linelen);
832  expectedLineLength += linelen;
833  keepGoing = false;
834  } else
835  keepGoing = false;
836  }
837 
838  fieldStart = expectedLineLength - fieldWidth;
839 }
840 
842  int &firstFieldWidth,
843  int &fieldStart,
844  int &fieldWidth,
845  int &expectedLineLength) const {
846  char *fmt = line + 1;
847  char *ptr = 0;
848 
849  expectedLineLength = 0;
850  bool keepGoing = true;
851  bool first = true;
852  while (keepGoing) {
853  int linelen = 0;
854 
855  if ((ptr = strstr(fmt, ",")) != 0) {
856  *ptr = '\0';
857  interpret(fmt, fieldWidth, linelen);
858  if (first) {
859  first = false;
860  firstFieldWidth = fieldWidth;
861  }
862  expectedLineLength += linelen;
863  fmt = ptr + 1;
864  } else if ((ptr = strstr(fmt, ")")) != 0) {
865  *ptr = '\0';
866  interpret(fmt, fieldWidth, linelen);
867  if (first) {
868  first = false;
869  firstFieldWidth = fieldWidth;
870  }
871  expectedLineLength += linelen;
872  keepGoing = false;
873  } else
874  keepGoing = false;
875  }
876 
877  fieldStart = expectedLineLength - fieldWidth;
878 }
879 
881  int &fieldWidth,
882  int &linelen) const {
883  int i0, i1, i2;
884 
885  qDebug() << "avtANSYSFileFormat::Interpret: " << fmt;
886 
887  // Example: 6e16.9
888  if (sscanf(fmt, "%de%d.%d", &i0, &i1, &i2) == 3) {
889  linelen = i0 * i1 / 2;
890  fieldWidth = i1;
891  }
892  // Example: 19i7
893  else if (sscanf(fmt, "%di%d", &i0, &i1) == 2) {
894  linelen = i0 * i1;
895  fieldWidth = i1;
896  } else {
897  qDebug() << "Invalid format string: " << fmt;
898  }
899 }
900 
902 
905  m_reader->SetFileName(fileName().toLocal8Bit());
906  m_reader->Update();
907  emit finished();
908 }
909 
911 
914  m_reader->SetFileName(fileName().toLocal8Bit());
915  m_reader->Update();
916  emit finished();
917 }
918 
919 } // namespace VtkUtils
std::string name
void setFileName(const QString &file)
AbstractFileReader(QObject *parent=nullptr)
void setTitle(const QString &title)
void interpretFormatString(char *line, int &fieldStart, int &fieldWidth, int &expectedLineLength) const
void interpret(const char *fmt, int &fieldWidth, int &linelen) const
AnsysFileReader(QObject *parent=nullptr)
void interpretFormatStringEx(char *line, int &firstFieldWidth, int &fieldStart, int &fieldWidth, int &expectedLineLength) const
DynaFileReader(QObject *parent=nullptr)
QMap< QString, vtkDataArray * > m_dataMap
FluentFileReader(QObject *parent=nullptr)
std::vector< int > m_matList
NastranFileReader(QObject *parent=nullptr)
std::map< int, int > m_uniqMatIds
ObjFileReader(QObject *parent=nullptr)
PdbFileReader(QObject *parent=nullptr)
PlyFileReader(QObject *parent=nullptr)
StlFileReader(QObject *parent=nullptr)
VtkFileReader(QObject *parent=nullptr)
static vtkUnstructuredGridRelevantPointsFilter * New()
#define MAX_ANSYS_LINE
#define INVALID_MAT_ID
#define SHORT_FIELD_WIDTH
#define LONG_FIELD_WIDTH
#define INDEX_FIELD_WIDTH
#define STRNCASECMP
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
static float Getf(const char *s)
void vtkInitOnce(T **obj)
Definition: vtkutils.h:44
static int Geti(const char *s)