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