Salome HOME
Color Number (Color Group) parameter is returned for compatibility
[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 SALOMEDS::Color& theColor, const SALOMEDS::Color& theRefColor )
133 {
134   if( fabs( theColor.R - theRefColor.R ) < 0.01 &&
135       fabs( theColor.G - theRefColor.G ) < 0.01 &&
136       fabs( theColor.B - theRefColor.B ) < 0.01 )
137     return true;
138
139   return false;
140 }
141
142 //=============================================================================
143 /*!
144  *  Split each group from list <aGroups> on some parts (families)
145  *  on the basis of the elements membership in other groups from this list.
146  *  Resulting families have no common elements.
147  */
148 //=============================================================================
149 DriverMED_FamilyPtrList 
150 DriverMED_Family
151 ::MakeFamilies(const SMESHDS_SubMeshPtrMap& theSubMeshes,
152                const SMESHDS_GroupBasePtrList& theGroups,
153                const bool doGroupOfNodes,
154                const bool doGroupOfEdges,
155                const bool doGroupOfFaces,
156                const bool doGroupOfVolumes)
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
165   // Reserve four ids for families of free elements
166   // (1 - nodes, -1 - edges, -2 - faces, -3 - volumes).
167   // 'Free' means here not belonging to any group.
168   int aNodeFamId = FIRST_NODE_FAMILY;
169   int aElemFamId = FIRST_ELEM_FAMILY;
170
171   // Process sub-meshes
172   SMESHDS_SubMeshPtrMap::const_iterator aSMIter = theSubMeshes.begin();
173   for (; aSMIter != theSubMeshes.end(); aSMIter++)
174   {
175     const int anId = aSMIter->first;
176     SMESHDS_SubMesh* aSubMesh = aSMIter->second;
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;
215
216   int id = 0;
217   ColorMap aColorMap;
218   for (aGroupsIter = theGroups.begin(); aGroupsIter != theGroups.end(); aGroupsIter++)
219   {
220     Quantity_Color aQColor = (*aGroupsIter)->GetColor();
221     SALOMEDS::Color aColor;
222     aColor.R = aQColor.Red();
223     aColor.G = aQColor.Green();
224     aColor.B = aQColor.Blue();
225
226     bool isFound = false;
227     for (ColorMap::iterator aColorIter = aColorMap.begin(); aColorIter != aColorMap.end(); aColorIter++)
228     {
229       SALOMEDS::Color aRefColor = aColorIter->second;
230       if( CompareColors( aColor, aRefColor ) )
231       {
232         isFound = true;
233         break;
234       }
235     }
236
237     if( !isFound )
238       aColorMap[ id++ ] = aColor;
239   }
240
241   for (aGroupsIter = theGroups.begin(); aGroupsIter != theGroups.end(); aGroupsIter++)
242   {
243     DriverMED_FamilyPtr aFam2 (new DriverMED_Family);
244     aFam2->Init(*aGroupsIter, aColorMap);
245
246     DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
247     while (aFamsIter != aFamilies.end())
248     {
249       DriverMED_FamilyPtr aFam1 = *aFamsIter;
250       DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
251       if (aFam1->myType == aFam2->myType)
252       {
253         DriverMED_FamilyPtr aCommon (new DriverMED_Family);
254         aFam1->Split(aFam2, aCommon);
255         if (!aCommon->IsEmpty())
256         {
257           aCommon->SetGroupAttributVal(0);
258           aFamilies.push_back(aCommon);
259         }
260         if (aFam1->IsEmpty())
261         {
262           aFamilies.erase(aCurrIter);
263         }
264         if (aFam2->IsEmpty()) 
265           break;
266       }
267     }
268     // The rest elements of group
269     if (!aFam2->IsEmpty())
270     {
271       aFamilies.push_back(aFam2);
272     }
273   }
274
275   DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
276   for (; aFamsIter != aFamilies.end(); aFamsIter++)
277   {
278     DriverMED_FamilyPtr aFam = *aFamsIter;
279     if (aFam->myType == SMDSAbs_Node) {
280       aFam->SetId(aNodeFamId++);
281       if (doGroupOfNodes) aFam->myGroupNames.insert(anAllNodesGroupName);
282     }
283     else {
284       aFam->SetId(aElemFamId--);
285       if (aFam->myType == SMDSAbs_Edge) {
286         if (doGroupOfEdges) aFam->myGroupNames.insert(anAllEdgesGroupName);
287       }
288       else if (aFam->myType == SMDSAbs_Face) {
289         if (doGroupOfFaces) aFam->myGroupNames.insert(anAllFacesGroupName);
290       }
291       else if (aFam->myType == SMDSAbs_Volume) {
292         if (doGroupOfVolumes) aFam->myGroupNames.insert(anAllVolumesGroupName);
293       }
294     }
295   }
296
297   // Create families for elements, not belonging to any group
298   if (doGroupOfNodes)
299   {
300     DriverMED_FamilyPtr aFreeNodesFam (new DriverMED_Family);
301     aFreeNodesFam->SetId(REST_NODES_FAMILY);
302     aFreeNodesFam->myType = SMDSAbs_Node;
303     aFreeNodesFam->myGroupNames.insert(anAllNodesGroupName);
304     aFamilies.push_back(aFreeNodesFam);
305   }
306
307   if (doGroupOfEdges)
308   {
309     DriverMED_FamilyPtr aFreeEdgesFam (new DriverMED_Family);
310     aFreeEdgesFam->SetId(REST_EDGES_FAMILY);
311     aFreeEdgesFam->myType = SMDSAbs_Edge;
312     aFreeEdgesFam->myGroupNames.insert(anAllEdgesGroupName);
313     aFamilies.push_back(aFreeEdgesFam);
314   }
315
316   if (doGroupOfFaces)
317   {
318     DriverMED_FamilyPtr aFreeFacesFam (new DriverMED_Family);
319     aFreeFacesFam->SetId(REST_FACES_FAMILY);
320     aFreeFacesFam->myType = SMDSAbs_Face;
321     aFreeFacesFam->myGroupNames.insert(anAllFacesGroupName);
322     aFamilies.push_back(aFreeFacesFam);
323   }
324
325   if (doGroupOfVolumes)
326   {
327     DriverMED_FamilyPtr aFreeVolumesFam (new DriverMED_Family);
328     aFreeVolumesFam->SetId(REST_VOLUMES_FAMILY);
329     aFreeVolumesFam->myType = SMDSAbs_Volume;
330     aFreeVolumesFam->myGroupNames.insert(anAllVolumesGroupName);
331     aFamilies.push_back(aFreeVolumesFam);
332   }
333
334   DriverMED_FamilyPtr aNullFam (new DriverMED_Family);
335   aNullFam->SetId(0);
336   aNullFam->myType = SMDSAbs_All;
337   aFamilies.push_back(aNullFam);
338
339   return aFamilies;
340 }
341
342 //=============================================================================
343 /*!
344  *  Create TFamilyInfo for this family
345  */
346 //=============================================================================
347 MED::PFamilyInfo 
348 DriverMED_Family::GetFamilyInfo(const MED::PWrapper& theWrapper, 
349                                 const MED::PMeshInfo& theMeshInfo) const
350 {
351   ostringstream aStr;
352   aStr << "FAM_" << myId;
353   set<string>::const_iterator aGrIter = myGroupNames.begin();
354   for(; aGrIter != myGroupNames.end(); aGrIter++){
355     aStr << "_" << *aGrIter;
356   }
357
358   MED::PFamilyInfo anInfo;
359   string aValue = aStr.str();
360   if(myId == 0 || myGroupAttributVal == 0){
361     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
362                                       aValue,
363                                       myId,
364                                       myGroupNames);
365   }else{
366     MED::TStringVector anAttrDescs (1, "");  // 1 attribute with empty description,
367     MED::TIntVector anAttrIds (1, myId);        // Id=0,
368     MED::TIntVector anAttrVals (1, myGroupAttributVal);
369     anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
370                                       aValue,
371                                       myId,
372                                       myGroupNames,
373                                       anAttrDescs,
374                                       anAttrIds,
375                                       anAttrVals);
376   }
377
378 //  cout << endl;
379 //  cout << "Groups: ";
380 //  set<string>::iterator aGrIter = myGroupNames.begin();
381 //  for (; aGrIter != myGroupNames.end(); aGrIter++)
382 //  {
383 //    cout << " " << *aGrIter;
384 //  }
385 //  cout << endl;
386 //
387 //  cout << "Elements: ";
388 //  set<const SMDS_MeshElement *>::iterator anIter = myElements.begin();
389 //  for (; anIter != myElements.end(); anIter++)
390 //  {
391 //    cout << " " << (*anIter)->GetID();
392 //  }
393 //  cout << endl;
394
395   return anInfo;
396 }
397
398 //=============================================================================
399 /*!
400  *  Initialize the tool by SMESHDS_GroupBase
401  */
402 //=============================================================================
403 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup, const ColorMap& theColorMap)
404 {
405   // Elements
406   myElements.clear();
407   SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
408   while (elemIt->more())
409   {
410     myElements.insert(elemIt->next());
411   }
412
413   // Type
414   myType = theGroup->GetType();
415
416   // Groups list
417   myGroupNames.clear();
418   myGroupNames.insert(string(theGroup->GetStoreName()));
419
420   myGroupAttributVal = 0;
421   
422   ColorMap::const_iterator aColorIter = theColorMap.begin();
423   for (; aColorIter != theColorMap.end(); aColorIter++)
424   {
425     Quantity_Color aGroupQColor = theGroup->GetColor();
426     SALOMEDS::Color aGroupColor;
427     aGroupColor.R = aGroupQColor.Red();
428     aGroupColor.G = aGroupQColor.Green();
429     aGroupColor.B = aGroupQColor.Blue();
430
431     SALOMEDS::Color aColor = aColorIter->second;
432     if( CompareColors( aGroupColor, aColor ) )
433     {
434       myGroupAttributVal = aColorIter->first;
435       break;
436     }
437   }
438 }
439
440 //=============================================================================
441 /*!
442  *  Split <theSubMesh> on some parts (families)
443  *  on the basis of the elements type.
444  */
445 //=============================================================================
446 DriverMED_FamilyPtrList 
447 DriverMED_Family
448 ::SplitByType (SMESHDS_SubMesh* theSubMesh,
449                const int        theId)
450 {
451   DriverMED_FamilyPtrList aFamilies;
452   DriverMED_FamilyPtr aNodesFamily   (new DriverMED_Family);
453   DriverMED_FamilyPtr anEdgesFamily  (new DriverMED_Family);
454   DriverMED_FamilyPtr aFacesFamily   (new DriverMED_Family);
455   DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
456
457   char submeshGrpName[ 30 ];
458   sprintf( submeshGrpName, "SubMesh %d", theId );
459
460   SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
461   while (aNodesIter->more())
462   {
463     const SMDS_MeshNode* aNode = aNodesIter->next();
464     aNodesFamily->AddElement(aNode);
465   }
466
467   SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
468   while (anElemsIter->more())
469   {
470     const SMDS_MeshElement* anElem = anElemsIter->next();
471     switch (anElem->GetType())
472     {
473     case SMDSAbs_Edge:
474       anEdgesFamily->AddElement(anElem);
475       break;
476     case SMDSAbs_Face:
477       aFacesFamily->AddElement(anElem);
478       break;
479     case SMDSAbs_Volume:
480       aVolumesFamily->AddElement(anElem);
481       break;
482     default:
483       break;
484     }
485   }
486
487   if (!aNodesFamily->IsEmpty()) {
488     aNodesFamily->SetType(SMDSAbs_Node);
489     aNodesFamily->AddGroupName(submeshGrpName);
490     aFamilies.push_back(aNodesFamily);
491   }
492   if (!anEdgesFamily->IsEmpty()) {
493     anEdgesFamily->SetType(SMDSAbs_Edge);
494     anEdgesFamily->AddGroupName(submeshGrpName);
495     aFamilies.push_back(anEdgesFamily);
496   }
497   if (!aFacesFamily->IsEmpty()) {
498     aFacesFamily->SetType(SMDSAbs_Face);
499     aFacesFamily->AddGroupName(submeshGrpName);
500     aFamilies.push_back(aFacesFamily);
501   }
502   if (!aVolumesFamily->IsEmpty()) {
503     aVolumesFamily->SetType(SMDSAbs_Volume);
504     aVolumesFamily->AddGroupName(submeshGrpName);
505     aFamilies.push_back(aVolumesFamily);
506   }
507
508   return aFamilies;
509 }
510
511 //=============================================================================
512 /*!
513  *  Remove from <myElements> elements, common with <by>,
514  *  Remove from <by> elements, common with <myElements>,
515  *  Create family <common> from common elements, with combined groups list.
516  */
517 //=============================================================================
518 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
519                               DriverMED_FamilyPtr common)
520 {
521   // Elements
522   ElementsSet::iterator anIter = by->myElements.begin();
523   while ( anIter != by->myElements.end())
524   {
525     if (myElements.find(*anIter) != myElements.end())
526     {
527       common->myElements.insert(*anIter);
528       myElements.erase(*anIter);
529       by->myElements.erase(anIter++);
530     }
531     else
532       anIter++;
533   }
534
535   if (!common->IsEmpty())
536   {
537     // Groups list
538     common->myGroupNames = myGroupNames;
539     MED::TStringSet::iterator aGrNamesIter = by->myGroupNames.begin();
540     for (; aGrNamesIter != by->myGroupNames.end(); aGrNamesIter++)
541     {
542       common->myGroupNames.insert(*aGrNamesIter);
543     }
544
545     // Type
546     common->myType = myType;
547   }
548 }