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