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