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