Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/smesh.git] / src / DriverMED / DriverMED_Family.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SMESH DriverMED : tool to split groups on families
23 //  File   : DriverMED_Family.cxx
24 //  Author : Julia DOROVSKIKH
25 //  Module : SMESH
26 //  $Header$
27 //
28 #include "DriverMED_Family.h"
29 #include "MED_Factory.hxx"
30
31 #include <sstream>      
32
33 using namespace std;
34
35 //=============================================================================
36 /*!
37  *  Default constructor
38  */
39 //=============================================================================
40 DriverMED_Family
41 ::DriverMED_Family():
42   myGroupAttributVal(0)
43 {}
44
45
46 //=============================================================================
47 const ElementsSet& 
48 DriverMED_Family
49 ::GetElements () const 
50
51   return myElements; 
52 }
53
54 int 
55 DriverMED_Family
56 ::GetId () const 
57
58   return myId; 
59 }
60
61 void 
62 DriverMED_Family
63 ::SetId (const int theId) 
64
65   myId = theId; 
66 }
67
68 void
69 DriverMED_Family
70 ::AddElement(const SMDS_MeshElement* theElement)
71 {
72   myElements.insert(theElement); 
73 }
74
75 void
76 DriverMED_Family
77 ::AddGroupName(std::string theGroupName)
78 {
79   myGroupNames.insert(theGroupName); 
80 }
81
82 void
83 DriverMED_Family
84 ::SetType(const SMDSAbs_ElementType theType) 
85
86   myType = theType; 
87 }
88
89 SMDSAbs_ElementType
90 DriverMED_Family
91 ::GetType()
92 {
93   return myType; 
94 }
95
96 bool
97 DriverMED_Family
98 ::MemberOf(std::string theGroupName) const
99
100   return myGroupNames.find(theGroupName) != myGroupNames.end(); 
101 }
102
103 const MED::TStringSet& 
104 DriverMED_Family
105 ::GetGroupNames () const 
106
107   return myGroupNames; 
108 }
109
110
111 int 
112 DriverMED_Family
113 ::GetGroupAttributVal() const 
114 {
115   return myGroupAttributVal;
116
117
118 void
119 DriverMED_Family
120 ::SetGroupAttributVal( int theValue) 
121 {
122   myGroupAttributVal = theValue;
123 }
124
125 bool
126 DriverMED_Family
127 ::IsEmpty () const 
128
129   return myElements.empty(); 
130 }
131
132 //=============================================================================
133 /*!
134  *  Split each group from list <aGroups> on some parts (families)
135  *  on the basis of the elements membership in other groups from this list.
136  *  Resulting families have no common elements.
137  */
138 //=============================================================================
139 DriverMED_FamilyPtrList 
140 DriverMED_Family
141 ::MakeFamilies(const SMESHDS_SubMeshPtrMap& theSubMeshes,
142                const SMESHDS_GroupBasePtrList& theGroups,
143                const bool doGroupOfNodes,
144                const bool doGroupOfEdges,
145                const bool doGroupOfFaces,
146                const bool doGroupOfVolumes)
147 {
148   DriverMED_FamilyPtrList aFamilies;
149
150   string anAllNodesGroupName = "Group_Of_All_Nodes";
151   string anAllEdgesGroupName = "Group_Of_All_Edges";
152   string anAllFacesGroupName = "Group_Of_All_Faces";
153   string anAllVolumesGroupName = "Group_Of_All_Volumes";
154
155   // Reserve four ids for families of free elements
156   // (1 - nodes, -1 - edges, -2 - faces, -3 - volumes).
157   // 'Free' means here not belonging to any group.
158   int aNodeFamId = FIRST_NODE_FAMILY;
159   int aElemFamId = FIRST_ELEM_FAMILY;
160
161   // Process sub-meshes
162   SMESHDS_SubMeshPtrMap::const_iterator aSMIter = theSubMeshes.begin();
163   for (; aSMIter != theSubMeshes.end(); aSMIter++)
164   {
165     const int anId = aSMIter->first;
166     SMESHDS_SubMesh* aSubMesh = aSMIter->second;
167     if ( aSubMesh->IsComplexSubmesh() )
168       continue; // submesh containing other submeshs
169     DriverMED_FamilyPtrList aSMFams = SplitByType(aSubMesh,anId);
170     DriverMED_FamilyPtrList::iterator aSMFamsIter = aSMFams.begin();
171     for (; aSMFamsIter != aSMFams.end(); aSMFamsIter++)
172     {
173       DriverMED_FamilyPtr aFam2 = (*aSMFamsIter);
174       DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
175       while (aFamsIter != aFamilies.end())
176       {
177         DriverMED_FamilyPtr aFam1 = *aFamsIter;
178         DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
179         if (aFam1->myType == aFam2->myType)
180         {
181           DriverMED_FamilyPtr aCommon (new DriverMED_Family);
182           aFam1->Split(aFam2, aCommon);
183           if (!aCommon->IsEmpty())
184           {
185             aFamilies.push_back(aCommon);
186           }
187           if (aFam1->IsEmpty())
188           {
189             aFamilies.erase(aCurrIter);
190           }
191           if (aFam2->IsEmpty()) 
192             break;
193         }
194       }
195       // The rest elements of family
196       if (!aFam2->IsEmpty())
197       {
198         aFamilies.push_back(aFam2);
199       }
200     }
201   }
202
203   // Process groups
204   SMESHDS_GroupBasePtrList::const_iterator aGroupsIter = theGroups.begin();
205   for (; aGroupsIter != theGroups.end(); aGroupsIter++)
206   {
207     DriverMED_FamilyPtr aFam2 (new DriverMED_Family);
208     aFam2->Init(*aGroupsIter);
209
210     DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
211     while (aFamsIter != aFamilies.end())
212     {
213       DriverMED_FamilyPtr aFam1 = *aFamsIter;
214       DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
215       if (aFam1->myType == aFam2->myType)
216       {
217         DriverMED_FamilyPtr aCommon (new DriverMED_Family);
218         aFam1->Split(aFam2, aCommon);
219         if (!aCommon->IsEmpty())
220         {
221           aCommon->SetGroupAttributVal(0);
222           aFamilies.push_back(aCommon);
223         }
224         if (aFam1->IsEmpty())
225         {
226           aFamilies.erase(aCurrIter);
227         }
228         if (aFam2->IsEmpty()) 
229           break;
230       }
231     }
232     // The rest elements of group
233     if (!aFam2->IsEmpty())
234     {
235       aFamilies.push_back(aFam2);
236     }
237   }
238
239   DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
240   for (; aFamsIter != aFamilies.end(); aFamsIter++)
241   {
242     DriverMED_FamilyPtr aFam = *aFamsIter;
243     if (aFam->myType == SMDSAbs_Node) {
244       aFam->SetId(aNodeFamId++);
245       if (doGroupOfNodes) aFam->myGroupNames.insert(anAllNodesGroupName);
246     }
247     else {
248       aFam->SetId(aElemFamId--);
249       if (aFam->myType == SMDSAbs_Edge) {
250         if (doGroupOfEdges) aFam->myGroupNames.insert(anAllEdgesGroupName);
251       }
252       else if (aFam->myType == SMDSAbs_Face) {
253         if (doGroupOfFaces) aFam->myGroupNames.insert(anAllFacesGroupName);
254       }
255       else if (aFam->myType == SMDSAbs_Volume) {
256         if (doGroupOfVolumes) aFam->myGroupNames.insert(anAllVolumesGroupName);
257       }
258     }
259   }
260
261   // Create families for elements, not belonging to any group
262   if (doGroupOfNodes)
263   {
264     DriverMED_FamilyPtr aFreeNodesFam (new DriverMED_Family);
265     aFreeNodesFam->SetId(REST_NODES_FAMILY);
266     aFreeNodesFam->myType = SMDSAbs_Node;
267     aFreeNodesFam->myGroupNames.insert(anAllNodesGroupName);
268     aFamilies.push_back(aFreeNodesFam);
269   }
270
271   if (doGroupOfEdges)
272   {
273     DriverMED_FamilyPtr aFreeEdgesFam (new DriverMED_Family);
274     aFreeEdgesFam->SetId(REST_EDGES_FAMILY);
275     aFreeEdgesFam->myType = SMDSAbs_Edge;
276     aFreeEdgesFam->myGroupNames.insert(anAllEdgesGroupName);
277     aFamilies.push_back(aFreeEdgesFam);
278   }
279
280   if (doGroupOfFaces)
281   {
282     DriverMED_FamilyPtr aFreeFacesFam (new DriverMED_Family);
283     aFreeFacesFam->SetId(REST_FACES_FAMILY);
284     aFreeFacesFam->myType = SMDSAbs_Face;
285     aFreeFacesFam->myGroupNames.insert(anAllFacesGroupName);
286     aFamilies.push_back(aFreeFacesFam);
287   }
288
289   if (doGroupOfVolumes)
290   {
291     DriverMED_FamilyPtr aFreeVolumesFam (new DriverMED_Family);
292     aFreeVolumesFam->SetId(REST_VOLUMES_FAMILY);
293     aFreeVolumesFam->myType = SMDSAbs_Volume;
294     aFreeVolumesFam->myGroupNames.insert(anAllVolumesGroupName);
295     aFamilies.push_back(aFreeVolumesFam);
296   }
297
298   DriverMED_FamilyPtr aNullFam (new DriverMED_Family);
299   aNullFam->SetId(0);
300   aNullFam->myType = SMDSAbs_All;
301   aFamilies.push_back(aNullFam);
302
303   return aFamilies;
304 }
305
306 //=============================================================================
307 /*!
308  *  Create TFamilyInfo for this family
309  */
310 //=============================================================================
311 MED::PFamilyInfo 
312 DriverMED_Family::GetFamilyInfo(const MED::PWrapper& theWrapper, 
313                                 const MED::PMeshInfo& theMeshInfo) const
314 {
315   ostringstream aStr;
316   aStr << "FAM_" << myId;
317   set<string>::const_iterator aGrIter = myGroupNames.begin();
318   for(; aGrIter != myGroupNames.end(); aGrIter++){
319     aStr << "_" << *aGrIter;
320   }
321   string aValue = aStr.str();
322   // PAL19785,0019867 - med forbids whitespace to be the last char in the name
323   int maxSize;
324   if ( theWrapper->GetVersion() == MED::eV2_1 )
325     maxSize = MED::GetNOMLength<MED::eV2_1>();
326   else
327     maxSize = MED::GetNOMLength<MED::eV2_2>();
328   int lastCharPos = min( maxSize, (int) aValue.size() ) - 1;
329   while ( isspace( aValue[ lastCharPos ] ))
330     aValue.resize( lastCharPos-- );
331
332   MED::PFamilyInfo anInfo;
333   if(myId == 0 || myGroupAttributVal == 0){
334     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
335                                       aValue,
336                                       myId,
337                                       myGroupNames);
338   }else{
339     MED::TStringVector anAttrDescs (1, "");  // 1 attribute with empty description,
340     MED::TIntVector anAttrIds (1, myId);        // Id=0,
341     MED::TIntVector anAttrVals (1, myGroupAttributVal);
342     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
343                                       aValue,
344                                       myId,
345                                       myGroupNames,
346                                       anAttrDescs,
347                                       anAttrIds,
348                                       anAttrVals);
349   }
350
351 //  cout << endl;
352 //  cout << "Groups: ";
353 //  set<string>::iterator aGrIter = myGroupNames.begin();
354 //  for (; aGrIter != myGroupNames.end(); aGrIter++)
355 //  {
356 //    cout << " " << *aGrIter;
357 //  }
358 //  cout << endl;
359 //
360 //  cout << "Elements: ";
361 //  set<const SMDS_MeshElement *>::iterator anIter = myElements.begin();
362 //  for (; anIter != myElements.end(); anIter++)
363 //  {
364 //    cout << " " << (*anIter)->GetID();
365 //  }
366 //  cout << endl;
367
368   return anInfo;
369 }
370
371 //=============================================================================
372 /*!
373  *  Initialize the tool by SMESHDS_GroupBase
374  */
375 //=============================================================================
376 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup)
377 {
378   // Elements
379   myElements.clear();
380   SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
381   while (elemIt->more())
382   {
383     myElements.insert(elemIt->next());
384   }
385
386   // Type
387   myType = theGroup->GetType();
388
389   // Groups list
390   myGroupNames.clear();
391   myGroupNames.insert(string(theGroup->GetStoreName()));
392
393   Quantity_Color aColor = theGroup->GetColor();
394   double aRed = aColor.Red();
395   double aGreen = aColor.Green();
396   double aBlue = aColor.Blue();
397   int aR = int( aRed*255   );
398   int aG = int( aGreen*255 );
399   int aB = int( aBlue*255  );
400 //   cout << "aRed = " << aR << endl;
401 //   cout << "aGreen = " << aG << endl;
402 //   cout << "aBlue = " << aB << endl;
403   myGroupAttributVal = (int)(aR*1000000 + aG*1000 + aB);
404   //cout << "myGroupAttributVal = " << myGroupAttributVal << endl;
405 }
406
407 //=============================================================================
408 /*!
409  *  Split <theSubMesh> on some parts (families)
410  *  on the basis of the elements type.
411  */
412 //=============================================================================
413 DriverMED_FamilyPtrList 
414 DriverMED_Family
415 ::SplitByType (SMESHDS_SubMesh* theSubMesh,
416                const int        theId)
417 {
418   DriverMED_FamilyPtrList aFamilies;
419   DriverMED_FamilyPtr aNodesFamily   (new DriverMED_Family);
420   DriverMED_FamilyPtr anEdgesFamily  (new DriverMED_Family);
421   DriverMED_FamilyPtr aFacesFamily   (new DriverMED_Family);
422   DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
423
424   char submeshGrpName[ 30 ];
425   sprintf( submeshGrpName, "SubMesh %d", theId );
426
427   SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
428   while (aNodesIter->more())
429   {
430     const SMDS_MeshNode* aNode = aNodesIter->next();
431     aNodesFamily->AddElement(aNode);
432   }
433
434   SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
435   while (anElemsIter->more())
436   {
437     const SMDS_MeshElement* anElem = anElemsIter->next();
438     switch (anElem->GetType())
439     {
440     case SMDSAbs_Edge:
441       anEdgesFamily->AddElement(anElem);
442       break;
443     case SMDSAbs_Face:
444       aFacesFamily->AddElement(anElem);
445       break;
446     case SMDSAbs_Volume:
447       aVolumesFamily->AddElement(anElem);
448       break;
449     default:
450       break;
451     }
452   }
453
454   if (!aNodesFamily->IsEmpty()) {
455     aNodesFamily->SetType(SMDSAbs_Node);
456     aNodesFamily->AddGroupName(submeshGrpName);
457     aFamilies.push_back(aNodesFamily);
458   }
459   if (!anEdgesFamily->IsEmpty()) {
460     anEdgesFamily->SetType(SMDSAbs_Edge);
461     anEdgesFamily->AddGroupName(submeshGrpName);
462     aFamilies.push_back(anEdgesFamily);
463   }
464   if (!aFacesFamily->IsEmpty()) {
465     aFacesFamily->SetType(SMDSAbs_Face);
466     aFacesFamily->AddGroupName(submeshGrpName);
467     aFamilies.push_back(aFacesFamily);
468   }
469   if (!aVolumesFamily->IsEmpty()) {
470     aVolumesFamily->SetType(SMDSAbs_Volume);
471     aVolumesFamily->AddGroupName(submeshGrpName);
472     aFamilies.push_back(aVolumesFamily);
473   }
474
475   return aFamilies;
476 }
477
478 //=============================================================================
479 /*!
480  *  Remove from <myElements> elements, common with <by>,
481  *  Remove from <by> elements, common with <myElements>,
482  *  Create family <common> from common elements, with combined groups list.
483  */
484 //=============================================================================
485 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
486                               DriverMED_FamilyPtr common)
487 {
488   // Elements
489   ElementsSet::iterator anIter = by->myElements.begin();
490   while ( anIter != by->myElements.end())
491   {
492     if (myElements.find(*anIter) != myElements.end())
493     {
494       common->myElements.insert(*anIter);
495       myElements.erase(*anIter);
496       by->myElements.erase(anIter++);
497     }
498     else
499       anIter++;
500   }
501
502   if (!common->IsEmpty())
503   {
504     // Groups list
505     common->myGroupNames = myGroupNames;
506     MED::TStringSet::iterator aGrNamesIter = by->myGroupNames.begin();
507     for (; aGrNamesIter != by->myGroupNames.end(); aGrNamesIter++)
508     {
509       common->myGroupNames.insert(*aGrNamesIter);
510     }
511
512     // Type
513     common->myType = myType;
514   }
515 }