Salome HOME
f6d67ea597d72ee76eb19488b0b9f874c7c4bc52
[modules/smesh.git] / src / DriverMED / DriverMED_Family.cxx
1 // Copyright (C) 2007-2016  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, or (at your option) any later version.
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( myElements.end(), 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(SMESHDS_SubMeshIteratorPtr      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                const bool doAllInGroups)
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   while ( theSubMeshes->more() )
175   {
176     SMESHDS_SubMesh* aSubMesh = const_cast< SMESHDS_SubMesh* >( theSubMeshes->next() );
177     const int anId = aSubMesh->GetID();
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   if ( doAllInGroups )
339   {
340     if ( !doGroupOfEdges )
341     {
342       DriverMED_FamilyPtr aNigEdgeFam (new DriverMED_Family);
343       aNigEdgeFam->SetId( NIG_EDGES_FAMILY );
344       aNigEdgeFam->myType = SMDSAbs_Edge;
345       aNigEdgeFam->myGroupNames.insert( NIG_GROUP_PREFIX "_EDGES" );
346       aFamilies.push_back(aNigEdgeFam);
347     }
348     if ( !doGroupOfFaces )
349     {
350       DriverMED_FamilyPtr aNigFaceFam (new DriverMED_Family);
351       aNigFaceFam->SetId( NIG_FACES_FAMILY );
352       aNigFaceFam->myType = SMDSAbs_Face;
353       aNigFaceFam->myGroupNames.insert( NIG_GROUP_PREFIX "_FACES" );
354       aFamilies.push_back(aNigFaceFam);
355     }
356     if ( !doGroupOfVolumes )
357     {
358       DriverMED_FamilyPtr aNigVolFam (new DriverMED_Family);
359       aNigVolFam->SetId( NIG_VOLS_FAMILY );
360       aNigVolFam->myType = SMDSAbs_Volume;
361       aNigVolFam->myGroupNames.insert( NIG_GROUP_PREFIX "_VOLS" );
362       aFamilies.push_back(aNigVolFam);
363     }
364   }
365
366   return aFamilies;
367 }
368
369 //=============================================================================
370 /*!
371  *  Create TFamilyInfo for this family
372  */
373 //=============================================================================
374 MED::PFamilyInfo
375 DriverMED_Family::GetFamilyInfo(const MED::PWrapper& theWrapper, 
376                                 const MED::PMeshInfo& theMeshInfo) const
377 {
378   ostringstream aStr;
379   aStr << "FAM_" << myId;
380   set<string>::const_iterator aGrIter = myGroupNames.begin();
381   for(; aGrIter != myGroupNames.end(); aGrIter++){
382     aStr << "_" << *aGrIter;
383   }
384   string aValue = aStr.str();
385   // PAL19785,0019867 - med forbids whitespace to be the last char in the name
386   int maxSize;
387   //if ( theWrapper->GetVersion() == MED::eV2_1 )
388   //  maxSize = MED::GetNOMLength<MED::eV2_1>();
389   //else
390     maxSize = MED::GetNOMLength<MED::eV2_2>();
391   int lastCharPos = min( maxSize, (int) aValue.size() ) - 1;
392   while ( isspace( aValue[ lastCharPos ] ))
393     aValue.resize( lastCharPos-- );
394
395   MED::PFamilyInfo anInfo;
396   if(myId == 0 || myGroupAttributVal == 0){
397     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
398                                       aValue,
399                                       myId,
400                                       myGroupNames);
401   }else{
402     MED::TStringVector anAttrDescs (1, "");  // 1 attribute with empty description,
403     MED::TIntVector anAttrIds (1, myId);        // Id=0,
404     MED::TIntVector anAttrVals (1, myGroupAttributVal);
405     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
406                                       aValue,
407                                       myId,
408                                       myGroupNames,
409                                       anAttrDescs,
410                                       anAttrIds,
411                                       anAttrVals);
412   }
413
414 //  cout << endl;
415 //  cout << "Groups: ";
416 //  set<string>::iterator aGrIter = myGroupNames.begin();
417 //  for (; aGrIter != myGroupNames.end(); aGrIter++)
418 //  {
419 //    cout << " " << *aGrIter;
420 //  }
421 //  cout << endl;
422 //
423 //  cout << "Elements: ";
424 //  set<const SMDS_MeshElement *>::iterator anIter = myElements.begin();
425 //  for (; anIter != myElements.end(); anIter++)
426 //  {
427 //    cout << " " << (*anIter)->GetID();
428 //  }
429 //  cout << endl;
430
431   return anInfo;
432 }
433
434 //=============================================================================
435 /*!
436  *  Initialize the tool by SMESHDS_GroupBase
437  */
438 //=============================================================================
439 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup)
440 {
441   // Elements
442   myElements.clear();
443   SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
444   while (elemIt->more())
445   {
446     myElements.insert( myElements.end(), elemIt->next() );
447   }
448
449   // Type
450   myType = theGroup->GetType();
451
452   // Groups list
453   myGroupNames.clear();
454   myGroupNames.insert(string(theGroup->GetStoreName()));
455
456   Quantity_Color aColor = theGroup->GetColor();
457   double aRed   = aColor.Red();
458   double aGreen = aColor.Green();
459   double aBlue  = aColor.Blue();
460   int aR = int( aRed*255   );
461   int aG = int( aGreen*255 );
462   int aB = int( aBlue*255  );
463 //   cout << "aRed = " << aR << endl;
464 //   cout << "aGreen = " << aG << endl;
465 //   cout << "aBlue = " << aB << endl;
466   myGroupAttributVal = (int)(aR*1000000 + aG*1000 + aB);
467   //cout << "myGroupAttributVal = " << myGroupAttributVal << endl;
468 }
469
470 //=============================================================================
471 /*!
472  *  Split <theSubMesh> on some parts (families)
473  *  on the basis of the elements type.
474  */
475 //=============================================================================
476 DriverMED_FamilyPtrList 
477 DriverMED_Family::SplitByType (SMESHDS_SubMesh* theSubMesh,
478                                const int        theId)
479 {
480   DriverMED_FamilyPtrList aFamilies;
481   DriverMED_FamilyPtr aNodesFamily   (new DriverMED_Family);
482   DriverMED_FamilyPtr anEdgesFamily  (new DriverMED_Family);
483   DriverMED_FamilyPtr aFacesFamily   (new DriverMED_Family);
484   DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
485   // DriverMED_FamilyPtr a0DElemsFamily (new DriverMED_Family);
486   // DriverMED_FamilyPtr aBallsFamily   (new DriverMED_Family);
487
488   char submeshGrpName[ 30 ];
489   sprintf( submeshGrpName, "SubMesh %d", theId );
490
491   SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
492   while (aNodesIter->more())
493   {
494     const SMDS_MeshNode* aNode = aNodesIter->next();
495     aNodesFamily->AddElement(aNode);
496   }
497
498   SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
499   while (anElemsIter->more())
500   {
501     const SMDS_MeshElement* anElem = anElemsIter->next();
502     switch (anElem->GetType())
503     {
504     case SMDSAbs_Edge:
505       anEdgesFamily->AddElement(anElem);
506       break;
507     case SMDSAbs_Face:
508       aFacesFamily->AddElement(anElem);
509       break;
510     case SMDSAbs_Volume:
511       aVolumesFamily->AddElement(anElem);
512       break;
513     default:
514       break;
515     }
516   }
517
518   if (!aNodesFamily->IsEmpty()) {
519     aNodesFamily->SetType(SMDSAbs_Node);
520     aNodesFamily->AddGroupName(submeshGrpName);
521     aFamilies.push_back(aNodesFamily);
522   }
523   if (!anEdgesFamily->IsEmpty()) {
524     anEdgesFamily->SetType(SMDSAbs_Edge);
525     anEdgesFamily->AddGroupName(submeshGrpName);
526     aFamilies.push_back(anEdgesFamily);
527   }
528   if (!aFacesFamily->IsEmpty()) {
529     aFacesFamily->SetType(SMDSAbs_Face);
530     aFacesFamily->AddGroupName(submeshGrpName);
531     aFamilies.push_back(aFacesFamily);
532   }
533   if (!aVolumesFamily->IsEmpty()) {
534     aVolumesFamily->SetType(SMDSAbs_Volume);
535     aVolumesFamily->AddGroupName(submeshGrpName);
536     aFamilies.push_back(aVolumesFamily);
537   }
538
539   return aFamilies;
540 }
541
542 //=============================================================================
543 /*!
544  *  Remove from <myElements> elements, common with <by>,
545  *  Remove from <by> elements, common with <myElements>,
546  *  Create family <common> from common elements, with combined groups list.
547  */
548 //=============================================================================
549 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
550                               DriverMED_FamilyPtr common)
551 {
552   // Elements
553   ElementsSet::iterator anIter = by->myElements.begin(), elemInMe;
554   while ( anIter != by->myElements.end())
555   {
556     elemInMe = myElements.find(*anIter);
557     if (elemInMe != myElements.end())
558     {
559       common->myElements.insert(*anIter);
560       myElements.erase(elemInMe);
561       by->myElements.erase(anIter++);
562     }
563     else
564       anIter++;
565   }
566
567   if (!common->IsEmpty())
568   {
569     // Groups list
570     common->myGroupNames = myGroupNames;
571     common->myGroupNames.insert( by->myGroupNames.begin(), by->myGroupNames.end() );
572
573     // Type
574     common->myType = myType;
575   }
576 }