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