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