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