gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
GModelIO_VTK.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include "GModel.h"
7 #include "OS.h"
8 #include "MPoint.h"
9 #include "MLine.h"
10 #include "MTriangle.h"
11 #include "MQuadrangle.h"
12 #include "MTetrahedron.h"
13 #include "MHexahedron.h"
14 #include "MPrism.h"
15 #include "MPyramid.h"
16 #include "StringUtils.h"
17 #include "GmshVersion.h"
18 
19 int GModel::writeVTK(const std::string &name, bool binary, bool saveAll,
20  double scalingFactor, bool bigEndian)
21 {
22  FILE *fp = Fopen(name.c_str(), binary ? "wb" : "w");
23  if(!fp) {
24  Msg::Error("Unable to open file '%s'", name.c_str());
25  return 0;
26  }
27 
28  if(noPhysicalGroups()) saveAll = true;
29 
30  // get the number of vertices and index the vertices in a continuous
31  // sequence
32  int numVertices = indexMeshVertices(saveAll);
33 
34  fprintf(fp, "# vtk DataFile Version 2.0\n");
35  fprintf(fp, "%s, Created by Gmsh %s \n", getName().c_str(), GMSH_VERSION);
36  if(binary)
37  fprintf(fp, "BINARY\n");
38  else
39  fprintf(fp, "ASCII\n");
40  fprintf(fp, "DATASET UNSTRUCTURED_GRID\n");
41 
42  // get all the entities in the model
43  std::vector<GEntity *> entities;
44  getEntities(entities);
45 
46  // write mesh vertices
47  fprintf(fp, "POINTS %d double\n", numVertices);
48  for(std::size_t i = 0; i < entities.size(); i++)
49  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
50  entities[i]->mesh_vertices[j]->writeVTK(fp, binary, scalingFactor,
51  bigEndian);
52  fprintf(fp, "\n");
53 
54  // loop over all elements we need to save and count vertices
55  int numElements = 0, totalNumInt = 0;
56  for(std::size_t i = 0; i < entities.size(); i++) {
57  if(entities[i]->physicals.size() || saveAll) {
58  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
59  if(entities[i]->getMeshElement(j)->getTypeForVTK()) {
60  numElements++;
61  totalNumInt += entities[i]->getMeshElement(j)->getNumVertices() + 1;
62  }
63  }
64  }
65  }
66 
67  // print vertex indices in ascii or binary
68  fprintf(fp, "CELLS %d %d\n", numElements, totalNumInt);
69  for(std::size_t i = 0; i < entities.size(); i++) {
70  if(entities[i]->physicals.size() || saveAll) {
71  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
72  if(entities[i]->getMeshElement(j)->getTypeForVTK())
73  entities[i]->getMeshElement(j)->writeVTK(fp, binary, bigEndian);
74  }
75  }
76  }
77  fprintf(fp, "\n");
78 
79  bool havePhysicals = false;
80  std::vector<int> physicals;
81 
82  // print element types in ascii or binary
83  fprintf(fp, "CELL_TYPES %d\n", numElements);
84  for(std::size_t i = 0; i < entities.size(); i++) {
85  if(entities[i]->physicals.size() || saveAll) {
86  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
87  int type = entities[i]->getMeshElement(j)->getTypeForVTK();
88  if(type) {
89  if(binary) {
90  // VTK always expects big endian binary data
91  if(!bigEndian) SwapBytes((char *)&type, sizeof(int), 1);
92  fwrite(&type, sizeof(int), 1, fp);
93  }
94  else {
95  fprintf(fp, "%d\n", type);
96  }
97  if(entities[i]->physicals.size()) {
98  physicals.push_back(entities[i]->physicals[0]);
99  havePhysicals = true;
100  }
101  else {
102  physicals.push_back(-1);
103  }
104  }
105  }
106  }
107  }
108 
109  if(havePhysicals && numElements == (int)physicals.size()) {
110  fprintf(fp, "\n");
111  fprintf(fp, "CELL_DATA %d\n", numElements);
112  fprintf(fp, "SCALARS CellEntityIds int 1\n");
113  fprintf(fp, "LOOKUP_TABLE default\n");
114  for(int i = 0; i < numElements; i++) {
115  int type = physicals[i];
116  if(binary) {
117  // VTK always expects big endian binary data
118  if(!bigEndian) SwapBytes((char *)&type, sizeof(int), 1);
119  fwrite(&type, sizeof(int), 1, fp);
120  }
121  else {
122  fprintf(fp, "%d\n", type);
123  }
124  }
125  }
126 
127  fclose(fp);
128  return 1;
129 }
130 
131 int GModel::readVTK(const std::string &name, bool bigEndian)
132 {
133  FILE *fp = Fopen(name.c_str(), "rb");
134  if(!fp) {
135  Msg::Error("Unable to open file '%s'", name.c_str());
136  return 0;
137  }
138 
139  char buffer[256], buffer2[256];
140  std::map<int, std::map<int, std::string> > physicals[4];
141 
142  if(!fgets(buffer, sizeof(buffer), fp)) {
143  fclose(fp);
144  return 0;
145  } // version line
146  if(!fgets(buffer, sizeof(buffer), fp)) {
147  fclose(fp);
148  return 0;
149  } // title
150 
151  if(fscanf(fp, "%s", buffer) != 1) // ASCII or BINARY
152  Msg::Error("Failed reading buffer");
153  bool binary = false;
154  if(!strcmp(buffer, "BINARY")) binary = true;
155 
156  if(fscanf(fp, "%s %s", buffer, buffer2) != 2) {
157  fclose(fp);
158  return 0;
159  }
160 
161  bool unstructured = false;
162  if(!strcmp(buffer, "DATASET") && !strcmp(buffer2, "UNSTRUCTURED_GRID"))
163  unstructured = true;
164 
165  if((strcmp(buffer, "DATASET") && strcmp(buffer2, "UNSTRUCTURED_GRID")) ||
166  (strcmp(buffer, "DATASET") && strcmp(buffer2, "POLYDATA"))) {
167  Msg::Error("VTK reader can only read unstructured or polydata datasets");
168  fclose(fp);
169  return 0;
170  }
171 
172  // read mesh vertices
173  int numVertices;
174  if(fscanf(fp, "%s %d %s", buffer, &numVertices, buffer2) != 3) return 0;
175  if(strcmp(buffer, "POINTS") || !numVertices) {
176  Msg::Warning("No points in dataset");
177  fclose(fp);
178  return 0;
179  }
180  int datasize;
181  if(!strcmp(buffer2, "double"))
182  datasize = sizeof(double);
183  else if(!strcmp(buffer2, "float"))
184  datasize = sizeof(float);
185  else {
186  Msg::Warning("VTK reader only accepts float or double datasets");
187  fclose(fp);
188  return 0;
189  }
190  Msg::Info("Reading %d points", numVertices);
191  std::vector<MVertex *> vertices(numVertices);
192  for(int i = 0; i < numVertices; i++) {
193  double xyz[3];
194  if(binary) {
195  if(datasize == sizeof(float)) {
196  float f[3];
197  if(fread(f, sizeof(float), 3, fp) != 3) {
198  fclose(fp);
199  return 0;
200  }
201  if(!bigEndian) SwapBytes((char *)f, sizeof(float), 3);
202  for(int j = 0; j < 3; j++) xyz[j] = f[j];
203  }
204  else {
205  if(fread(xyz, sizeof(double), 3, fp) != 3) {
206  fclose(fp);
207  return 0;
208  }
209  if(!bigEndian) SwapBytes((char *)xyz, sizeof(double), 3);
210  }
211  }
212  else {
213  if(fscanf(fp, "%lf %lf %lf", &xyz[0], &xyz[1], &xyz[2]) != 3) {
214  fclose(fp);
215  return 0;
216  }
217  }
218  vertices[i] = new MVertex(xyz[0], xyz[1], xyz[2]);
219  }
220 
221  // read mesh elements
222  int numElements, totalNumInt;
223  if(fscanf(fp, "%s %d %d", buffer, &numElements, &totalNumInt) != 3) {
224  fclose(fp);
225  return 0;
226  }
227 
228  bool haveCells = true;
229  bool haveLines = false;
230  if(!strcmp(buffer, "CELLS") && numElements > 0)
231  Msg::Info("Reading %d cells", numElements);
232  else if(!strcmp(buffer, "POLYGONS") && numElements > 0)
233  Msg::Info("Reading %d polygons", numElements);
234  else if(!strcmp(buffer, "LINES") && numElements > 0) {
235  haveCells = false;
236  haveLines = true;
237  Msg::Info("Reading %d lines", numElements);
238  }
239  else {
240  Msg::Warning("No cells or polygons in dataset");
241  fclose(fp);
242  return 0;
243  }
244 
245  int iPoint = getMaxElementaryNumber(0) + 1;
246  int iCurve = getMaxElementaryNumber(1) + 1;
247  int iSurface = getMaxElementaryNumber(2) + 1;
248  int iVolume = getMaxElementaryNumber(3) + 1;
249 
250  std::map<int, std::vector<MElement *> > elements[8];
251 
252  if(haveCells) {
253  std::vector<std::vector<MVertex *> > cells(numElements);
254  for(std::size_t i = 0; i < cells.size(); i++) {
255  int numVerts, n[100];
256  if(binary) {
257  if(fread(&numVerts, sizeof(int), 1, fp) != 1) {
258  fclose(fp);
259  return 0;
260  }
261  if(!bigEndian) SwapBytes((char *)&numVerts, sizeof(int), 1);
262  if((int)fread(n, sizeof(int), numVerts, fp) != numVerts) {
263  fclose(fp);
264  return 0;
265  }
266  if(!bigEndian) SwapBytes((char *)n, sizeof(int), numVerts);
267  }
268  else {
269  if(fscanf(fp, "%d", &numVerts) != 1) {
270  fclose(fp);
271  return 0;
272  }
273  for(int j = 0; j < numVerts; j++) {
274  if(fscanf(fp, "%d", &n[j]) != 1) {
275  fclose(fp);
276  return 0;
277  }
278  }
279  }
280  for(int j = 0; j < numVerts; j++) {
281  if(n[j] >= 0 && n[j] < (int)vertices.size())
282  cells[i].push_back(vertices[n[j]]);
283  else
284  Msg::Error("Wrong node index %d", n[j]);
285  }
286  }
287 
288  if(unstructured) {
289  if(fscanf(fp, "%s %d", buffer, &numElements) != 2) {
290  fclose(fp);
291  return 0;
292  }
293  if(strcmp(buffer, "CELL_TYPES") || numElements != (int)cells.size()) {
294  Msg::Error("No or invalid number of cells types");
295  fclose(fp);
296  return 0;
297  }
298  for(std::size_t i = 0; i < cells.size(); i++) {
299  int type;
300  if(binary) {
301  if(fread(&type, sizeof(int), 1, fp) != 1) {
302  fclose(fp);
303  return 0;
304  }
305  if(!bigEndian) SwapBytes((char *)&type, sizeof(int), 1);
306  }
307  else {
308  if(fscanf(fp, "%d", &type) != 1) {
309  fclose(fp);
310  return 0;
311  }
312  }
313  switch(type) {
314  case 1: elements[0][iPoint++].push_back(new MPoint(cells[i])); break;
315  // first order elements
316  case 3: elements[1][iCurve].push_back(new MLine(cells[i])); break;
317  case 5: elements[2][iSurface].push_back(new MTriangle(cells[i])); break;
318  case 9:
319  elements[3][iSurface].push_back(new MQuadrangle(cells[i]));
320  break;
321  case 10:
322  elements[4][iVolume].push_back(new MTetrahedron(cells[i]));
323  break;
324  case 12:
325  elements[5][iVolume].push_back(new MHexahedron(cells[i]));
326  break;
327  case 13: elements[6][iVolume].push_back(new MPrism(cells[i])); break;
328  case 14: elements[7][iVolume].push_back(new MPyramid(cells[i])); break;
329  // second order elements
330  case 21: elements[1][iCurve].push_back(new MLine3(cells[i])); break;
331  case 22:
332  elements[2][iSurface].push_back(new MTriangle6(cells[i]));
333  break;
334  case 23:
335  elements[3][iSurface].push_back(new MQuadrangle8(cells[i]));
336  break;
337  case 28:
338  elements[3][iSurface].push_back(new MQuadrangle9(cells[i]));
339  break;
340  case 24:
341  elements[4][iVolume].push_back(new MTetrahedron10(
342  cells[i][0], cells[i][1], cells[i][2], cells[i][3], cells[i][4],
343  cells[i][5], cells[i][6], cells[i][7], cells[i][9], cells[i][8]));
344  break;
345  case 25:
346  elements[5][iVolume].push_back(new MHexahedron20(
347  cells[i][0], cells[i][1], cells[i][2], cells[i][3], cells[i][4],
348  cells[i][5], cells[i][6], cells[i][7], cells[i][8], cells[i][11],
349  cells[i][13], cells[i][9], cells[i][16], cells[i][18], cells[i][19],
350  cells[i][17], cells[i][10], cells[i][12], cells[i][14],
351  cells[i][15]));
352  break;
353  case 29:
354  elements[5][iVolume].push_back(new MHexahedron27(
355  cells[i][0], cells[i][1], cells[i][2], cells[i][3], cells[i][4],
356  cells[i][5], cells[i][6], cells[i][7], cells[i][8], cells[i][11],
357  cells[i][13], cells[i][9], cells[i][16], cells[i][18], cells[i][19],
358  cells[i][17], cells[i][10], cells[i][12], cells[i][14],
359  cells[i][15], cells[i][22], cells[i][23], cells[i][21],
360  cells[i][24], cells[i][20], cells[i][25], cells[i][26]));
361  break;
362  case 26:
363  elements[6][iVolume].push_back(
364  new MPrism15(cells[i][0], cells[i][1], cells[i][2], cells[i][3],
365  cells[i][4], cells[i][5], cells[i][6], cells[i][9],
366  cells[i][7], cells[i][12], cells[i][14], cells[i][13],
367  cells[i][8], cells[i][10], cells[i][11]));
368  break;
369  case 32:
370  elements[6][iVolume].push_back(new MPrism18(
371  cells[i][0], cells[i][1], cells[i][2], cells[i][3], cells[i][4],
372  cells[i][5], cells[i][6], cells[i][9], cells[i][7], cells[i][12],
373  cells[i][14], cells[i][13], cells[i][8], cells[i][10], cells[i][11],
374  cells[i][15], cells[i][17], cells[i][16]));
375  break;
376  default: Msg::Error("Unknown type of cell %d", type); break;
377  }
378  }
379  }
380  else {
381  for(std::size_t i = 0; i < cells.size(); i++) {
382  int nbNodes = (int)cells[i].size();
383  switch(nbNodes) {
384  case 1: elements[0][iPoint++].push_back(new MPoint(cells[i])); break;
385  case 2: elements[1][iCurve].push_back(new MLine(cells[i])); break;
386  case 3: elements[2][iSurface].push_back(new MTriangle(cells[i])); break;
387  case 4:
388  elements[3][iSurface].push_back(new MQuadrangle(cells[i]));
389  break;
390  default:
391  Msg::Error("Unknown type of mesh element with %d nodes", nbNodes);
392  break;
393  }
394  }
395  }
396  }
397  else if(haveLines) {
398  if(!binary) {
399  int v0, v1;
400  char line[100000], *p, *pEnd, *pEnd2;
401  for(int k = 0; k < numElements; k++) {
402  physicals[1][iCurve][1] = "centerline";
403  if(!fgets(line, sizeof(line), fp)) {
404  fclose(fp);
405  return 0;
406  }
407  v0 = (int)strtol(line, &pEnd, 10); // ignore first line
408  v0 = (int)strtol(pEnd, &pEnd2, 10);
409  p = pEnd2;
410  while(1) {
411  v1 = strtol(p, &pEnd, 10);
412  if(p == pEnd) break;
413  elements[1][iCurve].push_back(new MLine(vertices[v0], vertices[v1]));
414  p = pEnd;
415  v0 = v1;
416  }
417  iCurve++;
418  }
419  }
420  else {
421  Msg::Error("Line import not done for binary VTK files");
422  }
423  }
424 
425  for(int i = 0; i < (int)(sizeof(elements) / sizeof(elements[0])); i++)
426  _storeElementsInEntities(elements[i]);
429 
430  // store the physical tags
431  for(int i = 0; i < 4; i++) _storePhysicalTagsInEntities(i, physicals[i]);
432 
433  fclose(fp);
434  return 1;
435 }
MTriangle.h
MPrism15
Definition: MPrism.h:263
GModel::getMaxElementaryNumber
int getMaxElementaryNumber(int dim)
Definition: GModel.cpp:817
MTetrahedron
Definition: MTetrahedron.h:34
MLine3
Definition: MLine.h:128
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
OS.h
MVertex
Definition: MVertex.h:24
GModel::getName
std::string getName() const
Definition: GModel.h:329
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
GModel::_storeElementsInEntities
void _storeElementsInEntities(std::map< int, std::vector< MElement * > > &map)
Definition: GModel.cpp:2273
MTetrahedron10
Definition: MTetrahedron.h:233
MPyramid
Definition: MPyramid.h:32
MPoint.h
MPrism
Definition: MPrism.h:34
MLine.h
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
MLine
Definition: MLine.h:21
GModel::readVTK
int readVTK(const std::string &name, bool bigEndian=false)
Definition: GModelIO_VTK.cpp:131
SwapBytes
void SwapBytes(char *array, int size, int n)
Definition: StringUtils.cpp:16
MHexahedron.h
MQuadrangle8
Definition: MQuadrangle.h:203
GModel::vertices
std::set< GVertex *, GEntityPtrLessThan > vertices
Definition: GModel.h:146
MPyramid.h
MHexahedron
Definition: MHexahedron.h:28
GModel::getEntities
void getEntities(std::vector< GEntity * > &entities, int dim=-1) const
Definition: GModel.cpp:651
MTriangle
Definition: MTriangle.h:26
StringUtils.h
MHexahedron27
Definition: MHexahedron.h:420
MPrism18
Definition: MPrism.h:413
MTetrahedron.h
MTriangle6
Definition: MTriangle.h:191
MHexahedron20
Definition: MHexahedron.h:251
MQuadrangle.h
GModel::noPhysicalGroups
bool noPhysicalGroups()
Definition: GModel.cpp:828
MPoint
Definition: MPoint.h:16
MPrism.h
MQuadrangle9
Definition: MQuadrangle.h:325
GModel::writeVTK
int writeVTK(const std::string &name, bool binary=false, bool saveAll=false, double scalingFactor=1.0, bool bigEndian=false)
Definition: GModelIO_VTK.cpp:19
GModel.h
GModel::_storeVerticesInEntities
void _storeVerticesInEntities(std::map< int, MVertex * > &vertices)
Definition: GModel.cpp:2496
line
Definition: shapeFunctions.h:342
GModel::_associateEntityWithMeshVertices
void _associateEntityWithMeshVertices()
Definition: GModel.cpp:2470
MQuadrangle
Definition: MQuadrangle.h:26
GModel::indexMeshVertices
std::size_t indexMeshVertices(bool all, int singlePartition=0, bool renumber=true)
Definition: GModel.cpp:2135
GModel::_storePhysicalTagsInEntities
void _storePhysicalTagsInEntities(int dim, std::map< int, std::map< int, std::string > > &map)
Definition: GModel.cpp:2568