Salome HOME
bos #24228 [CEA 24217][Windows] cannot compile SMESH: additional fix.
[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 #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 ElemTypeSet&
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 = MED::GetNOMLength();
387   int lastCharPos = min( maxSize, (int) aValue.size() ) - 1;
388   while ( isspace( aValue[ lastCharPos ] ))
389     aValue.resize( lastCharPos-- );
390
391   MED::PFamilyInfo anInfo;
392   if(myId == 0 || myGroupAttributVal == 0){
393     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
394                                       aValue,
395                                       myId,
396                                       myGroupNames);
397   }else{
398     MED::TStringVector anAttrDescs (1, "");  // 1 attribute with empty description,
399     MED::TIntVector anAttrIds (1, myId);        // Id=0,
400     MED::TIntVector anAttrVals (1, myGroupAttributVal);
401     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
402                                       aValue,
403                                       myId,
404                                       myGroupNames,
405                                       anAttrDescs,
406                                       anAttrIds,
407                                       anAttrVals);
408   }
409
410 //  cout << endl;
411 //  cout << "Groups: ";
412 //  set<string>::iterator aGrIter = myGroupNames.begin();
413 //  for (; aGrIter != myGroupNames.end(); aGrIter++)
414 //  {
415 //    cout << " " << *aGrIter;
416 //  }
417 //  cout << endl;
418 //
419 //  cout << "Elements: ";
420 //  set<const SMDS_MeshElement *>::iterator anIter = myElements.begin();
421 //  for (; anIter != myElements.end(); anIter++)
422 //  {
423 //    cout << " " << (*anIter)->GetID();
424 //  }
425 //  cout << endl;
426
427   return anInfo;
428 }
429
430 //=============================================================================
431 /*!
432  *  Initialize the tool by SMESHDS_GroupBase
433  */
434 //=============================================================================
435 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup)
436 {
437   // Elements
438   myElements.clear();
439   SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
440   while (elemIt->more())
441   {
442     myElements.insert( myElements.end(), elemIt->next() );
443   }
444
445   // Type
446   myType = theGroup->GetType();
447
448   // Groups list
449   myGroupNames.clear();
450   myGroupNames.insert(string(theGroup->GetStoreName()));
451
452   Quantity_Color aColor = theGroup->GetColor();
453   double aRed   = aColor.Red();
454   double aGreen = aColor.Green();
455   double aBlue  = aColor.Blue();
456   int aR = int( aRed*255   );
457   int aG = int( aGreen*255 );
458   int aB = int( aBlue*255  );
459 //   cout << "aRed = " << aR << endl;
460 //   cout << "aGreen = " << aG << endl;
461 //   cout << "aBlue = " << aB << endl;
462   myGroupAttributVal = (int)(aR*1000000 + aG*1000 + aB);
463   //cout << "myGroupAttributVal = " << myGroupAttributVal << endl;
464 }
465
466 //=============================================================================
467 /*!
468  *  Split <theSubMesh> on some parts (families)
469  *  on the basis of the elements type.
470  */
471 //=============================================================================
472 DriverMED_FamilyPtrList 
473 DriverMED_Family::SplitByType (SMESHDS_SubMesh* theSubMesh,
474                                const int        theId)
475 {
476   DriverMED_FamilyPtrList aFamilies;
477   DriverMED_FamilyPtr aNodesFamily   (new DriverMED_Family);
478   DriverMED_FamilyPtr anEdgesFamily  (new DriverMED_Family);
479   DriverMED_FamilyPtr aFacesFamily   (new DriverMED_Family);
480   DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
481   // DriverMED_FamilyPtr a0DElemsFamily (new DriverMED_Family);
482   // DriverMED_FamilyPtr aBallsFamily   (new DriverMED_Family);
483
484   char submeshGrpName[ 30 ];
485   sprintf( submeshGrpName, "SubMesh %d", theId );
486
487   SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
488   while (aNodesIter->more())
489   {
490     const SMDS_MeshNode* aNode = aNodesIter->next();
491     aNodesFamily->AddElement(aNode);
492   }
493
494   SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
495   while (anElemsIter->more())
496   {
497     const SMDS_MeshElement* anElem = anElemsIter->next();
498     switch (anElem->GetType())
499     {
500     case SMDSAbs_Edge:
501       anEdgesFamily->AddElement(anElem);
502       break;
503     case SMDSAbs_Face:
504       aFacesFamily->AddElement(anElem);
505       break;
506     case SMDSAbs_Volume:
507       aVolumesFamily->AddElement(anElem);
508       break;
509     default:
510       break;
511     }
512   }
513
514   if (!aNodesFamily->IsEmpty()) {
515     aNodesFamily->SetType(SMDSAbs_Node);
516     aNodesFamily->AddGroupName(submeshGrpName);
517     aFamilies.push_back(aNodesFamily);
518   }
519   if (!anEdgesFamily->IsEmpty()) {
520     anEdgesFamily->SetType(SMDSAbs_Edge);
521     anEdgesFamily->AddGroupName(submeshGrpName);
522     aFamilies.push_back(anEdgesFamily);
523   }
524   if (!aFacesFamily->IsEmpty()) {
525     aFacesFamily->SetType(SMDSAbs_Face);
526     aFacesFamily->AddGroupName(submeshGrpName);
527     aFamilies.push_back(aFacesFamily);
528   }
529   if (!aVolumesFamily->IsEmpty()) {
530     aVolumesFamily->SetType(SMDSAbs_Volume);
531     aVolumesFamily->AddGroupName(submeshGrpName);
532     aFamilies.push_back(aVolumesFamily);
533   }
534
535   return aFamilies;
536 }
537
538 //=============================================================================
539 /*!
540  *  Remove from <myElements> elements, common with <by>,
541  *  Remove from <by> elements, common with <myElements>,
542  *  Create family <common> from common elements, with combined groups list.
543  */
544 //=============================================================================
545 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
546                               DriverMED_FamilyPtr common)
547 {
548   // Elements
549   ElementsSet::iterator anIter = by->myElements.begin(), elemInMe;
550   while ( anIter != by->myElements.end())
551   {
552     elemInMe = myElements.find(*anIter);
553     if (elemInMe != myElements.end())
554     {
555       common->myElements.insert(*anIter);
556       myElements.erase(elemInMe);
557       by->myElements.erase(anIter++);
558     }
559     else
560       anIter++;
561   }
562
563   if (!common->IsEmpty())
564   {
565     // Groups list
566     common->myGroupNames = myGroupNames;
567     common->myGroupNames.insert( by->myGroupNames.begin(), by->myGroupNames.end() );
568
569     // Type
570     common->myType = myType;
571   }
572 }
573
574 //================================================================================
575 /*!
576  * \brief Return a number of elements of a given type
577  */
578 //================================================================================
579
580 size_t DriverMED_Family::NbElements( SMDSAbs_ElementType theType ) const
581 {
582   if ( myTypes.size() < 2 )
583     return myElements.size();
584
585   int nb = 0;
586   for ( ElementsSet::iterator e = myElements.begin(); e != myElements.end(); ++e )
587     nb += ( theType == (*e)->GetType() );
588
589   return nb;
590 }