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