Salome HOME
Merge branch 'V9_7_BR'
[modules/smesh.git] / src / DriverMED / DriverMED_Family.cxx
1 // Copyright (C) 2007-2021  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
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( myElements.end(), 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 ElemTypeSet&
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(SMESHDS_SubMeshIteratorPtr      theSubMeshes,
148                const SMESHDS_GroupBasePtrList& theGroups,
149                const bool doGroupOfNodes,
150                const bool doGroupOfEdges,
151                const bool doGroupOfFaces,
152                const bool doGroupOfVolumes,
153                const bool doGroupOf0DElems,
154                const bool doGroupOfBalls,
155                const bool doAllInGroups)
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   while ( theSubMeshes->more() )
174   {
175     SMESHDS_SubMesh* aSubMesh = const_cast< SMESHDS_SubMesh* >( theSubMeshes->next() );
176     const int anId = aSubMesh->GetID();
177     if ( aSubMesh->IsComplexSubmesh() )
178       continue; // submesh containing other submeshs
179     DriverMED_FamilyPtrList aSMFams = SplitByType(aSubMesh,anId);
180     DriverMED_FamilyPtrList::iterator aSMFamsIter = aSMFams.begin();
181     for (; aSMFamsIter != aSMFams.end(); aSMFamsIter++)
182     {
183       DriverMED_FamilyPtr aFam2 = (*aSMFamsIter);
184       DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
185       while (aFamsIter != aFamilies.end())
186       {
187         DriverMED_FamilyPtr aFam1 = *aFamsIter;
188         DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
189         if (aFam1->myType == aFam2->myType)
190         {
191           DriverMED_FamilyPtr aCommon (new DriverMED_Family);
192           aFam1->Split(aFam2, aCommon);
193           if (!aCommon->IsEmpty())
194           {
195             aFamilies.push_back(aCommon);
196           }
197           if (aFam1->IsEmpty())
198           {
199             aFamilies.erase(aCurrIter);
200           }
201           if (aFam2->IsEmpty()) 
202             break;
203         }
204       }
205       // The rest elements of family
206       if (!aFam2->IsEmpty())
207       {
208         aFamilies.push_back(aFam2);
209       }
210     }
211   }
212
213   // Process groups
214   SMESHDS_GroupBasePtrList::const_iterator aGroupsIter = theGroups.begin();
215   for (; aGroupsIter != theGroups.end(); aGroupsIter++)
216   {
217     DriverMED_FamilyPtr aFam2 (new DriverMED_Family);
218     aFam2->Init(*aGroupsIter);
219
220     DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
221     while (aFamsIter != aFamilies.end())
222     {
223       DriverMED_FamilyPtr aFam1 = *aFamsIter;
224       DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
225       if (aFam1->myType == aFam2->myType)
226       {
227         DriverMED_FamilyPtr aCommon (new DriverMED_Family);
228         aFam1->Split(aFam2, aCommon);
229         if (!aCommon->IsEmpty())
230         {
231           aCommon->SetGroupAttributVal(0);
232           aFamilies.push_back(aCommon);
233         }
234         if (aFam1->IsEmpty())
235         {
236           aFamilies.erase(aCurrIter);
237         }
238         if (aFam2->IsEmpty()) 
239           break;
240       }
241     }
242     // The rest elements of group
243     if (!aFam2->IsEmpty())
244     {
245       aFamilies.push_back(aFam2);
246     }
247   }
248
249   DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
250   for (; aFamsIter != aFamilies.end(); aFamsIter++)
251   {
252     DriverMED_FamilyPtr aFam = *aFamsIter;
253     if (aFam->myType == SMDSAbs_Node) {
254       aFam->SetId(aNodeFamId++);
255       if (doGroupOfNodes) aFam->myGroupNames.insert(anAllNodesGroupName);
256     }
257     else {
258       aFam->SetId(aElemFamId--);
259       if (aFam->myType == SMDSAbs_Edge) {
260         if (doGroupOfEdges) aFam->myGroupNames.insert(anAllEdgesGroupName);
261       }
262       else if (aFam->myType == SMDSAbs_Face) {
263         if (doGroupOfFaces) aFam->myGroupNames.insert(anAllFacesGroupName);
264       }
265       else if (aFam->myType == SMDSAbs_Volume) {
266         if (doGroupOfVolumes) aFam->myGroupNames.insert(anAllVolumesGroupName);
267       }
268       else if (aFam->myType == SMDSAbs_0DElement) {
269         if (doGroupOfVolumes) aFam->myGroupNames.insert(anAll0DElemsGroupName);
270       }
271       else if (aFam->myType == SMDSAbs_Ball) {
272         if (doGroupOfVolumes) aFam->myGroupNames.insert(anAllBallsGroupName);
273       }
274     }
275   }
276
277   // Create families for elements, not belonging to any group
278   if (doGroupOfNodes)
279   {
280     DriverMED_FamilyPtr aFreeNodesFam (new DriverMED_Family);
281     aFreeNodesFam->SetId(REST_NODES_FAMILY);
282     aFreeNodesFam->myType = SMDSAbs_Node;
283     aFreeNodesFam->myGroupNames.insert(anAllNodesGroupName);
284     aFamilies.push_back(aFreeNodesFam);
285   }
286
287   if (doGroupOfEdges)
288   {
289     DriverMED_FamilyPtr aFreeEdgesFam (new DriverMED_Family);
290     aFreeEdgesFam->SetId(REST_EDGES_FAMILY);
291     aFreeEdgesFam->myType = SMDSAbs_Edge;
292     aFreeEdgesFam->myGroupNames.insert(anAllEdgesGroupName);
293     aFamilies.push_back(aFreeEdgesFam);
294   }
295
296   if (doGroupOfFaces)
297   {
298     DriverMED_FamilyPtr aFreeFacesFam (new DriverMED_Family);
299     aFreeFacesFam->SetId(REST_FACES_FAMILY);
300     aFreeFacesFam->myType = SMDSAbs_Face;
301     aFreeFacesFam->myGroupNames.insert(anAllFacesGroupName);
302     aFamilies.push_back(aFreeFacesFam);
303   }
304
305   if (doGroupOfVolumes)
306   {
307     DriverMED_FamilyPtr aFreeVolumesFam (new DriverMED_Family);
308     aFreeVolumesFam->SetId(REST_VOLUMES_FAMILY);
309     aFreeVolumesFam->myType = SMDSAbs_Volume;
310     aFreeVolumesFam->myGroupNames.insert(anAllVolumesGroupName);
311     aFamilies.push_back(aFreeVolumesFam);
312   }
313
314   if (doGroupOf0DElems)
315   {
316     DriverMED_FamilyPtr aFree0DFam (new DriverMED_Family);
317     aFree0DFam->SetId(REST_0DELEM_FAMILY);
318     aFree0DFam->myType = SMDSAbs_0DElement;
319     aFree0DFam->myGroupNames.insert(anAll0DElemsGroupName);
320     aFamilies.push_back(aFree0DFam);
321   }
322
323   if (doGroupOfBalls)
324   {
325     DriverMED_FamilyPtr aFreeBallsFam (new DriverMED_Family);
326     aFreeBallsFam->SetId(REST_BALL_FAMILY);
327     aFreeBallsFam->myType = SMDSAbs_Ball;
328     aFreeBallsFam->myGroupNames.insert(anAllBallsGroupName);
329     aFamilies.push_back(aFreeBallsFam);
330   }
331
332   DriverMED_FamilyPtr aNullFam (new DriverMED_Family);
333   aNullFam->SetId( 0 );
334   aNullFam->myType = SMDSAbs_All;
335   aFamilies.push_back(aNullFam);
336
337   if ( doAllInGroups )
338   {
339     if ( !doGroupOfEdges )
340     {
341       DriverMED_FamilyPtr aNigEdgeFam (new DriverMED_Family);
342       aNigEdgeFam->SetId( NIG_EDGES_FAMILY );
343       aNigEdgeFam->myType = SMDSAbs_Edge;
344       aNigEdgeFam->myGroupNames.insert( NIG_GROUP_PREFIX "_EDGES" );
345       aFamilies.push_back(aNigEdgeFam);
346     }
347     if ( !doGroupOfFaces )
348     {
349       DriverMED_FamilyPtr aNigFaceFam (new DriverMED_Family);
350       aNigFaceFam->SetId( NIG_FACES_FAMILY );
351       aNigFaceFam->myType = SMDSAbs_Face;
352       aNigFaceFam->myGroupNames.insert( NIG_GROUP_PREFIX "_FACES" );
353       aFamilies.push_back(aNigFaceFam);
354     }
355     if ( !doGroupOfVolumes )
356     {
357       DriverMED_FamilyPtr aNigVolFam (new DriverMED_Family);
358       aNigVolFam->SetId( NIG_VOLS_FAMILY );
359       aNigVolFam->myType = SMDSAbs_Volume;
360       aNigVolFam->myGroupNames.insert( NIG_GROUP_PREFIX "_VOLS" );
361       aFamilies.push_back(aNigVolFam);
362     }
363   }
364
365   return aFamilies;
366 }
367
368 //=============================================================================
369 /*!
370  *  Initialize the tool by SMESHDS_GroupBase
371  */
372 //=============================================================================
373 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup)
374 {
375   // Elements
376   myElements.clear();
377   SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
378   while (elemIt->more())
379   {
380     myElements.insert( myElements.end(), elemIt->next() );
381   }
382
383   // Type
384   myType = theGroup->GetType();
385
386   // Groups list
387   myGroupNames.clear();
388   myGroupNames.insert(string(theGroup->GetStoreName()));
389
390   Quantity_Color aColor = theGroup->GetColor();
391   double aRed   = aColor.Red();
392   double aGreen = aColor.Green();
393   double aBlue  = aColor.Blue();
394   int aR = int( aRed*255   );
395   int aG = int( aGreen*255 );
396   int aB = int( aBlue*255  );
397 //   cout << "aRed = " << aR << endl;
398 //   cout << "aGreen = " << aG << endl;
399 //   cout << "aBlue = " << aB << endl;
400   myGroupAttributVal = (int)(aR*1000000 + aG*1000 + aB);
401   //cout << "myGroupAttributVal = " << myGroupAttributVal << endl;
402 }
403
404 //=============================================================================
405 /*!
406  *  Split <theSubMesh> on some parts (families)
407  *  on the basis of the elements type.
408  */
409 //=============================================================================
410 DriverMED_FamilyPtrList 
411 DriverMED_Family::SplitByType (SMESHDS_SubMesh* theSubMesh,
412                                const int        theId)
413 {
414   DriverMED_FamilyPtrList aFamilies;
415   DriverMED_FamilyPtr aNodesFamily   (new DriverMED_Family);
416   DriverMED_FamilyPtr anEdgesFamily  (new DriverMED_Family);
417   DriverMED_FamilyPtr aFacesFamily   (new DriverMED_Family);
418   DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
419   // DriverMED_FamilyPtr a0DElemsFamily (new DriverMED_Family);
420   // DriverMED_FamilyPtr aBallsFamily   (new DriverMED_Family);
421
422   char submeshGrpName[ 30 ];
423   sprintf( submeshGrpName, "SubMesh %d", theId );
424
425   SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
426   while (aNodesIter->more())
427   {
428     const SMDS_MeshNode* aNode = aNodesIter->next();
429     aNodesFamily->AddElement(aNode);
430   }
431
432   SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
433   while (anElemsIter->more())
434   {
435     const SMDS_MeshElement* anElem = anElemsIter->next();
436     switch (anElem->GetType())
437     {
438     case SMDSAbs_Edge:
439       anEdgesFamily->AddElement(anElem);
440       break;
441     case SMDSAbs_Face:
442       aFacesFamily->AddElement(anElem);
443       break;
444     case SMDSAbs_Volume:
445       aVolumesFamily->AddElement(anElem);
446       break;
447     default:
448       break;
449     }
450   }
451
452   if (!aNodesFamily->IsEmpty()) {
453     aNodesFamily->SetType(SMDSAbs_Node);
454     aNodesFamily->AddGroupName(submeshGrpName);
455     aFamilies.push_back(aNodesFamily);
456   }
457   if (!anEdgesFamily->IsEmpty()) {
458     anEdgesFamily->SetType(SMDSAbs_Edge);
459     anEdgesFamily->AddGroupName(submeshGrpName);
460     aFamilies.push_back(anEdgesFamily);
461   }
462   if (!aFacesFamily->IsEmpty()) {
463     aFacesFamily->SetType(SMDSAbs_Face);
464     aFacesFamily->AddGroupName(submeshGrpName);
465     aFamilies.push_back(aFacesFamily);
466   }
467   if (!aVolumesFamily->IsEmpty()) {
468     aVolumesFamily->SetType(SMDSAbs_Volume);
469     aVolumesFamily->AddGroupName(submeshGrpName);
470     aFamilies.push_back(aVolumesFamily);
471   }
472
473   return aFamilies;
474 }
475
476 //=============================================================================
477 /*!
478  *  Remove from <myElements> elements, common with <by>,
479  *  Remove from <by> elements, common with <myElements>,
480  *  Create family <common> from common elements, with combined groups list.
481  */
482 //=============================================================================
483 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
484                               DriverMED_FamilyPtr common)
485 {
486   // Elements
487   ElementsSet::iterator anIter = by->myElements.begin(), elemInMe;
488   while ( anIter != by->myElements.end())
489   {
490     elemInMe = myElements.find(*anIter);
491     if (elemInMe != myElements.end())
492     {
493       common->myElements.insert(*anIter);
494       myElements.erase(elemInMe);
495       by->myElements.erase(anIter++);
496     }
497     else
498       anIter++;
499   }
500
501   if (!common->IsEmpty())
502   {
503     // Groups list
504     common->myGroupNames = myGroupNames;
505     common->myGroupNames.insert( by->myGroupNames.begin(), by->myGroupNames.end() );
506
507     // Type
508     common->myType = myType;
509   }
510 }
511
512 //================================================================================
513 /*!
514  * \brief Return a number of elements of a given type
515  */
516 //================================================================================
517
518 size_t DriverMED_Family::NbElements( SMDSAbs_ElementType theType ) const
519 {
520   if ( myTypes.size() < 2 )
521     return myElements.size();
522
523   int nb = 0;
524   for ( ElementsSet::iterator e = myElements.begin(); e != myElements.end(); ++e )
525     nb += ( theType == (*e)->GetType() );
526
527   return nb;
528 }