Salome HOME
Merge from V6_main 13/12/2012
[modules/paravis.git] / src / Plugins / MedReader / IO / vtkMedUtilities.cxx
1 // Copyright (C) 2010-2012  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_STRUCT_GEO_INTERNAL:
217       return "MED_STRUCT_GEO_INTERNAL";
218     case MED_NO_GEOTYPE:
219       return "MED_NO_GEOTYPE";
220     default:
221       return "UNKNOWN_GEOMETRY";
222   }
223 }
224
225 const char* vtkMedUtilities::EntityName(med_entity_type type)
226 {
227   switch(type)
228     {
229     case MED_CELL:
230       return "MED_CELL";
231     case MED_DESCENDING_FACE:
232       return "MED_DESCENDING_FACE";
233     case MED_DESCENDING_EDGE:
234       return "MED_DESCENDING_EDGE";
235     case MED_NODE:
236       return "MED_NODE";
237     case MED_NODE_ELEMENT:
238       return "MED_NODE_ELEMENT";
239     case MED_STRUCT_ELEMENT:
240       return "MED_STRUCT_ELEMENT";
241     case MED_UNDEF_ENTITY_TYPE:
242       return "MED_UNDEF_ENTITY_TYPE";
243     default:
244       return "UNKNOWN_ENTITY_TYPE ";
245   }
246 }
247
248 const char* vtkMedUtilities::ConnectivityName(med_connectivity_mode conn)
249 {
250   switch(conn)
251     {
252     case MED_NODAL:
253       return "MED_NODAL";
254     case MED_DESCENDING:
255       return "MED_DESCENDING";
256     case MED_NO_CMODE:
257       return "MED_NO_CMODE";
258     default:
259       return "UNKNOWN_CONNECTIVITY_MODE";
260   }
261 }
262
263 const std::string vtkMedUtilities::SimplifyName(const char* medName)
264 {
265   ostringstream sstr;
266   bool underscore=false;
267   bool space=false;
268   int l=strlen(medName);
269   for(int cc=0; cc<l; cc++)
270     {
271     if(medName[cc]==' ')
272       {
273       space=true;
274       continue;
275       }
276     else if(medName[cc]=='_')
277       {
278       underscore=true;
279       continue;
280       }
281     else
282       {
283       if(underscore||space)
284         sstr<<'_';
285       underscore=false;
286       space=false;
287       sstr<<medName[cc];
288       }
289     }
290   return sstr.str();
291 }
292
293 const std::string vtkMedUtilities::FamilyKey(const char* meshName,
294     int pointOrCell, const char* familyName)
295 {
296   ostringstream sstr;
297   sstr<<"FAMILY"<<Separator<<SimplifyName(meshName)<<Separator;
298   if(pointOrCell==OnCell)
299     sstr<<vtkMedUtilities::OnCellName;
300   else
301     sstr<<vtkMedUtilities::OnPointName;
302   sstr<<Separator<<SimplifyName(familyName);
303   return sstr.str();
304 }
305
306 const std::string vtkMedUtilities::GroupKey(const char* meshName,
307     int pointOrCell, const char* groupName)
308 {
309   ostringstream sstr;
310   sstr << "GROUP" << vtkMedUtilities::Separator
311       << vtkMedUtilities::SimplifyName(meshName)
312       << vtkMedUtilities::Separator;
313   if(pointOrCell==OnCell)
314     sstr << vtkMedUtilities::OnCellName;
315   else
316     sstr << vtkMedUtilities::OnPointName;
317   if(groupName==NULL)
318     sstr << vtkMedUtilities::Separator
319         << vtkMedUtilities::NoGroupName;
320   else
321     sstr << vtkMedUtilities::Separator
322         << vtkMedUtilities::SimplifyName(groupName);
323
324   return sstr.str();
325 }
326
327 const std::string vtkMedUtilities::EntityKey(const vtkMedEntity& entity)
328 {
329   ostringstream sstr;
330   sstr << "CELL_TYPE" << Separator << EntityName(entity.EntityType)
331       << Separator<<entity.GeometryName;
332   return sstr.str();
333 }
334
335 int vtkMedUtilities::GetNumberOfPoint(med_geometry_type geometry)
336 {
337   return geometry%100;
338 }
339
340 int vtkMedUtilities::GetDimension(med_geometry_type geometry)
341 {
342   return geometry/100;
343 }
344
345 int vtkMedUtilities::GetVTKCellType(med_geometry_type geometry)
346 {
347
348   switch(geometry)
349   {
350     case MED_POINT1:
351       return VTK_VERTEX;
352     case MED_SEG2:
353       return VTK_LINE;
354     case MED_SEG3:
355       return VTK_QUADRATIC_EDGE;
356     case MED_SEG4:
357       return VTK_CUBIC_LINE;
358     case MED_TRIA3:
359       return VTK_TRIANGLE;
360     case MED_QUAD4:
361       return VTK_QUAD;
362     case MED_TRIA6:
363       return VTK_QUADRATIC_TRIANGLE;
364     case MED_TRIA7:
365       return VTK_BIQUADRATIC_TRIANGLE;
366     case MED_QUAD8:
367       return VTK_QUADRATIC_QUAD;
368     case MED_QUAD9:
369       return VTK_BIQUADRATIC_QUAD;
370     case MED_TETRA4:
371       return VTK_TETRA;
372     case MED_PYRA5:
373       return VTK_PYRAMID;
374     case MED_PENTA6:
375       return VTK_WEDGE;
376     case MED_HEXA8:
377       return VTK_HEXAHEDRON;
378     case MED_TETRA10:
379       return VTK_QUADRATIC_TETRA;
380     case MED_OCTA12:
381       return VTK_HEXAGONAL_PRISM;
382     case MED_PYRA13:
383       return VTK_QUADRATIC_PYRAMID;
384     case MED_PENTA15:
385       return VTK_QUADRATIC_WEDGE;
386     case MED_HEXA20:
387       return VTK_QUADRATIC_HEXAHEDRON;
388     case MED_HEXA27:
389       return VTK_TRIQUADRATIC_HEXAHEDRON;
390     case MED_POLYGON:
391       return VTK_POLYGON;
392     case MED_POLYHEDRON:
393       return VTK_POLYHEDRON;
394     case MED_NO_GEOTYPE:
395       return VTK_EMPTY_CELL;
396     default:
397       vtkGenericWarningMacro("No vtk type matches " << geometry << ", aborting")
398       ;
399       return VTK_EMPTY_CELL;
400   }
401 }
402
403 int vtkMedUtilities::MedToVTKIndex(int vtktype, int node)
404 {
405   if(vtktype != VTK_TRIQUADRATIC_HEXAHEDRON)
406     return node;
407
408   static int VTK_TRIQUADRATIC_HEXAHEDRON_MED_TO_VTK_INDEX[27] =
409     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
410      24, 22, 21, 23, 20, 25, 26};
411
412   return VTK_TRIQUADRATIC_HEXAHEDRON_MED_TO_VTK_INDEX[node % 27] + static_cast<int>(27 * floor((double)node / 27));
413 }
414
415 int vtkMedUtilities::GetNumberOfNodes(med_geometry_type geometry)
416 {
417   switch(geometry)
418   {
419     case MED_POINT1:
420       return 1;
421     case MED_SEG2:
422       return 2;
423     case MED_SEG3:
424       return 3;
425     case MED_SEG4:
426       return 4;
427     case MED_TRIA3:
428       return 3;
429     case MED_QUAD4:
430       return 4;
431     case MED_TRIA6:
432       return 6;
433     case MED_TRIA7:
434       return 7;
435     case MED_QUAD8:
436       return 8;
437     case MED_QUAD9:
438       return 9;
439     case MED_TETRA4:
440       return 4;
441     case MED_PYRA5:
442       return 5;
443     case MED_PENTA6:
444       return 5;
445     case MED_HEXA8:
446       return 8;
447     case MED_TETRA10:
448       return 10;
449     case MED_OCTA12:
450       return 12;
451     case MED_PYRA13:
452       return 13;
453     case MED_PENTA15:
454       return 15;
455     case MED_HEXA20:
456       return 20;
457     case MED_HEXA27:
458       return 27;
459     case MED_POLYGON:
460       return -1;
461     case MED_POLYHEDRON:
462       return -1;
463     case MED_NO_GEOTYPE:
464       return 0;
465     default:
466       vtkGenericWarningMacro("No vtk type matches "
467                              << vtkMedUtilities::GeometryName(geometry)
468                              << ", aborting");
469       return -1;
470   }
471 }
472
473 int vtkMedUtilities::GetNumberOfSubEntity(med_geometry_type geometry)
474 {
475   switch(geometry)
476   {
477     case MED_POINT1:
478       return 0;
479     case MED_SEG2:
480       return 2;
481     case MED_SEG3:
482       return 3;
483     case MED_SEG4:
484       return 4;
485     case MED_TRIA3:
486       return 3;
487     case MED_QUAD4:
488       return 4;
489     case MED_TRIA6:
490       return 3;
491     case MED_TRIA7:
492       return 3;
493     case MED_QUAD8:
494       return 4;
495     case MED_QUAD9:
496       return 4;
497     case MED_TETRA4:
498       return 4;
499     case MED_PYRA5:
500       return 5;
501     case MED_PENTA6:
502       return 5;
503     case MED_HEXA8:
504       return 6;
505     case MED_TETRA10:
506       return 4;
507     case MED_OCTA12:
508       return 8;
509     case MED_PYRA13:
510       return 5;
511     case MED_PENTA15:
512       return 5;
513     case MED_HEXA20:
514       return 6;
515     case MED_HEXA27:
516       return 6;
517     case MED_POLYGON:
518       return -1;
519     case MED_POLYHEDRON:
520       return -1;
521     case MED_NO_GEOTYPE:
522       return 0;
523     default:
524       vtkGenericWarningMacro("No vtk type matches "
525                              << geometry
526                              << ", aborting");
527       return -1;
528   }
529 }
530
531 med_entity_type vtkMedUtilities::GetSubType(med_entity_type type)
532 {
533   switch(type)
534     {
535     case MED_CELL:
536       return MED_DESCENDING_FACE;
537     case MED_DESCENDING_FACE:
538       return MED_DESCENDING_EDGE;
539     case MED_DESCENDING_EDGE:
540       return MED_NODE;
541     default:
542       return MED_NODE;
543     }
544 }
545
546 med_geometry_type vtkMedUtilities::GetSubGeometry(
547     med_geometry_type geometry, int index)
548 {
549   switch(geometry)
550   {
551     case MED_SEG2:
552       return MED_POINT1;
553     case MED_SEG3:
554       return MED_POINT1;
555     case MED_SEG4:
556       return MED_POINT1;
557
558     case MED_TRIA3:
559       return MED_SEG2;
560     case MED_TRIA6:
561       return MED_SEG3;
562     case MED_TRIA7:
563       return MED_SEG3;
564
565     case MED_QUAD4:
566       return MED_SEG2;
567     case MED_QUAD8:
568       return MED_SEG3;
569     case MED_QUAD9:
570       return MED_SEG3;
571
572     case MED_TETRA4:
573       return MED_TRIA3;
574     case MED_TETRA10:
575       return MED_TRIA6;
576
577     case MED_PYRA5:
578       {
579       if(index==0)
580         return MED_QUAD4;
581       return MED_TRIA3;
582       }
583     case MED_PYRA13:
584       {
585       if(index==0)
586         return MED_QUAD8;
587       else
588         return MED_TRIA6;
589       }
590
591     case MED_PENTA6:
592       {
593       if(index==0||index==1)
594         return MED_TRIA3;
595       else
596         return MED_QUAD4;
597       }
598     case MED_PENTA15:
599       {
600       if(index==0||index==1)
601         return MED_TRIA6;
602       else
603         return MED_QUAD8;
604       }
605
606     case MED_HEXA8:
607       return MED_QUAD4;
608     case MED_HEXA20:
609       return MED_QUAD8;
610     case MED_HEXA27:
611       return MED_QUAD9;
612     default:
613       return MED_NONE;
614   }
615 }
616
617 int vtkMedUtilities::FormatPolyhedronForVTK(
618     vtkMedFamilyOnEntityOnProfile* foep, vtkIdType index,
619     vtkIdList* ids )
620 {
621   vtkMedEntityArray* array = foep->GetFamilyOnEntity()->GetEntityArray();
622   vtkMedIntArray* conn = array->GetConnectivityArray();
623   vtkMedIntArray* faceIndex = array->GetFaceIndex();
624   vtkMedIntArray* nodeIndex = array->GetNodeIndex();
625   med_int start = faceIndex->GetValue(index)-1;
626   med_int end = faceIndex->GetValue(index+1)-1;
627
628   // The format for the Polyhedrons is:
629   //(numCellFaces, numFace0Pts, id1, id2, id3, numFace1Pts,id1, id2, id3, ...)
630   ids->Reset();
631
632   if (array->GetConnectivity()==MED_NODAL)
633     {
634     ids->InsertNextId(end-start);
635     for (int ff = start; ff<end; ff++)
636       {
637       med_int fstart = nodeIndex->GetValue(ff)-1;
638       med_int fend = nodeIndex->GetValue(ff+1)-1;
639       ids->InsertNextId(fend-fstart);
640       for (med_int pt = fstart; pt<fend; pt++)
641         {
642         vtkIdType realIndex = foep->GetVTKPointIndex(conn->GetValue(pt)-1);
643         if(realIndex < 0)
644           {
645           vtkGenericWarningMacro("this polyhedron is not on this profile");
646           foep->SetValid(0);
647           return 0;
648           }
649         ids->InsertNextId(realIndex);
650         }
651       }
652     }
653
654   if (array->GetConnectivity()==MED_DESCENDING)
655     {
656     ids->InsertNextId(end-start);
657     vtkSmartPointer<vtkIdList> subIds = vtkSmartPointer<vtkIdList>::New();
658
659     for (int i = 0 ; i<nodeIndex->GetSize(); i++)
660       {
661       int numPoints =
662           vtkMedUtilities::GetNumberOfSubEntity(nodeIndex->GetValue(i));
663       ids->InsertNextId(numPoints);
664
665       vtkMedEntity entity;
666       entity.EntityType = MED_DESCENDING_FACE;
667       entity.GeometryType = nodeIndex->GetValue(i);
668
669       vtkMedEntityArray* theFaces =
670           array->GetParentGrid()->GetEntityArray(entity);
671
672       theFaces->GetCellVertices(conn->GetValue(i)-1, subIds);
673
674       for (int j = 0 ; j< numPoints; j++)
675         {
676         vtkIdType realIndex = foep->GetVTKPointIndex(subIds->GetId(j));
677         if(realIndex < 0)
678           {
679           vtkGenericWarningMacro("this polyhedron is not on this profile");
680           return 0;
681           }
682         ids->InsertNextId(realIndex);
683         }
684       }
685     }
686   return 1;
687 }
688
689 void vtkMedUtilities::SplitGroupKey(const char* name, vtkstd::string& mesh,
690     vtkstd::string& entity, vtkstd::string& group)
691 {
692   vtkstd::string remain;
693   remain=name;
694   mesh="*";
695   entity="*";
696   group="*";
697   vtkstd::string header="*";
698
699   if(remain=="*")
700     {
701     return;
702     }
703   vtkstd::string::size_type pos;
704   // First get the header, which must be "GROUP"
705   pos=remain.find_first_of(vtkMedUtilities::Separator);
706   header=remain.substr(0, pos);
707   remain=remain.substr(pos+1, remain.size()-pos-1);
708
709   // then get the mesh name
710   pos=remain.find_first_of(vtkMedUtilities::Separator);
711   mesh=remain.substr(0, pos);
712   if(mesh=="*"||pos==remain.size()-1)
713     return;
714   remain=remain.substr(pos+1, remain.size()-pos-1);
715
716   // then the entity name (OnPoint or OnCell)
717   pos=remain.find_first_of(vtkMedUtilities::Separator);
718   entity=remain.substr(0, pos);
719   if(entity=="*"||pos==remain.size()-1)
720     return;
721
722   // then the group
723   group=remain.substr(pos+1, remain.size()-pos-1);
724 }
725
726 int vtkMedUtilities::GetParentNodeIndex(med_geometry_type parentGeometry,
727     int subEntityIndex, int subEntityNodeIndex)
728 {
729   switch(parentGeometry)
730   {
731     case MED_TRIA3:
732     case MED_TRIA6:
733     case MED_TRIA7:
734       return MED_TRIA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
735     case MED_QUAD4:
736     case MED_QUAD8:
737     case MED_QUAD9:
738       return MED_QUAD_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
739     case MED_TETRA4:
740     case MED_TETRA10:
741       return MED_TETRA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
742     case MED_PYRA5:
743     case MED_PYRA13:
744       return MED_PYRA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
745     case MED_PENTA6:
746     case MED_PENTA15:
747       return MED_PENTA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
748     case MED_HEXA8:
749     case MED_HEXA20:
750     case MED_HEXA27:
751       return MED_HEXA_CHILD_TO_PARENT_INDEX[subEntityIndex][subEntityNodeIndex];
752   }
753   return -1;
754 }
755
756 void vtkMedUtilities::ProjectConnectivity(med_geometry_type parentGeometry,
757     vtkIdList* parentIds, vtkIdList* subEntityIds, int subEntityIndex, bool invert)
758 {
759   for(int subEntityNodeIndex=0; subEntityNodeIndex
760       <subEntityIds->GetNumberOfIds(); subEntityNodeIndex++)
761     {
762     int realIndex = subEntityNodeIndex;
763     if(invert)
764       realIndex = subEntityIds->GetNumberOfIds() - subEntityNodeIndex - 1;
765     parentIds->SetId(GetParentNodeIndex(parentGeometry, subEntityIndex,
766         subEntityNodeIndex), subEntityIds->GetId(realIndex));
767     }
768 }
769
770 std::string vtkMedUtilities::GetModeKey(int index, double frequency, int maxindex)
771 {
772   std::ostringstream key;
773   key<<"[";
774   if(maxindex > 0)
775     {
776       int maxdecim = (int)floor(log(1.0*maxindex)/log(10.0));
777     int decim = 0;
778     if(index > 0)
779       {
780         decim = (int)floor(log(1.0*index)/log(10.0));
781       }
782     for(int i=decim; i<maxdecim; i++)
783       {
784       key << "0";
785       }
786     }
787
788   key<<index<<"] "<<frequency;
789   return key.str();
790 }
791
792 int vtkMedUtilities::GetModeFromKey(const char* key, int& index,
793     double& frequency)
794 {
795   const std::string k(key);
796   size_t index_start=k.find("[");
797   size_t index_end=k.find("]");
798   const string index_string=k.substr(index_start, index_end);
799   stringstream indexsstr;
800   indexsstr<<index_string;
801   indexsstr>>index;
802   const string freq_string=k.substr(index_end+1, string::npos);
803   stringstream freqsstr;
804   freqsstr<<freq_string;
805   freqsstr>>frequency;
806   return 1;
807 }
808
809 vtkMultiBlockDataSet* vtkMedUtilities::GetParent(vtkMultiBlockDataSet* root,
810                                 vtkStringArray* path)
811 {
812     vtkMultiBlockDataSet* output=root;
813     vtkMultiBlockDataSet* parent=output;
814     for(int depth = 0; depth<path->GetNumberOfValues(); depth++)
815       {
816       vtkStdString parentName = path->GetValue(depth);
817       bool found=false;
818       for(int blockId=0; blockId<parent->GetNumberOfBlocks(); blockId++)
819         {
820         vtkInformation* metaData=parent->GetMetaData(blockId);
821         if(metaData->Has(vtkCompositeDataSet::NAME()))
822           {
823           const char* blockName=metaData->Get(vtkCompositeDataSet::NAME());
824           if(parentName==blockName &&
825               vtkMultiBlockDataSet::SafeDownCast(
826                   parent->GetBlock(blockId))!=NULL)
827             {
828             parent=vtkMultiBlockDataSet::SafeDownCast(parent->GetBlock(blockId));
829             found=true;
830             break;
831             }
832           }
833         }
834       if (!found)
835         {
836         // If I am here, it means that I did not find any block with the good name, create one
837         int nb=parent->GetNumberOfBlocks();
838         vtkMultiBlockDataSet* block=vtkMultiBlockDataSet::New();
839         parent->SetBlock(nb, block);
840         block->Delete();
841         parent->GetMetaData(nb)->Set(vtkCompositeDataSet::NAME(),
842             parentName.c_str());
843         parent=block;
844         }
845       }
846     return parent;
847 }
848
849 int vtkMedUtilities::SizeOf(med_attribute_type type)
850 {
851   switch(type)
852     {
853     case MED_ATT_FLOAT64 : return sizeof(med_float);
854     case MED_ATT_INT : return sizeof(med_int);
855     case MED_ATT_NAME : return MED_NAME_SIZE * sizeof(char);
856     }
857   return 0;
858 }
859
860 bool operator==(const vtkMedComputeStep& cs0, const vtkMedComputeStep& cs1)
861 {
862   return cs0.IterationIt == cs1.IterationIt && cs0.TimeIt == cs1.TimeIt;
863 }
864
865 bool operator!=(const vtkMedComputeStep& cs0, const vtkMedComputeStep& cs1)
866 {
867   return cs0.IterationIt != cs1.IterationIt || cs0.TimeIt != cs1.TimeIt;
868 }
869
870 bool operator<(const vtkMedComputeStep& cs0, const vtkMedComputeStep& cs1)
871 {
872   if(cs0.IterationIt != cs1.IterationIt)
873     return cs0.IterationIt < cs1.IterationIt;
874   return cs0.TimeIt < cs1.TimeIt;
875 }
876
877 bool operator==(const vtkMedEntity& e0, const vtkMedEntity& e1)
878 {
879   return e0.EntityType == e1.EntityType && e0.GeometryType == e1.GeometryType;
880 }
881
882 bool operator!=(const vtkMedEntity& e0, const vtkMedEntity& e1)
883 {
884   return e0.EntityType != e1.EntityType || e0.GeometryType != e1.GeometryType;
885 }
886
887 bool operator<(const vtkMedEntity& e0, const vtkMedEntity& e1)
888 {
889   if(e0.EntityType != e1.EntityType)
890     return e0.EntityType < e1.EntityType;
891   return e0.GeometryType < e1.GeometryType;
892 }