MEPP2 Project
MshFileReader.h
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as
6 // published by the Free Software Foundation; either version 3 of
7 // the License, or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 #pragma once
12 
13 /*
14  * gmsh ref:
15  * - http://geuz.org/gmsh/doc/texinfo/gmsh.html#MSH-ASCII-file-format
16  */
17 
18 #include <iostream>
19 
20 #include <cstdio>
21 #include <cstring>
22 #include <cstdlib>
23 
26 
27 //Comment this one if you want a strict usage of msh file with only one Nodes and one Elements block.
28 #define USE_MULTI_BLOC
29 
30 namespace FEVV {
31 namespace IO {
32 
33 
34 using namespace StrUtils;
35 using namespace FileUtils;
36  //Return the dimension of an element type
37  template< typename IndexType >
38  inline IndexType dimensions(IndexType type)
39  {
40  //If it is a 2D element
41  if (type==2 || type==3 || type==9)
42  return 2;
43  //If it is a 3D element
44  else if (type==4 || type==5)
45  return 3;
46  //If we don't find a known element we return 0
47  return 0;
48  }
49 
50  //Get every node of an element
51  template< typename IndexType >
52  std::vector<IndexType> get_index(char* buffer, IndexType d)
53  {
54  //We split the line at every whitespace
55  char* token = strtok(buffer, " ");
56  token = strtok(NULL, " ");
57  //We get the type of the element
58  unsigned long type = static_cast<unsigned long>(atol(token));
59  unsigned long temp;
60  //If the dimensions of the element is unknown, meaning that the element is not implemented yet
61  if (dimensions(type)==0)
62  throw "MSH Reader: Error there is an unknown element or a not implemented yet element";
63  //If the dimensions of the element is different from the other elements
64  if (dimensions(type)!=static_cast<unsigned long>(d))
65  throw "MSH Reader: Error there is 2D elements with 3D Elements";
66 
67  //We get the number of nodes composing the element
68  switch(type)
69  {
70  case 2:
71  temp = 3;
72  break;
73  case 3:
74  case 4:
75  temp = 4;
76  break;
77  case 9:
78  temp = 6;
79  break;
80  case 5:
81  temp = 8;
82  break;
83  default:
84  temp=0;
85  }
86  //We get the next element of the buffer
87  token = strtok(NULL, " ");
88  std::vector<IndexType> indexes;
89  //We convert it to a long and we got the number of tags of the element
90  unsigned long nb = atol(token);
91  //If there is a wrong number of tag
92  if (nb > 4 || nb < 2)
93  throw "MSH Reader: Wrong number of tags, it should be between 2 and 4 included";
94  //We loop until the end of the line
95  for(unsigned long i(0); i<nb+temp; i++)
96  {
97  token = strtok(NULL, " ");
98  //If we finished the tags we push back in the vector the value of the node
99  if (i>=nb)
100  indexes.push_back(static_cast<IndexType>(atol(token)-1));
101  }
102  return indexes;
103  }
104 
105  //Initialize vectors and the dimension of the file
106  //It will read the file and get the number of nodes/elements to
107  //resize the vectors and get the dimension of the file
108 template< typename CoordType,
109  typename CoordNType,
110  typename CoordCType,
111  typename IndexType >
112  bool init_vectors( const std::string &file_path,
113  std::vector< std::vector<CoordType> >& points_coords,
114  std::vector< std::vector<CoordNType> >& normals_coords,
115  std::vector< std::vector<CoordCType> >& vertex_color_coords,
116  std::vector< std::vector<IndexType> >& line_indices,
117  std::vector< std::vector<CoordCType> >& lines_color_coords,
118  std::vector< std::vector<IndexType> >& face_indices,
119  std::vector< std::vector<CoordCType> >& face_color_coords,
120  IndexType& dim)
121  {
122  FILE* file;
123 
124  file = fopen(file_path.c_str(), "r");
125  if (file==NULL)
126  {
127  std::cerr << "MSH Reader : Unable to open " << file_path << std::endl;
128  return false;
129  }
130 
131  long nb_points(0);
132  long nb_p_color(0);
133  long nb_p_normal(0);
134  long nb_e_color(0);
135  long nb_elements(0);
136  int nb_param_reads;
137  long number;
138 
139 #ifndef USE_MULTI_BLOC
140  bool found_multi_nodes = false;
141  bool found_multi_elements = false;
142 #endif
143  const unsigned int T_MAX = 256;
144  char buffer[T_MAX];
145 
146  while(fgets(buffer, T_MAX, file) != NULL)
147  {
148  //If we found a Node block
149  if (strcmp(buffer, "$Nodes\n")==0)
150  {
151 #ifndef USE_MULTI_BLOC
152  if (!found_multi_nodes)
153  found_multi_nodes = true;
154  else
155  {
156  std::cerr << "You can't have multiple Nodes blocks" << std::endl;
157  return false;
158  }
159 #endif
160  //If the file is bad structured
161  if (fgets(buffer, T_MAX, file) == NULL)
162  {
163  std::cerr << "MSH Reader: Error in the file structure ($EndNodes missing ?)" << std::endl;
164  fclose(file);
165  return false;
166  }
167  //We get the number of nodes declared in this block
168  nb_param_reads = sscanf(buffer, "%ld", &number);
169  //If there is a wrong declaration
170  if (nb_param_reads < 1)
171  {
172  std::cerr << "MSH Reader: Error in the file structure ($Nodes tag with no number associated)" << std::endl;
173  fclose(file);
174  return false;
175  }
176  //We add the number of points found in this block to the total amount
177  nb_points += number;
178  }
179 
180  //If we found a Element block
181  else if (strcmp(buffer, "$Elements\n")==0)
182  {
183 #ifndef USE_MULTI_BLOC
184  if (!found_multi_elements)
185  found_multi_elements = true;
186  else
187  {
188  std::cerr << "You can't have multiple Nodes blocks" << std::endl;
189  return false;
190  }
191 #endif
192  //If the file is bad structured
193  if (fgets(buffer, T_MAX, file) == NULL)
194  {
195  std::cerr << "MSH Reader: Error in the file structure ($EndElements missing ?)" << std::endl;
196  fclose(file);
197  return false;
198  }
199  //We get the number of elements declared in this block
200  nb_param_reads = sscanf(buffer, "%ld", &number);
201  //If there is a wrong declaration
202  if (nb_param_reads < 1)
203  {
204  std::cerr << "MSH Reader: Error in the file structure ($Nodes tag with no number associated)" << std::endl;
205  fclose(file);
206  return false;
207  }
208  //We add the nomber of elements declared in this block to the total amount of elements
209  nb_elements += number;
210  //If the file is bad structured
211  if (fgets(buffer, T_MAX, file) == NULL)
212  {
213  std::cerr << "MSH Reader: Error in the file structure ($EndElements missing ?)" << std::endl;
214  fclose(file);
215  return false;
216  }
217  //If the dimension hasn't been changed until the beginning
218  if (dim==0)
219  {
220  //We read the type of the element
221  //The first time we use number variables but we don't need the first value
222  nb_param_reads = sscanf(buffer, "%ld %ld", &number, &number);
223  if (nb_param_reads != 2)
224  {
225  std::cerr << "MSH Reader: Error in the element declaration" << std::endl;
226  fclose(file);
227  return false;
228  }
229  //We get the dimension of the element
230  dim = static_cast<IndexType>(dimensions(number));
231  //If we get a 0 then there is an unexpected element and we explain the error
232  if (dim==0)
233  {
234  std::cerr << "MSH Reader: Error the element is not recognized or not supported yet" << std::endl;
235  fclose(file);
236  return false;
237  }
238  }
239  }
240 
241  //If we found a data block
242  else if (!(strcmp(buffer, "$NodeData\n")!=0 && strcmp(buffer, "$ElementData\n")!=0))
243  {
244  const char* types[] = {"NodeData", "ElementData"};
245  unsigned short type;
246  //If it is a NodeData block
247  if (strcmp(buffer, "$NodeData\n")==0)
248  {
249  type = 0;
250  }
251  //Otherwise it is an ElementData block
252  else
253  {
254  type = 1;
255  }
256  //If the file is bad structured
257  if (fgets(buffer, T_MAX, file) == NULL)
258  {
259  std::cerr << "MSH Reader: Error in the file structure ($End" << types[type] << " missing ?)" << std::endl;
260  fclose(file);
261  return false;
262  }
263  //We get the number of string tags refering to this block
264  nb_param_reads = sscanf(buffer, "%ld", &number);
265  //If the file is bad structured
266  if (nb_param_reads < 1)
267  {
268  std::cerr << "MSH Reader: Error in the file structure ($" << types[type] << " tag with no string tag associated)" << std::endl;
269  fclose(file);
270  return false;
271  }
272  bool found_color = false;
273  bool found_normal = false;
274  //We loop through every string tags searching for a color or a normal tag
275  for(int i=0; i<number; i++)
276  {
277  //If the file is bad structured
278  if (fgets(buffer, T_MAX, file) == NULL)
279  {
280  std::cerr << "MSH Reader: Error in the file structure ($" << types[type] << " with wrong number of string datas)" << std::endl;
281  fclose(file);
282  return false;
283  }
284  //If we found a color tag
285  if (strcmp(buffer, "\"Color\"\n")==0 ||
286  strcmp(buffer, "\"color\"\n")==0 ||
287  strcmp(buffer, "\"COLOR\"\n")==0 ||
288  strcmp(buffer, "\"Colour\"\n")==0 ||
289  strcmp(buffer, "\"colour\"\n")==0 ||
290  strcmp(buffer, "\"COLOUR\"\n")==0 ||
291  strcmp(buffer, "\"Colors\"\n")==0 ||
292  strcmp(buffer, "\"colors\"\n")==0 ||
293  strcmp(buffer, "\"COLORS\"\n")==0 )
294  found_color = true;
295  //If we found a normal tag
296  if (strcmp(buffer, "\"Normal\"\n")==0 ||
297  strcmp(buffer, "\"normal\"\n")==0 ||
298  strcmp(buffer, "\"NORMAL\"\n")==0 ||
299  strcmp(buffer, "\"Normals\"\n")==0 ||
300  strcmp(buffer, "\"normals\"\n")==0 ||
301  strcmp(buffer, "\"NORMALS\"\n")==0)
302  found_normal = true;
303  }
304  //We can't have both color and normal under the same tag
305  if (found_color && found_normal)
306  {
307  std::cerr << "MSH Reader: Color and normal values declared in the same data block" << std::endl;
308  fclose(file);
309  return false;
310  }
311  //Then if one of those two are present
312  if (found_color || found_normal)
313  {
314  //If the file is bad structured
315  if (fgets(buffer, T_MAX, file) == NULL)
316  {
317  std::cerr << "MSH Reader: Error in the file structure ($End" << types[type] << " missing ?)" << std::endl;
318  fclose(file);
319  return false;
320  }
321  //We get the number of real parameters
322  nb_param_reads = sscanf(buffer, "%ld", &number);
323  //If the file is bad structured
324  if (nb_param_reads != 1)
325  {
326  std::cerr << "MSH Reader: Error in the file structure ($" << types[type] << " tag with no real tag associated)" << std::endl;
327  fclose(file);
328  return false;
329  }
330  //We loop through all real tags
331  for(int i=0; i<number; i++)
332  {
333  //If the file is bad structured
334  if (fgets(buffer, T_MAX, file) == NULL)
335  {
336  std::cerr << "MSH Reader: Error in the file structure ($" << types[type] << " with wrong number of real datas)" << std::endl;
337  fclose(file);
338  return false;
339  }
340  }
341  //If the file is bad structured
342  if (fgets(buffer, T_MAX, file) == NULL)
343  {
344  std::cerr << "MSH Reader: Error in the file structure ($End" << types[type] << " missing ?)" << std::endl;
345  fclose(file);
346  return false;
347  }
348  //We get the number of integer tags
349  nb_param_reads = sscanf(buffer, "%ld", &number);
350  //If the file is bad structured
351  if (nb_param_reads != 1)
352  {
353  std::cerr << "MSH Reader: Error in the file structure ($" << types[type] << " tag with no integer tag associated)" << std::endl;
354  fclose(file);
355  return false;
356  }
357  //We loop throught the integer tags
358  for(int i=0; i<number; i++)
359  {
360  //If the file is bad structured
361  if (fgets(buffer, T_MAX, file) == NULL)
362  {
363  std::cerr << "MSH Reader: Error in the file structure ($" << types[type] << " with wrong number of real datas)" << std::endl;
364  fclose(file);
365  return false;
366  }
367  }
368  //We get the number of datas declared in this block
369  nb_param_reads = sscanf(buffer, "%ld", &number);
370  //If the file is bad structured
371  if (nb_param_reads != 1)
372  {
373  std::cerr << "MSH Reader: Error in the file structure ($" << types[type] << " tag with no integer tag associated)" << std::endl;
374  fclose(file);
375  return false;
376  }
377  //If we are in a NodeData block
378  if (type==0)
379  {
380  //If we found a color string in this block
381  if (found_color)
382  nb_p_color += number;
383  //Otherwise it is a normal data
384  else
385  nb_p_normal += number;
386  }
387  //If we are in an ElementData block
388  else
389  nb_e_color += number;
390  }
391  }
392  }
393  fclose(file);
394 
395  //If only a part of points or elements are colored or only a part of point have a normal
396  if ((nb_points!=nb_p_color && nb_p_color!=0) || (nb_elements!=nb_e_color && nb_e_color!=0) || (nb_points!=nb_p_normal && nb_p_normal!=0))
397  {
398  std::cerr << "MSH Reader: Error in the file, all nodes or elements should have or not color" << std::endl;
399  return false;
400  }
401  //We resize the vectors
402  points_coords.resize(nb_points);
403  normals_coords.resize(nb_p_normal);
404  vertex_color_coords.resize(nb_p_color);
405  //If the dimension is 2 we resize only the vectors for the 2 dimensions elements
406  if (dim==2)
407  {
408  face_indices.resize(nb_elements);
409  face_color_coords.resize(nb_e_color);
410  }
411  //Otherwise we resize the vectors for the 3 dimensions elements
412  else
413  {
414  line_indices.resize(nb_elements);
415  lines_color_coords.resize(nb_e_color);
416  }
417  return true;
418  }
419 
423 template< typename CoordType,
424  typename CoordNType,
425  typename CoordCType,
426  typename IndexType >
427  bool read_gmsh_file(const std::string &file_path,
428  std::vector< std::vector<CoordType> >& points_coords,
429  std::vector< std::vector<CoordNType> >& normals_coords,
430  std::vector< std::vector<CoordCType> >& vertex_color_coords,
431  std::vector< std::vector<IndexType> >& line_indices,
432  std::vector< std::vector<CoordCType> >& lines_color_coords,
433  std::vector< std::vector<IndexType> >& face_indices,
434  std::vector< std::vector<CoordCType> >& face_color_coords,
435  std::vector< std::vector < std::vector<double> > >& field_attributes,
436  std::vector< std::string >& field_names)
437  {
438  //We check if the file has the good extension
439  if (!FileUtils::has_extension(file_path, ".msh"))
440  {
441  std::cerr << "MSH Reader: File extension is inappropriate" << std::endl;
442  }
443 
444  points_coords.clear();
445  normals_coords.clear();
446  vertex_color_coords.clear();
447  face_indices.clear();
448  face_color_coords.clear();
449  line_indices.clear();
450  lines_color_coords.clear();
451  field_names.clear();
452  field_attributes.clear();
453 
454  //Dimension of the elements
455  IndexType dim(0);
456 
457  if (!init_vectors(file_path, points_coords, normals_coords, vertex_color_coords, line_indices, lines_color_coords, face_indices, face_color_coords, dim))
458  {
459  std::cerr << "Error during initialization" << std::endl;
460  return false;
461  }
462 
463  const long T_MAX = 256;
464  char buffer[T_MAX];
465  long number_param;
466 
467  FILE* file = fopen(file_path.c_str(), "r");
468 
469  if (file==NULL)
470  {
471  std::cerr << "MSH Reader: Unable to open file : " << file_path << std::endl;
472  return false;
473  }
474 
475  while( fgets(buffer, T_MAX, file) != NULL)
476  {
477  //------------------$MeshFormat-------------------
478  if (strcmp(buffer, "$MeshFormat\n")==0)
479  {
480  //If the file is bad structured
481  if (fgets(buffer, T_MAX, file) == NULL)
482  {
483  std::cerr << "MSH Reader: Error in the file structure ($EndMeshFormat missing ?)" << std::endl;
484  fclose(file);
485  return false;
486  }
487  float version;
488  unsigned int type;
489  unsigned int size;
490 
491  number_param = sscanf(buffer, "%f %u %u", &version, &type, &size);
492  //Currently only the version 2.2 is supported by Gmsh
493  if (version != 2.2f)
494  {
495  std::cerr << "MSH Reader: The " << version << " version is not supported yet" << std::endl;
496  fclose(file);
497  return false;
498  }
499  //We check if the type of the file is not ASCI (i.e : a type of 0 is an ASCI file)
500  if (type!=0)
501  {
502  std::cerr << "MSH Reader: Only the ASCII file type is supported" << std::endl;
503  fclose(file);
504  return false;
505  }
506  //We check if the size of the elements is good or not
507  //Actually Gmsh only supports sizeof(double)
508  if (size != sizeof(double))
509  {
510  std::cerr << "MSH Reader: The size of the elements should be " << sizeof(double) << " and not " << size << std::endl;
511  fclose(file);
512  return false;
513  }
514  //We check that we got the $EndMeshFormat tag
515  if (fgets(buffer, T_MAX, file) == NULL || strcmp(buffer, "$EndMeshFormat\n")!=0)
516  {
517  std::cerr << "MSH Reader: Error in the file structure ($EndMeshFormat missing)" << std::endl;
518  fclose(file);
519  return false;
520  }
521  }
522  //--------------------$EndMeshFormat---------------------
523 
524  //--------------------$Nodes-----------------------------
525  else if (strcmp(buffer, "$Nodes\n")==0)
526  {
527  //If the file is bad structured
528  if (fgets(buffer, T_MAX, file)==NULL)
529  {
530  std::cerr << "MSH Reader: Error in the file structure ($EndNodes missing ?)" << std::endl;
531  fclose(file);
532  return false;
533  }
534  long temp;
535  std::vector<double> temp_pts;
536 
537  //We get the number of nodes declared in this block
538  number_param = sscanf(buffer, "%ld", &temp);
539  if (number_param != 1)
540  {
541  std::cerr << "MSH Reader: Error in the number of nodes" << std::endl;
542  fclose(file);
543  return false;
544  }
545  long index;
546  //Then we add all the nodes on the block
547  for(long i(0); i<temp; ++i)
548  {
549  if (fgets(buffer, T_MAX, file) == NULL)
550  {
551  std::cerr << "MSH Reader: Error in the file, no node associated to a $Node tag" << std::endl;
552  fclose(file);
553  return false;
554  }
555  temp_pts.clear();
556  temp_pts.resize(3);
557  //We get the three coordinates
558  number_param = sscanf(buffer, "%ld %lf %lf %lf", &index, &temp_pts[0], &temp_pts[1], &temp_pts[2]);
559  if (number_param != 4)
560  {
561  std::cerr << "MSH Reader: Error in the file, wrong node declaration" << std::endl;
562  fclose(file);
563  return false;
564  }
565  //Then we assign it to the vector points_coords if the index is correct
566  //Don't forget the index-1 because msh format starts array at 1 and not 0
567  if (index-1 < static_cast<long>(points_coords.size()))
568  points_coords[index-1] = std::vector<CoordType>(temp_pts.begin(), temp_pts.end());
569  else
570  {
571  std::cerr << "MSH Reader: Error in the node index, " << points_coords.size() << " declared and there is the " << index << " declared." << std::endl;
572  fclose(file);
573  return false;
574  }
575  }
576  //We check that there is the end block
577  if (fgets(buffer, T_MAX, file)==NULL || (strcmp(buffer, "$EndNodes")!=0 && strcmp(buffer, "$EndNodes\n")!=0))
578  {
579  std::cerr << "MSH Reader: Error in the file structure ($EndNodes missing)" << std::endl;
580  fclose(file);
581  return false;
582  }
583  }
584  //--------------------$EndNodes--------------------------
585 
586  //--------------------$Elements--------------------------
587  else if (strcmp(buffer, "$Elements\n")==0)
588  {
589  //If the file is bad structured
590  if (fgets(buffer, T_MAX, file)==NULL)
591  {
592  std::cerr << "MSH Reader: Error in the file structure ($EndElements missing ?)" << std::endl;
593  fclose(file);
594  return false;
595  }
596  long temp;
597  //We get the number of elements declared in this block
598  number_param = sscanf(buffer, "%ld", &temp);
599  if (number_param != 1)
600  {
601  std::cerr << "MSH Reader: Error in the number of elements" << std::endl;
602  fclose(file);
603  return false;
604  }
605  long index;
606  //We get every elements
607  for(long i(0); i<temp; ++i)
608  {
609  if (fgets(buffer, T_MAX, file) == NULL)
610  {
611  std::cerr << "MSH Reader: Error in the file, no element associated to a $Elements tag" << std::endl;
612  fclose(file);
613  return false;
614  }
615  //We get the number of the element
616  number_param = sscanf(buffer, "%ld", &index);
617  //If the file is bad structured
618  if (number_param!=1)
619  {
620  std::cerr << "MSH Reader: Error in the file, wrong declaration of an element" << std::endl;
621  fclose(file);
622  return false;
623  }
624  try
625  {
626  //We get the number of the nodes composing the element
627  std::vector<IndexType> temp = std::move(get_index<IndexType>(buffer, dim));
628  //If it is a 2D file we add it to the 2D elements vector
629  if (dim==2)
630  {
631  //If the index of the element isn't too big for the size declared
632  //The file should NOT skip an index
633  if (index-1 < static_cast<long>(face_indices.size()))
634  face_indices[index-1] = temp;
635  //Otherwise we throw an error
636  else
637  {
638  std::cerr << "MSH Reader: Error in the 2D elements index, " << face_indices.size() << " declared and there is the " << index << " declared." << std::endl;
639  fclose(file);
640  return false;
641  }
642  }
643  //Otherwise we add it to the 3D elements vector
644  else
645  {
646  //If the index of the element isn't too big for the size declared
647  //The file should NOT skip an index
648  if (index-1 < static_cast<long>(line_indices.size()))
649  line_indices[index-1] = temp;
650  //Otherwise we throw an error
651  else
652  {
653  std::cerr << "MSH Reader: Error in the 2D elements index, " << line_indices.size() << " declared and there is the " << index << " declared." << std::endl;
654  fclose(file);
655  return false;
656  }
657  }
658  }
659  catch (char* e)
660  {
661  std::cerr << e << std::endl;
662  fclose(file);
663  return false;
664  }
665 
666  }
667  buffer[strlen(buffer)-1]='\0';
668  //If the file is bad structured
669  if (fgets(buffer, T_MAX, file)==NULL || (strcmp(buffer, "$EndElements")!=0 && strcmp(buffer, "$EndElements\n")!=0))
670  {
671  std::cerr << "MSH Reader: Error in the file structure ($EndElements missing)" << std::endl;
672  fclose(file);
673  return false;
674  }
675  }
676  //--------------------$EndElements-----------------------
677 
678  //--------------------$Data--------------------------
679  else if (!(strcmp(buffer, "$NodeData\n")!=0 && strcmp(buffer, "$ElementData\n")!=0))
680  {
681  const char* types[] = {"NodeData", "ElementData"};
682  unsigned short type, data = 2;
683  //If we are in a NodeData block
684  if (strcmp(buffer, "$NodeData\n")==0)
685  type = 0;
686  //If we are in a ElementData block
687  else
688  type = 1;
689 
690  //String parameters
691  if (fgets(buffer, T_MAX, file)==NULL)
692  {
693  std::cerr << "MSH Reader: Error in the file structure ($End" << types[type] << " missing ?)" << std::endl;
694  fclose(file);
695  return false;
696  }
697  long params;
698  //We get the number of string parameters
699  number_param = sscanf(buffer, "%ld", &params);
700  if (number_param != 1)
701  {
702  std::cerr << "MSH Reader: Error in the file, wrong" << types[type] << " declaration in the number of string parameters" << std::endl;
703  fclose(file);
704  return false;
705  }
706  //We loop through all the string paramaters
707  for(long i(0); i<=params; ++i)
708  {
709  if (fgets(buffer, T_MAX, file)==NULL)
710  {
711  std::cerr << "MSH Reader: Error in the file, wrong number of string parameters in " << types[type] << std::endl;
712  fclose(file);
713  return false;
714  }
715  if (i==0)
716  {
717  if (strcmp(buffer, "\"Color\"\n")==0 ||
718  strcmp(buffer, "\"color\"\n")==0 ||
719  strcmp(buffer, "\"COLOR\"\n")==0 ||
720  strcmp(buffer, "\"Colour\"\n")==0 ||
721  strcmp(buffer, "\"colour\"\n")==0 ||
722  strcmp(buffer, "\"COLOUR\"\n")==0 ||
723  strcmp(buffer, "\"Colors\"\n")==0 ||
724  strcmp(buffer, "\"colors\"\n")==0 ||
725  strcmp(buffer, "\"COLORS\"\n")==0 )
726  {
727  data = 0;
728  }
729  else if (strcmp(buffer, "\"Normal\"\n")==0 ||
730  strcmp(buffer, "\"normal\"\n")==0 ||
731  strcmp(buffer, "\"NORMAL\"\n")==0 ||
732  strcmp(buffer, "\"Normals\"\n")==0 ||
733  strcmp(buffer, "\"normals\"\n")==0 ||
734  strcmp(buffer, "\"NORMALS\"\n")==0)
735  {
736  data = 1;
737  }
738  else
739  {
740  data = 2;
741  buffer[strlen(buffer)-1] = '\0';
742  std::string a = (type==0)?"POINT_DATA_":"ELEMENT_DATA_";
743  a += std::string(buffer).substr(1, std::string(buffer).size()-2);
744  field_names.push_back(a);
745  }
746  }
747  }
748 
749  //Real paramaters
750  //We get the number of real parameters
751  number_param = sscanf(buffer, "%ld", &params);
752  if (number_param!=1)
753  {
754  std::cerr << "MSH Reader: Error in the file, wrong " << types[type] << " declaration in the number of real parameters" << std::endl;
755  fclose(file);
756  return false;
757  }
758  //We loop through all the real paramaters
759  for(long i(0); i<=params; ++i)
760  {
761  if (fgets(buffer, T_MAX, file)==NULL)
762  {
763  std::cerr << "MSH Reader: Error in the file, wrong number of real parameters in " << types[type] << std::endl;
764  fclose(file);
765  return false;
766  }
767  }
768 
769  //Integer parameters
770  //We get the number of integer parameters
771  number_param = sscanf(buffer, "%ld", &params);
772  if (number_param!=1)
773  {
774  std::cerr << "MSH Reader: Error in the file, wrong " << types[type] << " declaration in the number of integer parameters" << std::endl;
775  fclose(file);
776  return false;
777  }
778  //We loop until the last integer parameter (the number of datas in the block)
779  for(long i(0); i<params; ++i)
780  {
781  if (fgets(buffer, T_MAX, file)==NULL)
782  {
783  std::cerr << "MSH Reader: Error in the file, wrong number of integer parameters in " << types[type] << std::endl;
784  fclose(file);
785  return false;
786  }
787  }
788  //We get the number of datas declared in this block
789  number_param = sscanf(buffer, "%ld", &params);
790  if (number_param!=1)
791  {
792  std::cerr << "MSH Reader: Error in the file, wrong number of integer parameters in " << types[type] << std::endl;
793  fclose(file);
794  return false;
795  }
796 
797  std::vector<CoordCType> temp_vector_c;
798  std::vector<CoordNType> temp_vector_n;
799  std::vector< std::vector<double> > temp_vector_f;
800  temp_vector_f.clear();
801  double temp1, temp2, temp3;
802  //We loop through every declared datas
803  for(long i(0); i<params; i++)
804  {
805  if (fgets(buffer, T_MAX, file)==NULL)
806  {
807  std::cerr << "MSH Reader: Error in the file, wrong number of integer parameters in " << types[type] << std::endl;
808  fclose(file);
809  return false;
810  }
811  switch(data)
812  {
813  case 0:
814  temp_vector_c.clear();
815  temp_vector_c.reserve(3);
816  break;
817  case 1:
818  temp_vector_n.clear();
819  temp_vector_n.reserve(3);
820  break;
821  }
822  long index;
823  //We get all the values concerning the data (the index and the data itself)
824  //If it is a color we get three values
825  //Duplicate this if block, create temp4 et check for 5 number_param for color if you want to use alpha
826  number_param = sscanf(buffer, "%ld %lf %lf %lf", &index, &temp1, &temp2, &temp3);
827  if (number_param<1 || number_param>4)
828  {
829  std::cerr << "MSH Reader: Error in the file, wrong number of arguments for integer parameters in " << type << std::endl;
830  fclose(file);
831  return false;
832  }
833  --number_param;
834  switch(data)
835  {
836  case 0:
837  temp_vector_c.push_back(static_cast<CoordCType>(temp1));
838  if (number_param > 1)
839  temp_vector_c.push_back(static_cast<CoordCType>(temp2));
840  if (number_param > 2)
841  temp_vector_c.push_back(static_cast<CoordCType>(temp3));
842  break;
843  case 1:
844  temp_vector_n.push_back(static_cast<CoordNType>(temp1));
845  if (number_param > 1)
846  temp_vector_n.push_back(static_cast<CoordNType>(temp2));
847  if (number_param > 2)
848  temp_vector_n.push_back(static_cast<CoordNType>(temp3));
849  break;
850  case 2:
851  if (static_cast< long >(temp_vector_f.size()) < index)
852  temp_vector_f.resize(index);
853  temp_vector_f[index-1].push_back(temp1);
854  if (number_param > 1)
855  temp_vector_f[index-1].push_back(temp2);
856  if (number_param > 2)
857  temp_vector_f[index-1].push_back(temp3);
858  }
859 
860  //Si ce n'est pas des points mais des éléments
861  if (type!=0)
862  {
863  //Si ils sont de dimension 2 on les met dans le vector face_indices
864  if (dim==2)
865  {
866  if (data == 0)
867  {
868  //On vérifie qu'on ne sort pas de la taille du tableau
869  if (index - 1 < static_cast<long>(face_color_coords.size()))
870  face_color_coords[index-1] = temp_vector_c;
871  else
872  {
873  std::cerr << "MSH Reader: Wrong index usage in 2D element color, " << index << " used when the size is " << face_color_coords.size() << std::endl << buffer << std::endl;
874  fclose(file);
875  return false;
876  }
877  }
878  }
879  //Si ils sont de dimension 3 on les met dans le vecteur line_indices
880  else
881  {
882  if (data==0)
883  {
884  //On vérifie qu'on ne sort pas de la taille du tableau
885  if (index - 1 < static_cast<long>(lines_color_coords.size()))
886  lines_color_coords[index-1] = temp_vector_c;
887  else
888  {
889  std::cerr << "MSH Reader: Wrong index usage in 3D element color, " << index << " used when the size is " << lines_color_coords.size() << std::endl;
890  fclose(file);
891  return false;
892  }
893  }
894  }
895  }
896 
897  //Si ce sont des points
898  else
899  {
900  if (data==0)
901  {
902  //On vérifie qu'on ne sort pas de la taille du tableau
903  if (index - 1 < static_cast<long>(vertex_color_coords.size()))
904  vertex_color_coords[index-1] = temp_vector_c;
905  else
906  {
907  std::cerr << "MSH Reader: Wrong index usage in node color, " << index << " used when the size is " << vertex_color_coords.size() << std::endl;
908  fclose(file);
909  return false;
910  }
911  }
912  else if (data==1)
913  {
914  //On vérifie qu'on ne sort pas de la taille du tableau
915  if (index - 1 < static_cast<long>(normals_coords.size()))
916  normals_coords[index-1] = temp_vector_n;
917  else
918  {
919  std::cerr << "MSH Reader: Wrong index usage in node normal, " << index << " used when the size is " << normals_coords.size() << std::endl;
920  fclose(file);
921  return false;
922  }
923  }
924  }
925  }
926  if (!temp_vector_f.empty())
927  field_attributes.push_back(temp_vector_f);
928  //We create a string with the end tag
929  char s[20] = "$End";
930  strcat(s, types[type]);
931  //Then if the file is bad structured OR
932  //If the line found is not an ending tag of the Data block
933  //(i.e : $EndThingData or $EndThingData\n)
934  if (fgets(buffer, T_MAX, file)==NULL || (strcmp(buffer, s)!=0 && strcmp(buffer, strcat(buffer, "\n"))!=0))
935  {
936  std::cerr << "MSH Reader: Error in the file, missing $End" << types[type] << std::endl;
937  fclose(file);
938  return false;
939  }
940  }
941  //--------------------$EndData-----------------------
942  }
943  return true;
944  }
945 
946 }
947 }
FEVV::IO::get_index
std::vector< IndexType > get_index(char *buffer, IndexType d)
Definition: MshFileReader.h:52
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
StringUtilities.hpp
FEVV::IO::init_vectors
bool init_vectors(const std::string &file_path, std::vector< std::vector< CoordType > > &points_coords, std::vector< std::vector< CoordNType > > &normals_coords, std::vector< std::vector< CoordCType > > &vertex_color_coords, std::vector< std::vector< IndexType > > &line_indices, std::vector< std::vector< CoordCType > > &lines_color_coords, std::vector< std::vector< IndexType > > &face_indices, std::vector< std::vector< CoordCType > > &face_color_coords, IndexType &dim)
Definition: MshFileReader.h:112
FEVV::FileUtils::has_extension
bool has_extension(const std::string &file_name)
Definition: FileUtilities.hpp:58
FEVV::IO::read_gmsh_file
bool read_gmsh_file(const std::string &file_path, std::vector< std::vector< CoordType > > &points_coords, std::vector< std::vector< CoordNType > > &normals_coords, std::vector< std::vector< CoordCType > > &vertex_color_coords, std::vector< std::vector< IndexType > > &line_indices, std::vector< std::vector< CoordCType > > &lines_color_coords, std::vector< std::vector< IndexType > > &face_indices, std::vector< std::vector< CoordCType > > &face_color_coords, std::vector< std::vector< std::vector< double > > > &field_attributes, std::vector< std::string > &field_names)
Definition: MshFileReader.h:427
FileUtilities.hpp
FEVV::IO::dimensions
IndexType dimensions(IndexType type)
Definition: MshFileReader.h:38