Salome HOME
PAL7222: Now names of families will contain names of corresponding groups
[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.org
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  *  Split each group from list <aGroups> on some parts (families)
38  *  on the basis of the elements membership in other groups from this list.
39  *  Resulting families have no common elements.
40  */
41 //=============================================================================
42 list<DriverMED_FamilyPtr> DriverMED_Family::MakeFamilies
43                          (const map <int, SMESHDS_SubMesh*>& theSubMeshes,
44                           const list<SMESHDS_GroupBase*>& theGroups,
45                           const bool doGroupOfNodes,
46                           const bool doGroupOfEdges,
47                           const bool doGroupOfFaces,
48                           const bool doGroupOfVolumes)
49 {
50   list<DriverMED_FamilyPtr> aFamilies;
51
52   string anAllNodesGroupName = "Group_Of_All_Nodes";
53   string anAllEdgesGroupName = "Group_Of_All_Edges";
54   string anAllFacesGroupName = "Group_Of_All_Faces";
55   string anAllVolumesGroupName = "Group_Of_All_Volumes";
56
57   // Reserve four ids for families of free elements
58   // (1 - nodes, -1 - edges, -2 - faces, -3 - volumes).
59   // 'Free' means here not belonging to any group.
60   int aNodeFamId = FIRST_NODE_FAMILY;
61   int aElemFamId = FIRST_ELEM_FAMILY;
62
63   // Process sub-meshes
64   map<int, SMESHDS_SubMesh*>::const_iterator aSMIter = theSubMeshes.begin();
65   for (; aSMIter != theSubMeshes.end(); aSMIter++)
66   {
67     if ( aSMIter->second->IsComplexSubmesh() )
68       continue; // submesh containing other submeshs
69     list<DriverMED_FamilyPtr> aSMFams = SplitByType((*aSMIter).second, (*aSMIter).first);
70     list<DriverMED_FamilyPtr>::iterator aSMFamsIter = aSMFams.begin();
71     for (; aSMFamsIter != aSMFams.end(); aSMFamsIter++)
72     {
73       DriverMED_FamilyPtr aFam2 = (*aSMFamsIter);
74
75       list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
76       while (aFamsIter != aFamilies.end())
77       {
78         DriverMED_FamilyPtr aFam1 = *aFamsIter;
79         list<DriverMED_FamilyPtr>::iterator aCurrIter = aFamsIter++;
80         if (aFam1->myType == aFam2->myType)
81         {
82           DriverMED_FamilyPtr aCommon (new DriverMED_Family);
83           aFam1->Split(aFam2, aCommon);
84           if (!aCommon->IsEmpty())
85           {
86             aFamilies.push_back(aCommon);
87           }
88           if (aFam1->IsEmpty())
89           {
90             aFamilies.erase(aCurrIter);
91           }
92           if (aFam2->IsEmpty()) break;
93         }
94       }
95       // The rest elements of family
96       if (!aFam2->IsEmpty())
97       {
98         aFamilies.push_back(aFam2);
99       }
100     }
101   }
102
103   // Process groups
104   list<SMESHDS_GroupBase*>::const_iterator aGroupsIter = theGroups.begin();
105   for (; aGroupsIter != theGroups.end(); aGroupsIter++)
106   {
107     DriverMED_FamilyPtr aFam2 (new DriverMED_Family);
108     aFam2->Init(*aGroupsIter);
109
110     list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
111     while (aFamsIter != aFamilies.end())
112     {
113       DriverMED_FamilyPtr aFam1 = *aFamsIter;
114       list<DriverMED_FamilyPtr>::iterator aCurrIter = aFamsIter++;
115       if (aFam1->myType == aFam2->myType)
116       {
117         DriverMED_FamilyPtr aCommon (new DriverMED_Family);
118         aFam1->Split(aFam2, aCommon);
119         if (!aCommon->IsEmpty())
120         {
121           aFamilies.push_back(aCommon);
122         }
123         if (aFam1->IsEmpty())
124         {
125           aFamilies.erase(aCurrIter);
126         }
127         if (aFam2->IsEmpty()) break;
128       }
129     }
130     // The rest elements of group
131     if (!aFam2->IsEmpty())
132     {
133       aFamilies.push_back(aFam2);
134     }
135   }
136
137   list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
138   for (; aFamsIter != aFamilies.end(); aFamsIter++)
139   {
140     DriverMED_FamilyPtr aFam = *aFamsIter;
141     if (aFam->myType == SMDSAbs_Node) {
142       aFam->SetId(aNodeFamId++);
143       if (doGroupOfNodes) aFam->myGroupNames.insert(anAllNodesGroupName);
144     }
145     else {
146       aFam->SetId(aElemFamId--);
147       if (aFam->myType == SMDSAbs_Edge) {
148         if (doGroupOfEdges) aFam->myGroupNames.insert(anAllEdgesGroupName);
149       }
150       else if (aFam->myType == SMDSAbs_Face) {
151         if (doGroupOfFaces) aFam->myGroupNames.insert(anAllFacesGroupName);
152       }
153       else if (aFam->myType == SMDSAbs_Volume) {
154         if (doGroupOfVolumes) aFam->myGroupNames.insert(anAllVolumesGroupName);
155       }
156     }
157   }
158
159   // Create families for elements, not belonging to any group
160   if (doGroupOfNodes)
161   {
162     DriverMED_FamilyPtr aFreeNodesFam (new DriverMED_Family);
163     aFreeNodesFam->SetId(REST_NODES_FAMILY);
164     aFreeNodesFam->myType = SMDSAbs_Node;
165     aFreeNodesFam->myGroupNames.insert(anAllNodesGroupName);
166     aFamilies.push_back(aFreeNodesFam);
167   }
168
169   if (doGroupOfEdges)
170   {
171     DriverMED_FamilyPtr aFreeEdgesFam (new DriverMED_Family);
172     aFreeEdgesFam->SetId(REST_EDGES_FAMILY);
173     aFreeEdgesFam->myType = SMDSAbs_Edge;
174     aFreeEdgesFam->myGroupNames.insert(anAllEdgesGroupName);
175     aFamilies.push_back(aFreeEdgesFam);
176   }
177
178   if (doGroupOfFaces)
179   {
180     DriverMED_FamilyPtr aFreeFacesFam (new DriverMED_Family);
181     aFreeFacesFam->SetId(REST_FACES_FAMILY);
182     aFreeFacesFam->myType = SMDSAbs_Face;
183     aFreeFacesFam->myGroupNames.insert(anAllFacesGroupName);
184     aFamilies.push_back(aFreeFacesFam);
185   }
186
187   if (doGroupOfVolumes)
188   {
189     DriverMED_FamilyPtr aFreeVolumesFam (new DriverMED_Family);
190     aFreeVolumesFam->SetId(REST_VOLUMES_FAMILY);
191     aFreeVolumesFam->myType = SMDSAbs_Volume;
192     aFreeVolumesFam->myGroupNames.insert(anAllVolumesGroupName);
193     aFamilies.push_back(aFreeVolumesFam);
194   }
195
196   DriverMED_FamilyPtr aNullFam (new DriverMED_Family);
197   aNullFam->SetId(0);
198   aNullFam->myType = SMDSAbs_All;
199   aFamilies.push_back(aNullFam);
200
201   return aFamilies;
202 }
203
204 //=============================================================================
205 /*!
206  *  Create TFamilyInfo for this family
207  */
208 //=============================================================================
209 MED::PFamilyInfo 
210 DriverMED_Family::GetFamilyInfo(const MED::PWrapper& theWrapper, 
211                                 const MED::PMeshInfo& theMeshInfo) const
212 {
213   string aValue;
214
215   ostringstream aStr;
216
217   aStr << "FAM_" << myId;
218   set<string>::iterator aGrIter = myGroupNames.begin();
219   for (; aGrIter != myGroupNames.end(); aGrIter++)
220   {
221     aStr << "_" << *aGrIter;
222   }
223
224   aValue = aStr.str();
225
226   MED::TStringVector anAttrDescs (1, "");  // 1 attribute with empty description,
227   MED::TIntVector anAttrIds (1, myId);        // Id=0,
228   MED::TIntVector anAttrVals (1, myId);       // Value=0
229
230   MED::PFamilyInfo anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
231                                                      aValue,
232                                                      myId,
233                                                      myGroupNames,
234                                                      anAttrDescs,
235                                                      anAttrIds,
236                                                      anAttrVals);
237
238 //  cout << endl;
239 //  cout << "Groups: ";
240 //  set<string>::iterator aGrIter = myGroupNames.begin();
241 //  for (; aGrIter != myGroupNames.end(); aGrIter++)
242 //  {
243 //    cout << " " << *aGrIter;
244 //  }
245 //  cout << endl;
246 //
247 //  cout << "Elements: ";
248 //  set<const SMDS_MeshElement *>::iterator anIter = myElements.begin();
249 //  for (; anIter != myElements.end(); anIter++)
250 //  {
251 //    cout << " " << (*anIter)->GetID();
252 //  }
253 //  cout << endl;
254
255   return anInfo;
256 }
257
258 //=============================================================================
259 /*!
260  *  Initialize the tool by SMESHDS_GroupBase
261  */
262 //=============================================================================
263 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup)
264 {
265   // Elements
266   myElements.clear();
267   SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
268   while (elemIt->more())
269   {
270     myElements.insert(elemIt->next());
271   }
272
273   // Type
274   myType = theGroup->GetType();
275
276   // Groups list
277   myGroupNames.clear();
278   myGroupNames.insert(string(theGroup->GetStoreName()));
279 }
280
281 //=============================================================================
282 /*!
283  *  Split <theSubMesh> on some parts (families)
284  *  on the basis of the elements type.
285  */
286 //=============================================================================
287 list<DriverMED_FamilyPtr> DriverMED_Family::SplitByType (SMESHDS_SubMesh* theSubMesh,
288                                                          const int        theId)
289 {
290   list<DriverMED_FamilyPtr> aFamilies;
291   DriverMED_FamilyPtr aNodesFamily   (new DriverMED_Family);
292   DriverMED_FamilyPtr anEdgesFamily  (new DriverMED_Family);
293   DriverMED_FamilyPtr aFacesFamily   (new DriverMED_Family);
294   DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
295
296   char submeshGrpName[ 30 ];
297   sprintf( submeshGrpName, "SubMesh %d", theId );
298
299   SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
300   while (aNodesIter->more())
301   {
302     const SMDS_MeshNode* aNode = aNodesIter->next();
303     aNodesFamily->AddElement(aNode);
304   }
305
306   SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
307   while (anElemsIter->more())
308   {
309     const SMDS_MeshElement* anElem = anElemsIter->next();
310     switch (anElem->GetType())
311     {
312     case SMDSAbs_Edge:
313       anEdgesFamily->AddElement(anElem);
314       break;
315     case SMDSAbs_Face:
316       aFacesFamily->AddElement(anElem);
317       break;
318     case SMDSAbs_Volume:
319       aVolumesFamily->AddElement(anElem);
320       break;
321     default:
322       break;
323     }
324   }
325
326   if (!aNodesFamily->IsEmpty()) {
327     aNodesFamily->SetType(SMDSAbs_Node);
328     aNodesFamily->AddGroupName(submeshGrpName);
329     aFamilies.push_back(aNodesFamily);
330   }
331   if (!anEdgesFamily->IsEmpty()) {
332     anEdgesFamily->SetType(SMDSAbs_Edge);
333     anEdgesFamily->AddGroupName(submeshGrpName);
334     aFamilies.push_back(anEdgesFamily);
335   }
336   if (!aFacesFamily->IsEmpty()) {
337     aFacesFamily->SetType(SMDSAbs_Face);
338     aFacesFamily->AddGroupName(submeshGrpName);
339     aFamilies.push_back(aFacesFamily);
340   }
341   if (!aVolumesFamily->IsEmpty()) {
342     aVolumesFamily->SetType(SMDSAbs_Volume);
343     aVolumesFamily->AddGroupName(submeshGrpName);
344     aFamilies.push_back(aVolumesFamily);
345   }
346
347   return aFamilies;
348 }
349
350 //=============================================================================
351 /*!
352  *  Remove from <myElements> elements, common with <by>,
353  *  Remove from <by> elements, common with <myElements>,
354  *  Create family <common> from common elements, with combined groups list.
355  */
356 //=============================================================================
357 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
358                               DriverMED_FamilyPtr common)
359 {
360   // Elements
361   set<const SMDS_MeshElement *>::iterator anIter = by->myElements.begin();
362   while ( anIter != by->myElements.end())
363   {
364     if (myElements.find(*anIter) != myElements.end())
365     {
366       common->myElements.insert(*anIter);
367       myElements.erase(*anIter);
368       by->myElements.erase(anIter++);
369     }
370     else
371       anIter++;
372   }
373
374   if (!common->IsEmpty())
375   {
376     // Groups list
377     common->myGroupNames = myGroupNames;
378     set<string>::iterator aGrNamesIter = by->myGroupNames.begin();
379     for (; aGrNamesIter != by->myGroupNames.end(); aGrNamesIter++)
380     {
381       common->myGroupNames.insert(*aGrNamesIter);
382     }
383
384     // Type
385     common->myType = myType;
386   }
387 }