Salome HOME
Minor: removing annoying print message
[modules/paravis.git] / src / Plugins / MedReader / IO / vtkMedUtilities.cxx
1 // Copyright (C) 2010-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "vtkMedUtilities.h"
21
22 #include "vtkMedMesh.h"
23 #include "vtkMedFamily.h"
24 #include "vtkMedGroup.h"
25 #include "vtkMedFamilyOnEntityOnProfile.h"
26 #include "vtkMedFamilyOnEntity.h"
27 #include "vtkMedEntityArray.h"
28 #include "vtkMedIntArray.h"
29 #include "vtkMedGrid.h"
30
31 #include "vtkObjectFactory.h"
32 #include "vtkInformation.h"
33 #include "vtkDoubleArray.h"
34 #include "vtkIntArray.h"
35 #include "vtkLongLongArray.h"
36 #include "vtkLongArray.h"
37 #include "vtkIdTypeArray.h"
38 #include "vtkCellType.h"
39 #include "vtkIdList.h"
40 #include "vtkMutableDirectedGraph.h"
41 #include "vtkStringArray.h"
42 #include "vtkDataSetAttributes.h"
43 #include "vtkOutEdgeIterator.h"
44 #include "vtkInformationIntegerKey.h"
45 #include "vtkInformationStringVectorKey.h"
46 #include "vtkInformationObjectBaseKey.h"
47
48 #include <sstream>
49 using namespace std;
50 char vtkMedUtilities::Separator='/';
51
52 const char* vtkMedUtilities::NoGroupName="No Group";
53 const char* vtkMedUtilities::OnPointName="OnPoint";
54 const char* vtkMedUtilities::OnCellName="OnCell";
55
56 const int MED_TRIA_CHILD_TO_PARENT_INDEX[3][3]=
57     {{0, 1, 3}, {1, 2, 4}, {2, 0, 5}};
58
59 const int MED_QUAD_CHILD_TO_PARENT_INDEX[4][3]=
60     {{0, 1, 4}, {1, 2, 5}, {2, 3, 6}, {3, 0, 7}};
61
62 const int MED_TETRA_CHILD_TO_PARENT_INDEX[4][6]=
63     {{0, 1, 2, 4, 5, 6},
64      {0, 3, 1, 7, 8, 4},
65      {1, 3, 2, 8, 9, 5},
66      {2, 3, 0, 9, 7, 6}};
67
68 const int MED_HEXA_CHILD_TO_PARENT_INDEX[6][8]=
69   {{0, 1, 2, 3, 8, 9, 10, 11},
70    {4, 7, 6, 5, 15, 14, 13, 12},
71    {0, 4, 5, 1, 16, 12, 17, 8},
72    {1, 5, 6, 2, 17, 13, 18, 9},
73    {2, 6, 7, 3, 18, 14, 19, 10},
74    {3, 7, 4, 0, 19, 15, 16, 11}};
75
76 const int MED_PYRA_CHILD_TO_PARENT_INDEX[5][8]=
77   {{0, 1, 2, 3, 5, 6, 7, 8},
78    {0, 4, 1, -1, 9, 10, 5, -1},
79    {1, 4, 2, -1, 10, 11, 6, -1},
80    {2, 4, 3, -1, 11, 12, 7, -1},
81    {3, 4, 0, -1, 12, 9, 8, -1}};
82
83 const int MED_PENTA_CHILD_TO_PARENT_INDEX[5][8]=
84   {{0, 1, 2, -1, 6, 7, 8, -1},
85    {3, 5, 4, -1, 11, 10, 9, -1},
86    {0, 3, 4, 1, 12, 9, 13, 6},
87    {1, 4, 5, 2, 13, 10, 14, 7},
88    {2, 5, 3, 0, 14, 11, 12, 8}};
89
90 vtkInformationKeyMacro(vtkMedUtilities, ELNO, Integer);
91 vtkInformationKeyMacro(vtkMedUtilities, ELGA, Integer);
92 vtkInformationKeyMacro(vtkMedUtilities, BLOCK_NAME, StringVector);
93 vtkInformationKeyMacro(vtkMedUtilities, STRUCT_ELEMENT, ObjectBase);
94 vtkInformationKeyMacro(vtkMedUtilities, STRUCT_ELEMENT_INDEX, Integer);
95
96 vtkDataArray* vtkMedUtilities::NewCoordArray()
97 {
98   return vtkMedUtilities::NewArray(MED_FLOAT64);
99 }
100
101 vtkDataArray* vtkMedUtilities::NewArray(med_field_type type)
102 {
103   switch(type)
104   {
105     case MED_FLOAT64:
106       if(sizeof(double)==8 && sizeof(med_float)==8)
107         return vtkDoubleArray::New();
108       vtkGenericWarningMacro("double type do not match med_float, aborting")
109       return NULL;
110     case MED_INT32:
111       if(sizeof(vtkIdType)==4)
112         return vtkIdTypeArray::New();
113       if(sizeof(int)==4)
114         return vtkIntArray::New();
115       if(sizeof(long)==4)
116         return vtkLongArray::New();
117       vtkGenericWarningMacro("No vtk type matches MED_INT32, aborting")
118       return NULL;
119     case MED_INT64:
120       if(sizeof(vtkIdType)==8)
121         return vtkIdTypeArray::New();
122       if(sizeof(long)==8)
123         return vtkLongArray::New();
124       if(sizeof(long long)==8)
125         return vtkLongLongArray::New();
126       vtkGenericWarningMacro("No vtk type matches MED_INT64, aborting")
127       ;
128       return NULL;
129     case MED_INT:
130       if(sizeof(med_int)==4)
131         return vtkMedUtilities::NewArray(MED_INT32);
132       if(sizeof(med_int)==8)
133         return vtkMedUtilities::NewArray(MED_INT64);
134       vtkGenericWarningMacro("No vtk type matches MED_INT, aborting")
135       return NULL;
136     default:
137       vtkGenericWarningMacro("the array type is not known, aborting.")
138       return NULL;
139   }
140 }
141
142 vtkAbstractArray* vtkMedUtilities::NewArray(med_attribute_type type)
143 {
144   switch(type)
145     {
146     case MED_ATT_FLOAT64 :
147       if(sizeof(double) == sizeof(med_float))
148         return vtkDoubleArray::New();
149       vtkGenericWarningMacro("double type do not match med_float, aborting");
150       return NULL;
151     case MED_ATT_INT :
152       if(sizeof(vtkIdType) == sizeof(med_int))
153         return vtkIdTypeArray::New();
154       if(sizeof(int) == sizeof(med_int))
155         return vtkIntArray::New();
156       if(sizeof(long) == sizeof(med_int))
157         return vtkLongArray::New();
158       if(sizeof(long long) == sizeof(med_int))
159         return vtkLongLongArray::New();
160       vtkGenericWarningMacro("med_int type does not match known VTK type, aborting");
161       return NULL;
162     case MED_ATT_NAME :
163       return vtkStringArray::New();
164     }
165   return NULL;
166 }
167
168 const char* vtkMedUtilities::GeometryName(med_geometry_type geometry)
169 {
170   switch(geometry)
171   {
172     case MED_POINT1:
173       return "MED_POINT1";
174     case MED_SEG2:
175       return "MED_SEG2";
176     case MED_SEG3:
177       return "MED_SEG3";
178     case MED_SEG4:
179       return "MED_SEG4";
180     case MED_TRIA3:
181       return "MED_TRIA3";
182     case MED_QUAD4:
183       return "MED_QUAD4";
184     case MED_TRIA6:
185       return "MED_TRIA6";
186     case MED_TRIA7:
187       return "MED_TRIA7";
188     case MED_QUAD8:
189       return "MED_QUAD8";
190     case MED_QUAD9:
191       return "MED_QUAD9";
192     case MED_TETRA4:
193       return "MED_TETRA4";
194     case MED_PYRA5:
195       return "MED_PYRA5";
196     case MED_PENTA6:
197       return "MED_PENTA6";
198     case MED_HEXA8:
199       return "MED_HEXA8";
200     case MED_TETRA10:
201       return "MED_TETRA10";
202     case MED_OCTA12:
203       return "MED_OCTA12";
204     case MED_PYRA13:
205       return "MED_PYRA13";
206     case MED_PENTA15:
207       return "MED_PENTA15";
208     case MED_HEXA20:
209       return "MED_HEXA20";
210     case MED_HEXA27:
211       return "MED_HEXA27";
212     case MED_POLYGON:
213       return "MED_POLYGON";
214     case MED_POLYHEDRON:
215       return "MED_POLYHEDRON";
216     case MED_NO_GEOTYPE:
217       return "MED_NO_GEOTYPE";
218     default:
219       return "UNKNOWN_GEOMETRY";
220   }
221 }
222
223 const char* vtkMedUtilities::EntityName(med_entity_type type)
224 {
225   switch(type)
226     {
227     case MED_CELL:
228       return "MED_CELL";
229     case MED_DESCENDING_FACE:
230       return "MED_DESCENDING_FACE";
231     case MED_DESCENDING_EDGE:
232       return "MED_DESCENDING_EDGE";
233     case MED_NODE:
234       return "MED_NODE";
235     case MED_NODE_ELEMENT:
236       return "MED_NODE_ELEMENT";
237     case MED_STRUCT_ELEMENT:
238       return "MED_STRUCT_ELEMENT";
239     case MED_UNDEF_ENTITY_TYPE:
240       return "MED_UNDEF_ENTITY_TYPE";
241     default:
242       return "UNKNOWN_ENTITY_TYPE ";
243   }
244 }
245
246 const char* vtkMedUtilities::ConnectivityName(med_connectivity_mode conn)
247 {
248   switch(conn)
249     {
250     case MED_NODAL:
251       return "MED_NODAL";
252     case MED_DESCENDING:
253       return "MED_DESCENDING";
254     case MED_NO_CMODE:
255       return "MED_NO_CMODE";
256     default:
257       return "UNKNOWN_CONNECTIVITY_MODE";
258   }
259 }
260
261 const std::string vtkMedUtilities::SimplifyName(const char* medName)
262 {
263   ostringstream sstr;
264   bool underscore=false;
265   bool space=false;
266   int l=strlen(medName);
267   for(int cc=0; cc<l; cc++)
268     {
269     if(medName[cc]==' ')
270       {
271       space=true;
272       continue;
273       }
274     else if(medName[cc]=='_')
275       {
276       underscore=true;
277       continue;
278       }
279     else
280       {
281       if(underscore||space)
282         sstr<<'_';
283       underscore=false;
284       space=false;
285       sstr<<medName[cc];
286       }
287     }
288   return sstr.str();
289 }
290
291 const std::string vtkMedUtilities::FamilyKey(const char* meshName,
292     int pointOrCell, const char* familyName)
293 {
294   ostringstream sstr;
295   sstr<<"FAMILY"<<Separator<<SimplifyName(meshName)<<Separator;
296   if(pointOrCell==OnCell)
297     sstr<<vtkMedUtilities::OnCellName;
298   else
299     sstr<<vtkMedUtilities::OnPointName;
300   sstr<<Separator<<SimplifyName(familyName);
301   return sstr.str();
302 }
303
304 const std::string vtkMedUtilities::GroupKey(const char* meshName,
305     int pointOrCell, const char* groupName)
306 {
307   ostringstream sstr;
308   sstr << "GROUP" << vtkMedUtilities::Separator
309       << vtkMedUtilities::SimplifyName(meshName)
310       << vtkMedUtilities::Separator;
311   if(pointOrCell==OnCell)
312     sstr << vtkMedUtilities::OnCellName;
313   else
314     sstr << vtkMedUtilities::OnPointName;
315   if(groupName==NULL)
316     sstr << vtkMedUtilities::Separator
317         << vtkMedUtilities::NoGroupName;
318   else
319     sstr << vtkMedUtilities::Separator
320         << vtkMedUtilities::SimplifyName(groupName);
321
322   return sstr.str();
323 }
324
325 const std::string vtkMedUtilities::EntityKey(const vtkMedEntity& entity)
326 {
327   ostringstream sstr;
328   sstr << "CELL_TYPE" << Separator << EntityName(entity.EntityType)
329       << Separator<<entity.GeometryName;
330   return sstr.str();
331 }
332
333 int vtkMedUtilities::GetNumberOfPoint(med_geometry_type geometry)
334 {
335   return geometry%100;
336 }
337
338 int vtkMedUtilities::GetDimension(med_geometry_type geometry)
339 {
340   return geometry/100;
341 }
342
343 int vtkMedUtilities::GetVTKCellType(med_geometry_type geometry)
344 {
345
346   switch(geometry)
347   {
348     case MED_POINT1:
349       return VTK_VERTEX;
350     case MED_SEG2:
351       return VTK_LINE;
352     case MED_SEG3:
353       return VTK_QUADRATIC_EDGE;
354     case MED_SEG4:
355       return VTK_CUBIC_LINE;
356     case MED_TRIA3:
357       return VTK_TRIANGLE;
358     case MED_QUAD4:
359       return VTK_QUAD;
360     case MED_TRIA6:
361       return VTK_QUADRATIC_TRIANGLE;
362     case MED_TRIA7:
363       return VTK_BIQUADRATIC_TRIANGLE;
364     case MED_QUAD8:
365       return VTK_QUADRATIC_QUAD;
366     case MED_QUAD9:
367       return VTK_BIQUADRATIC_QUAD;
368     case MED_TETRA4:
369       return VTK_TETRA;
370     case MED_PYRA5:
371       return VTK_PYRAMID;
372     case MED_PENTA6:
373       return VTK_WEDGE;
374     case MED_HEXA8:
375       return VTK_HEXAHEDRON;
376     case MED_TETRA10:
377       return VTK_QUADRATIC_TETRA;
378     case MED_OCTA12:
379       return VTK_HEXAGONAL_PRISM;
380     case MED_PYRA13:
381       return VTK_QUADRATIC_PYRAMID;
382     case MED_PENTA15:
383       return VTK_QUADRATIC_WEDGE;
384     case MED_HEXA20:
385       return VTK_QUADRATIC_HEXAHEDRON;
386     case MED_HEXA27:
387       return VTK_TRIQUADRATIC_HEXAHEDRON;
388     case MED_POLYGON:
389       return VTK_POLYGON;
390     case MED_POLYHEDRON:
391       return VTK_POLYHEDRON;
392     case MED_NO_GEOTYPE:
393       return VTK_EMPTY_CELL;
394     default:
395       vtkGenericWarningMacro("No vtk type matches " << geometry << ", aborting")
396       ;
397       return VTK_EMPTY_CELL;
398   }
399 }
400
401 int vtkMedUtilities::MedToVTKIndex(int vtktype, int node)
402 {
403   if(vtktype != VTK_TRIQUADRATIC_HEXAHEDRON)
404     return node;
405
406   static int VTK_TRIQUADRATIC_HEXAHEDRON_MED_TO_VTK_INDEX[27] =
407     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
408      24, 22, 21, 23, 20, 25, 26};
409
410   return VTK_TRIQUADRATIC_HEXAHEDRON_MED_TO_VTK_INDEX[node % 27] + static_cast<int>(27 * floor((double)node / 27));
411 }
412
413 int vtkMedUtilities::GetNumberOfNodes(med_geometry_type geometry)
414 {
415   switch(geometry)
416   {
417     case MED_POINT1:
418       return 1;
419     case MED_SEG2:
420       return 2;
421     case MED_SEG3:
422       return 3;
423     case MED_SEG4:
424       return 4;
425     case MED_TRIA3:
426       return 3;
427     case MED_QUAD4:
428       return 4;
429     case MED_TRIA6:
430       return 6;
431     case MED_TRIA7:
432       return 7;
433     case MED_QUAD8:
434       return 8;
435     case MED_QUAD9:
436       return 9;
437     case MED_TETRA4:
438       return 4;
439     case MED_PYRA5:
440       return 5;
441     case MED_PENTA6:
442       return 5;
443     case MED_HEXA8:
444       return 8;
445     case MED_TETRA10:
446       return 10;
447     case MED_OCTA12:
448       return 12;
449     case MED_PYRA13:
450       return 13;
451     case MED_PENTA15:
452       return 15;
453     case MED_HEXA20:
454       return 20;
455     case MED_HEXA27:
456       return 27;
457     case MED_POLYGON:
458       return -1;
459     case MED_POLYHEDRON:
460       return -1;
461     case MED_NO_GEOTYPE:
462       return 0;
463     default:
464       vtkGenericWarningMacro("No vtk type matches "
465                              << vtkMedUtilities::GeometryName(geometry)
466                              << ", aborting");
467       return -1;
468   }
469 }
470
471 int vtkMedUtilities::GetNumberOfSubEntity(med_geometry_type geometry)
472 {
473   switch(geometry)
474   {
475     case MED_POINT1:
476       return 0;
477     case MED_SEG2:
478       return 2;
479     case MED_SEG3:
480       return 3;
481     case MED_SEG4:
482       return 4;
483     case MED_TRIA3:
484       return 3;
485     case MED_QUAD4:
486       return 4;
487     case MED_TRIA6:
488       return 3;
489     case MED_TRIA7:
490       return 3;
491     case MED_QUAD8:
492       return 4;
493     case MED_QUAD9:
494       return 4;
495     case MED_TETRA4:
496       return 4;
497     case MED_PYRA5:
498       return 5;
499     case MED_PENTA6:
500       return 5;
501     case MED_HEXA8:
502       return 6;
503     case MED_TETRA10:
504       return 4;
505     case MED_OCTA12:
506       return 8;
507     case MED_PYRA13:
508       return 5;
509     case MED_PENTA15:
510       return 5;
511     case MED_HEXA20:
512       return 6;
513     case MED_HEXA27:
514       return 6;
515     case MED_POLYGON:
516       return -1;
517     case MED_POLYHEDRON:
518       return -1;
519     case MED_NO_GEOTYPE:
520       return 0;
521     default:
522       vtkGenericWarningMacro("No vtk type matches "
523                              << geometry
524                              << ", aborting");
525       return -1;
526   }
527 }
528
529 med_entity_type vtkMedUtilities::GetSubType(med_entity_type type)
530 {
531   switch(type)
532     {
533     case MED_CELL:
534       return MED_DESCENDING_FACE;
535     case MED_DESCENDING_FACE:
536       return MED_DESCENDING_EDGE;
537     case MED_DESCENDING_EDGE:
538       return MED_NODE;
539     default:
540       return MED_NODE;
541     }
542 }
543
544 med_geometry_type vtkMedUtilities::GetSubGeometry(
545     med_geometry_type geometry, int index)
546 {
547   switch(geometry)
548   {
549     case MED_SEG2:
550       return MED_POINT1;
551     case MED_SEG3:
552       return MED_POINT1;
553     case MED_SEG4:
554       return MED_POINT1;
555
556     case MED_TRIA3:
557       return MED_SEG2;
558     case MED_TRIA6:
559       return MED_SEG3;
560     case MED_TRIA7:
561       return MED_SEG3;
562
563     case MED_QUAD4:
564       return MED_SEG2;
565     case MED_QUAD8:
566       return MED_SEG3;
567     case MED_QUAD9:
568       return MED_SEG3;
569
570     case MED_TETRA4:
571       return MED_TRIA3;
572     case MED_TETRA10:
573       return MED_TRIA6;
574
575     case MED_PYRA5:
576       {
577       if(index==0)
578         return MED_QUAD4;
579       return MED_TRIA3;
580       }
581     case MED_PYRA13:
582       {
583       if(index==0)
584         return MED_QUAD8;
585       else
586         return MED_TRIA6;
587       }
588
589     case MED_PENTA6:
590       {
591       if(index==0||index==1)
592         return MED_TRIA3;
593       else
594         return MED_QUAD4;
595       }
596     case MED_PENTA15:
597       {
598       if(index==0||index==1)
599         return MED_TRIA6;
600       else
601         return MED_QUAD8;
602       }
603
604     case MED_HEXA8:
605       return MED_QUAD4;
606     case MED_HEXA20:
607       return MED_QUAD8;
608     case MED_HEXA27:
609       return MED_QUAD9;
610     default:
611       return MED_NONE;
612   }
613 }
614
615 int vtkMedUtilities::FormatPolyhedronForVTK(
616     vtkMedFamilyOnEntityOnProfile* foep, vtkIdType index,
617     vtkIdList* ids )
618 {
619   vtkMedEntityArray* array = foep->GetFamilyOnEntity()->GetEntityArray();
620   vtkMedIntArray* conn = array->GetConnectivityArray();
621   vtkMedIntArray* faceIndex = array->GetFaceIndex();
622   vtkMedIntArray* nodeIndex = array->GetNodeIndex();
623   med_int start = faceIndex->GetValue(index)-1;
624   med_int end = faceIndex->GetValue(index+1)-1;
625
626   // The format for the Polyhedrons is:
627   //(numCellFaces, numFace0Pts, id1, id2, id3, numFace1Pts,id1, id2, id3, ...)
628   ids->Reset();
629
630   if (array->GetConnectivity()==MED_NODAL)
631     {
632     ids->InsertNextId(end-start-1);
633     for (int ff = start; ff<end; ff++)
634       {
635       med_int fstart = nodeIndex->GetValue(ff)-1;
636       med_int fend = nodeIndex->GetValue(ff+1)-1;
637       ids->InsertNextId(fend-fstart);
638       for (med_int pt = fstart; pt<fend; pt++)
639         {
640         vtkIdType realIndex = foep->GetVTKPointIndex(conn->GetValue(pt)-1);
641         if(realIndex < 0)
642           {
643           vtkGenericWarningMacro("this polyhedron is not on this profile");
644           foep->SetValid(0);
645           return 0;
646           }
647         ids->InsertNextId(realIndex);
648         }
649       }
650     }
651
652   if (array->GetConnectivity()==MED_DESCENDING)
653     {
654     ids->InsertNextId(end-start);
655     vtkSmartPointer<vtkIdList> subIds = vtkSmartPointer<vtkIdList>::New();
656
657     for (int i = 0 ; i<nodeIndex->GetSize(); i++)
658       {
659       int numPoints =
660           vtkMedUtilities::GetNumberOfSubEntity(nodeIndex->GetValue(i));
661       ids->InsertNextId(numPoints);
662
663       vtkMedEntity entity;
664       entity.EntityType = MED_DESCENDING_FACE;
665       entity.GeometryType = nodeIndex->GetValue(i);
666
667       vtkMedEntityArray* theFaces =
668           array->GetParentGrid()->GetEntityArray(entity);
669
670       theFaces->GetCellVertices(conn->GetValue(i)-1, subIds);
671
672       for (int j = 0 ; j< numPoints; j++)
673         {
674         vtkIdType realIndex = foep->GetVTKPointIndex(subIds->GetId(j));
675         if(realIndex < 0)
676           {
677           vtkGenericWarningMacro("this polyhedron is not on this profile");
678           return 0;
679           }
680         ids->InsertNextId(realIndex);
681         }
682       }
683     }
684   return 1;
685 }
686
687 void vtkMedUtilities::SplitGroupKey(const char* name, std::string& mesh,
688     std::string& entity, std::string& group)
689 {
690   std::string remain;
691   remain=name;
692   mesh="*";
693   entity="*";
694   group="*";
695   std::string header="*";
696
697   if(remain=="*")
698     {
699     return;
700     }
701   std::string::size_type pos;
702   // First get the header, which must be "GROUP"
703   pos=remain.find_first_of(vtkMedUtilities::Separator);
704   header=remain.substr(0, pos);
705   remain=remain.substr(pos+1, remain.size()-pos-1);
706
707   // then get the mesh name
708   pos=remain.find_first_of(vtkMedUtilities::Separator);
709   mesh=remain.substr(0, pos);
710   if(mesh=="*"||pos==remain.size()-1)
711     return;
712   remain=remain.substr(pos+1, remain.size()-pos-1);
713
714   // then the entity name (OnPoint or OnCell)
715   pos=remain.find_first_of(vtkMedUtilities::Separator);
716   entity=remain.substr(0, pos);
717   if(entity=="*"||pos==remain.size()-1)
718     return;
719
720   // then the group
721   group=remain.substr(pos+1, remain.size()-pos-1);
722 }
723
724 int vtkMedUtilities::GetParentNodeIndex(med_geometry_type parentGeometry,
725     int subEntityIndex, int subEntityNodeIndex)
726 {
727   switch(parentGeometry)
728   {
729     case MED_TRIA3:
730     case MED_TRIA6:
731     case MED_TRIA7:
732       return MED_TRIA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
733     case MED_QUAD4:
734     case MED_QUAD8:
735     case MED_QUAD9:
736       return MED_QUAD_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
737     case MED_TETRA4:
738     case MED_TETRA10:
739       return MED_TETRA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
740     case MED_PYRA5:
741     case MED_PYRA13:
742       return MED_PYRA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
743     case MED_PENTA6:
744     case MED_PENTA15:
745       return MED_PENTA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
746     case MED_HEXA8:
747     case MED_HEXA20:
748     case MED_HEXA27:
749       return MED_HEXA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
750   }
751   return -1;
752 }
753
754 void vtkMedUtilities::ProjectConnectivity(med_geometry_type parentGeometry,
755     vtkIdList* parentIds, vtkIdList* subEntityIds, int subEntityIndex, bool invert)
756 {
757   for(int subEntityNodeIndex=0; subEntityNodeIndex
758       <subEntityIds->GetNumberOfIds(); subEntityNodeIndex++)
759     {
760     int realIndex = subEntityNodeIndex;
761     if(invert)
762       realIndex = subEntityIds->GetNumberOfIds() - subEntityNodeIndex - 1;
763     parentIds->SetId(GetParentNodeIndex(parentGeometry, subEntityIndex,
764         subEntityNodeIndex), subEntityIds->GetId(realIndex));
765     }
766 }
767
768 std::string vtkMedUtilities::GetModeKey(int index, double frequency, int maxindex)
769 {
770   std::ostringstream key;
771   key<<"[";
772   if(maxindex > 0)
773     {
774       int maxdecim = (int)floor(log(1.0*maxindex)/log(10.0));
775     int decim = 0;
776     if(index > 0)
777       {
778         decim = (int)floor(log(1.0*index)/log(10.0));
779       }
780     for(int i=decim; i<maxdecim; i++)
781       {
782       key << "0";
783       }
784     }
785
786   key<<index<<"] "<<frequency;
787   return key.str();
788 }
789
790 int vtkMedUtilities::GetModeFromKey(const char* key, int& index,
791     double& frequency)
792 {
793   const std::string k(key);
794   size_t index_start=k.find("[");
795   size_t index_end=k.find("]");
796   const string index_string=k.substr(index_start, index_end);
797   stringstream indexsstr;
798   indexsstr<<index_string;
799   indexsstr>>index;
800   const string freq_string=k.substr(index_end+1, string::npos);
801   stringstream freqsstr;
802   freqsstr<<freq_string;
803   freqsstr>>frequency;
804   return 1;
805 }
806
807 vtkMultiBlockDataSet* vtkMedUtilities::GetParent(vtkMultiBlockDataSet* root,
808                                 vtkStringArray* path)
809 {
810     vtkMultiBlockDataSet* output=root;
811     vtkMultiBlockDataSet* parent=output;
812     for(int depth = 0; depth<path->GetNumberOfValues(); depth++)
813       {
814       vtkStdString parentName = path->GetValue(depth);
815       bool found=false;
816       for(int blockId=0; blockId<parent->GetNumberOfBlocks(); blockId++)
817         {
818         vtkInformation* metaData=parent->GetMetaData(blockId);
819         if(metaData->Has(vtkCompositeDataSet::NAME()))
820           {
821           const char* blockName=metaData->Get(vtkCompositeDataSet::NAME());
822           if(parentName==blockName &&
823               vtkMultiBlockDataSet::SafeDownCast(
824                   parent->GetBlock(blockId))!=NULL)
825             {
826             parent=vtkMultiBlockDataSet::SafeDownCast(parent->GetBlock(blockId));
827             found=true;
828             break;
829             }
830           }
831         }
832       if (!found)
833         {
834         // If I am here, it means that I did not find any block with the good name, create one
835         int nb=parent->GetNumberOfBlocks();
836         vtkMultiBlockDataSet* block=vtkMultiBlockDataSet::New();
837         parent->SetBlock(nb, block);
838         block->Delete();
839         parent->GetMetaData(nb)->Set(vtkCompositeDataSet::NAME(),
840             parentName.c_str());
841         parent=block;
842         }
843       }
844     return parent;
845 }
846
847 int vtkMedUtilities::SizeOf(med_attribute_type type)
848 {
849   switch(type)
850     {
851     case MED_ATT_FLOAT64 : return sizeof(med_float);
852     case MED_ATT_INT : return sizeof(med_int);
853     case MED_ATT_NAME : return MED_NAME_SIZE * sizeof(char);
854     }
855   return 0;
856 }
857
858 bool operator==(const vtkMedComputeStep& cs0, const vtkMedComputeStep& cs1)
859 {
860   return cs0.IterationIt == cs1.IterationIt && cs0.TimeIt == cs1.TimeIt;
861 }
862
863 bool operator!=(const vtkMedComputeStep& cs0, const vtkMedComputeStep& cs1)
864 {
865   return cs0.IterationIt != cs1.IterationIt || cs0.TimeIt != cs1.TimeIt;
866 }
867
868 bool operator<(const vtkMedComputeStep& cs0, const vtkMedComputeStep& cs1)
869 {
870   if(cs0.IterationIt != cs1.IterationIt)
871     return cs0.IterationIt < cs1.IterationIt;
872   return cs0.TimeIt < cs1.TimeIt;
873 }
874
875 bool operator==(const vtkMedEntity& e0, const vtkMedEntity& e1)
876 {
877   return e0.EntityType == e1.EntityType && e0.GeometryType == e1.GeometryType;
878 }
879
880 bool operator!=(const vtkMedEntity& e0, const vtkMedEntity& e1)
881 {
882   return e0.EntityType != e1.EntityType || e0.GeometryType != e1.GeometryType;
883 }
884
885 bool operator<(const vtkMedEntity& e0, const vtkMedEntity& e1)
886 {
887   if(e0.EntityType != e1.EntityType)
888     return e0.EntityType < e1.EntityType;
889   return e0.GeometryType < e1.GeometryType;
890 }