]> SALOME platform Git repositories - modules/smesh.git/blob - src/DriverMED/DriverMED_Family.cxx
Salome HOME
Remove CORBA dependency
[modules/smesh.git] / src / DriverMED / DriverMED_Family.cxx
1 //  SMESH DriverMED : tool to split groups on families
2 //
3 //  Copyright (C) 2003  CEA
4 // 
5 //  This library is free software; you can redistribute it and/or 
6 //  modify it under the terms of the GNU Lesser General Public 
7 //  License as published by the Free Software Foundation; either 
8 //  version 2.1 of the License. 
9 // 
10 //  This library is distributed in the hope that it will be useful, 
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
13 //  Lesser General Public License for more details. 
14 // 
15 //  You should have received a copy of the GNU Lesser General Public 
16 //  License along with this library; if not, write to the Free Software 
17 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
18 // 
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 //
21 //
22 //
23 //  File   : DriverMED_Family.cxx
24 //  Author : Julia DOROVSKIKH
25 //  Module : SMESH
26 //  $Header$
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(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   myType = theType; 
87 }
88
89 SMDSAbs_ElementType
90 DriverMED_Family
91 ::GetType()
92 {
93   return myType; 
94 }
95
96 bool
97 DriverMED_Family
98 ::MemberOf(std::string theGroupName) const
99
100   return myGroupNames.find(theGroupName) != myGroupNames.end(); 
101 }
102
103 const MED::TStringSet& 
104 DriverMED_Family
105 ::GetGroupNames () const 
106
107   return myGroupNames; 
108 }
109
110
111 int 
112 DriverMED_Family
113 ::GetGroupAttributVal() const 
114 {
115   return myGroupAttributVal;
116
117
118 void
119 DriverMED_Family
120 ::SetGroupAttributVal( int theValue) 
121 {
122   myGroupAttributVal = theValue;
123 }
124
125 bool
126 DriverMED_Family
127 ::IsEmpty () const 
128
129   return myElements.empty(); 
130 }
131
132 bool CompareColors( const Quantity_Color& theColor, const Quantity_Color& theRefColor )
133 {
134   float aTolerance = 0.01;
135   if( fabs( theColor.Red() - theRefColor.Red() ) < aTolerance &&
136       fabs( theColor.Green() - theRefColor.Green() ) < aTolerance &&
137       fabs( theColor.Blue() - theRefColor.Blue() ) < aTolerance )
138     return true;
139
140   return false;
141 }
142
143 //=============================================================================
144 /*!
145  *  Split each group from list <aGroups> on some parts (families)
146  *  on the basis of the elements membership in other groups from this list.
147  *  Resulting families have no common elements.
148  */
149 //=============================================================================
150 DriverMED_FamilyPtrList 
151 DriverMED_Family
152 ::MakeFamilies(const SMESHDS_SubMeshPtrMap& theSubMeshes,
153                const SMESHDS_GroupBasePtrList& theGroups,
154                const bool doGroupOfNodes,
155                const bool doGroupOfEdges,
156                const bool doGroupOfFaces,
157                const bool doGroupOfVolumes)
158 {
159   DriverMED_FamilyPtrList aFamilies;
160
161   string anAllNodesGroupName = "Group_Of_All_Nodes";
162   string anAllEdgesGroupName = "Group_Of_All_Edges";
163   string anAllFacesGroupName = "Group_Of_All_Faces";
164   string anAllVolumesGroupName = "Group_Of_All_Volumes";
165
166   // Reserve four ids for families of free elements
167   // (1 - nodes, -1 - edges, -2 - faces, -3 - volumes).
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   SMESHDS_SubMeshPtrMap::const_iterator aSMIter = theSubMeshes.begin();
174   for (; aSMIter != theSubMeshes.end(); aSMIter++)
175   {
176     const int anId = aSMIter->first;
177     SMESHDS_SubMesh* aSubMesh = aSMIter->second;
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;
216
217   int id = 0;
218   ColorMap aColorMap;
219   for (aGroupsIter = theGroups.begin(); aGroupsIter != theGroups.end(); aGroupsIter++)
220   {
221     Quantity_Color aColor = (*aGroupsIter)->GetColor();
222
223     bool isFound = false;
224     for (ColorMap::iterator aColorIter = aColorMap.begin(); aColorIter != aColorMap.end(); aColorIter++)
225     {
226       Quantity_Color aRefColor = aColorIter->second;
227       if( CompareColors( aColor, aRefColor ) )
228       {
229         isFound = true;
230         break;
231       }
232     }
233
234     if( !isFound )
235       aColorMap[ id++ ] = aColor;
236   }
237
238   for (aGroupsIter = theGroups.begin(); aGroupsIter != theGroups.end(); aGroupsIter++)
239   {
240     DriverMED_FamilyPtr aFam2 (new DriverMED_Family);
241     aFam2->Init(*aGroupsIter, aColorMap);
242
243     DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
244     while (aFamsIter != aFamilies.end())
245     {
246       DriverMED_FamilyPtr aFam1 = *aFamsIter;
247       DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
248       if (aFam1->myType == aFam2->myType)
249       {
250         DriverMED_FamilyPtr aCommon (new DriverMED_Family);
251         aFam1->Split(aFam2, aCommon);
252         if (!aCommon->IsEmpty())
253         {
254           aCommon->SetGroupAttributVal(0);
255           aFamilies.push_back(aCommon);
256         }
257         if (aFam1->IsEmpty())
258         {
259           aFamilies.erase(aCurrIter);
260         }
261         if (aFam2->IsEmpty()) 
262           break;
263       }
264     }
265     // The rest elements of group
266     if (!aFam2->IsEmpty())
267     {
268       aFamilies.push_back(aFam2);
269     }
270   }
271
272   DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
273   for (; aFamsIter != aFamilies.end(); aFamsIter++)
274   {
275     DriverMED_FamilyPtr aFam = *aFamsIter;
276     if (aFam->myType == SMDSAbs_Node) {
277       aFam->SetId(aNodeFamId++);
278       if (doGroupOfNodes) aFam->myGroupNames.insert(anAllNodesGroupName);
279     }
280     else {
281       aFam->SetId(aElemFamId--);
282       if (aFam->myType == SMDSAbs_Edge) {
283         if (doGroupOfEdges) aFam->myGroupNames.insert(anAllEdgesGroupName);
284       }
285       else if (aFam->myType == SMDSAbs_Face) {
286         if (doGroupOfFaces) aFam->myGroupNames.insert(anAllFacesGroupName);
287       }
288       else if (aFam->myType == SMDSAbs_Volume) {
289         if (doGroupOfVolumes) aFam->myGroupNames.insert(anAllVolumesGroupName);
290       }
291     }
292   }
293
294   // Create families for elements, not belonging to any group
295   if (doGroupOfNodes)
296   {
297     DriverMED_FamilyPtr aFreeNodesFam (new DriverMED_Family);
298     aFreeNodesFam->SetId(REST_NODES_FAMILY);
299     aFreeNodesFam->myType = SMDSAbs_Node;
300     aFreeNodesFam->myGroupNames.insert(anAllNodesGroupName);
301     aFamilies.push_back(aFreeNodesFam);
302   }
303
304   if (doGroupOfEdges)
305   {
306     DriverMED_FamilyPtr aFreeEdgesFam (new DriverMED_Family);
307     aFreeEdgesFam->SetId(REST_EDGES_FAMILY);
308     aFreeEdgesFam->myType = SMDSAbs_Edge;
309     aFreeEdgesFam->myGroupNames.insert(anAllEdgesGroupName);
310     aFamilies.push_back(aFreeEdgesFam);
311   }
312
313   if (doGroupOfFaces)
314   {
315     DriverMED_FamilyPtr aFreeFacesFam (new DriverMED_Family);
316     aFreeFacesFam->SetId(REST_FACES_FAMILY);
317     aFreeFacesFam->myType = SMDSAbs_Face;
318     aFreeFacesFam->myGroupNames.insert(anAllFacesGroupName);
319     aFamilies.push_back(aFreeFacesFam);
320   }
321
322   if (doGroupOfVolumes)
323   {
324     DriverMED_FamilyPtr aFreeVolumesFam (new DriverMED_Family);
325     aFreeVolumesFam->SetId(REST_VOLUMES_FAMILY);
326     aFreeVolumesFam->myType = SMDSAbs_Volume;
327     aFreeVolumesFam->myGroupNames.insert(anAllVolumesGroupName);
328     aFamilies.push_back(aFreeVolumesFam);
329   }
330
331   DriverMED_FamilyPtr aNullFam (new DriverMED_Family);
332   aNullFam->SetId(0);
333   aNullFam->myType = SMDSAbs_All;
334   aFamilies.push_back(aNullFam);
335
336   return aFamilies;
337 }
338
339 //=============================================================================
340 /*!
341  *  Create TFamilyInfo for this family
342  */
343 //=============================================================================
344 MED::PFamilyInfo 
345 DriverMED_Family::GetFamilyInfo(const MED::PWrapper& theWrapper, 
346                                 const MED::PMeshInfo& theMeshInfo) const
347 {
348   ostringstream aStr;
349   aStr << "FAM_" << myId;
350   set<string>::const_iterator aGrIter = myGroupNames.begin();
351   for(; aGrIter != myGroupNames.end(); aGrIter++){
352     aStr << "_" << *aGrIter;
353   }
354
355   MED::PFamilyInfo anInfo;
356   string aValue = aStr.str();
357   if(myId == 0 || myGroupAttributVal == 0){
358     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
359                                       aValue,
360                                       myId,
361                                       myGroupNames);
362   }else{
363     MED::TStringVector anAttrDescs (1, "");  // 1 attribute with empty description,
364     MED::TIntVector anAttrIds (1, myId);        // Id=0,
365     MED::TIntVector anAttrVals (1, myGroupAttributVal);
366     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
367                                       aValue,
368                                       myId,
369                                       myGroupNames,
370                                       anAttrDescs,
371                                       anAttrIds,
372                                       anAttrVals);
373   }
374
375 //  cout << endl;
376 //  cout << "Groups: ";
377 //  set<string>::iterator aGrIter = myGroupNames.begin();
378 //  for (; aGrIter != myGroupNames.end(); aGrIter++)
379 //  {
380 //    cout << " " << *aGrIter;
381 //  }
382 //  cout << endl;
383 //
384 //  cout << "Elements: ";
385 //  set<const SMDS_MeshElement *>::iterator anIter = myElements.begin();
386 //  for (; anIter != myElements.end(); anIter++)
387 //  {
388 //    cout << " " << (*anIter)->GetID();
389 //  }
390 //  cout << endl;
391
392   return anInfo;
393 }
394
395 //=============================================================================
396 /*!
397  *  Initialize the tool by SMESHDS_GroupBase
398  */
399 //=============================================================================
400 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup, const ColorMap& theColorMap)
401 {
402   // Elements
403   myElements.clear();
404   SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
405   while (elemIt->more())
406   {
407     myElements.insert(elemIt->next());
408   }
409
410   // Type
411   myType = theGroup->GetType();
412
413   // Groups list
414   myGroupNames.clear();
415   myGroupNames.insert(string(theGroup->GetStoreName()));
416
417   myGroupAttributVal = 0;
418   
419   ColorMap::const_iterator aColorIter = theColorMap.begin();
420   for (; aColorIter != theColorMap.end(); aColorIter++)
421   {
422     if( CompareColors( theGroup->GetColor(), aColorIter->second ) )
423     {
424       myGroupAttributVal = aColorIter->first;
425       break;
426     }
427   }
428 }
429
430 //=============================================================================
431 /*!
432  *  Split <theSubMesh> on some parts (families)
433  *  on the basis of the elements type.
434  */
435 //=============================================================================
436 DriverMED_FamilyPtrList 
437 DriverMED_Family
438 ::SplitByType (SMESHDS_SubMesh* theSubMesh,
439                const int        theId)
440 {
441   DriverMED_FamilyPtrList aFamilies;
442   DriverMED_FamilyPtr aNodesFamily   (new DriverMED_Family);
443   DriverMED_FamilyPtr anEdgesFamily  (new DriverMED_Family);
444   DriverMED_FamilyPtr aFacesFamily   (new DriverMED_Family);
445   DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
446
447   char submeshGrpName[ 30 ];
448   sprintf( submeshGrpName, "SubMesh %d", theId );
449
450   SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
451   while (aNodesIter->more())
452   {
453     const SMDS_MeshNode* aNode = aNodesIter->next();
454     aNodesFamily->AddElement(aNode);
455   }
456
457   SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
458   while (anElemsIter->more())
459   {
460     const SMDS_MeshElement* anElem = anElemsIter->next();
461     switch (anElem->GetType())
462     {
463     case SMDSAbs_Edge:
464       anEdgesFamily->AddElement(anElem);
465       break;
466     case SMDSAbs_Face:
467       aFacesFamily->AddElement(anElem);
468       break;
469     case SMDSAbs_Volume:
470       aVolumesFamily->AddElement(anElem);
471       break;
472     default:
473       break;
474     }
475   }
476
477   if (!aNodesFamily->IsEmpty()) {
478     aNodesFamily->SetType(SMDSAbs_Node);
479     aNodesFamily->AddGroupName(submeshGrpName);
480     aFamilies.push_back(aNodesFamily);
481   }
482   if (!anEdgesFamily->IsEmpty()) {
483     anEdgesFamily->SetType(SMDSAbs_Edge);
484     anEdgesFamily->AddGroupName(submeshGrpName);
485     aFamilies.push_back(anEdgesFamily);
486   }
487   if (!aFacesFamily->IsEmpty()) {
488     aFacesFamily->SetType(SMDSAbs_Face);
489     aFacesFamily->AddGroupName(submeshGrpName);
490     aFamilies.push_back(aFacesFamily);
491   }
492   if (!aVolumesFamily->IsEmpty()) {
493     aVolumesFamily->SetType(SMDSAbs_Volume);
494     aVolumesFamily->AddGroupName(submeshGrpName);
495     aFamilies.push_back(aVolumesFamily);
496   }
497
498   return aFamilies;
499 }
500
501 //=============================================================================
502 /*!
503  *  Remove from <myElements> elements, common with <by>,
504  *  Remove from <by> elements, common with <myElements>,
505  *  Create family <common> from common elements, with combined groups list.
506  */
507 //=============================================================================
508 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
509                               DriverMED_FamilyPtr common)
510 {
511   // Elements
512   ElementsSet::iterator anIter = by->myElements.begin();
513   while ( anIter != by->myElements.end())
514   {
515     if (myElements.find(*anIter) != myElements.end())
516     {
517       common->myElements.insert(*anIter);
518       myElements.erase(*anIter);
519       by->myElements.erase(anIter++);
520     }
521     else
522       anIter++;
523   }
524
525   if (!common->IsEmpty())
526   {
527     // Groups list
528     common->myGroupNames = myGroupNames;
529     MED::TStringSet::iterator aGrNamesIter = by->myGroupNames.begin();
530     for (; aGrNamesIter != by->myGroupNames.end(); aGrNamesIter++)
531     {
532       common->myGroupNames.insert(*aGrNamesIter);
533     }
534
535     // Type
536     common->myType = myType;
537   }
538 }