Salome HOME
Mesh redesine. New fields added to specify whether hypothesis is main or additional...
[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   
231   MED::PFamilyInfo anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
232                                                      aValue,
233                                                      myId,
234                                                      myGroupNames);
235 /*                                                   
236                                                     anAttrDescs,
237                                                     anAttrIds,
238                                                     anAttrVals);
239 */
240
241 //  cout << endl;
242 //  cout << "Groups: ";
243 //  set<string>::iterator aGrIter = myGroupNames.begin();
244 //  for (; aGrIter != myGroupNames.end(); aGrIter++)
245 //  {
246 //    cout << " " << *aGrIter;
247 //  }
248 //  cout << endl;
249 //
250 //  cout << "Elements: ";
251 //  set<const SMDS_MeshElement *>::iterator anIter = myElements.begin();
252 //  for (; anIter != myElements.end(); anIter++)
253 //  {
254 //    cout << " " << (*anIter)->GetID();
255 //  }
256 //  cout << endl;
257
258   return anInfo;
259 }
260
261 //=============================================================================
262 /*!
263  *  Initialize the tool by SMESHDS_GroupBase
264  */
265 //=============================================================================
266 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup)
267 {
268   // Elements
269   myElements.clear();
270   SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
271   while (elemIt->more())
272   {
273     myElements.insert(elemIt->next());
274   }
275
276   // Type
277   myType = theGroup->GetType();
278
279   // Groups list
280   myGroupNames.clear();
281   myGroupNames.insert(string(theGroup->GetStoreName()));
282 }
283
284 //=============================================================================
285 /*!
286  *  Split <theSubMesh> on some parts (families)
287  *  on the basis of the elements type.
288  */
289 //=============================================================================
290 list<DriverMED_FamilyPtr> DriverMED_Family::SplitByType (SMESHDS_SubMesh* theSubMesh,
291                                                          const int        theId)
292 {
293   list<DriverMED_FamilyPtr> aFamilies;
294   DriverMED_FamilyPtr aNodesFamily   (new DriverMED_Family);
295   DriverMED_FamilyPtr anEdgesFamily  (new DriverMED_Family);
296   DriverMED_FamilyPtr aFacesFamily   (new DriverMED_Family);
297   DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
298
299   char submeshGrpName[ 30 ];
300   sprintf( submeshGrpName, "SubMesh %d", theId );
301
302   SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
303   while (aNodesIter->more())
304   {
305     const SMDS_MeshNode* aNode = aNodesIter->next();
306     aNodesFamily->AddElement(aNode);
307   }
308
309   SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
310   while (anElemsIter->more())
311   {
312     const SMDS_MeshElement* anElem = anElemsIter->next();
313     switch (anElem->GetType())
314     {
315     case SMDSAbs_Edge:
316       anEdgesFamily->AddElement(anElem);
317       break;
318     case SMDSAbs_Face:
319       aFacesFamily->AddElement(anElem);
320       break;
321     case SMDSAbs_Volume:
322       aVolumesFamily->AddElement(anElem);
323       break;
324     default:
325       break;
326     }
327   }
328
329   if (!aNodesFamily->IsEmpty()) {
330     aNodesFamily->SetType(SMDSAbs_Node);
331     aNodesFamily->AddGroupName(submeshGrpName);
332     aFamilies.push_back(aNodesFamily);
333   }
334   if (!anEdgesFamily->IsEmpty()) {
335     anEdgesFamily->SetType(SMDSAbs_Edge);
336     anEdgesFamily->AddGroupName(submeshGrpName);
337     aFamilies.push_back(anEdgesFamily);
338   }
339   if (!aFacesFamily->IsEmpty()) {
340     aFacesFamily->SetType(SMDSAbs_Face);
341     aFacesFamily->AddGroupName(submeshGrpName);
342     aFamilies.push_back(aFacesFamily);
343   }
344   if (!aVolumesFamily->IsEmpty()) {
345     aVolumesFamily->SetType(SMDSAbs_Volume);
346     aVolumesFamily->AddGroupName(submeshGrpName);
347     aFamilies.push_back(aVolumesFamily);
348   }
349
350   return aFamilies;
351 }
352
353 //=============================================================================
354 /*!
355  *  Remove from <myElements> elements, common with <by>,
356  *  Remove from <by> elements, common with <myElements>,
357  *  Create family <common> from common elements, with combined groups list.
358  */
359 //=============================================================================
360 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
361                               DriverMED_FamilyPtr common)
362 {
363   // Elements
364   set<const SMDS_MeshElement *>::iterator anIter = by->myElements.begin();
365   while ( anIter != by->myElements.end())
366   {
367     if (myElements.find(*anIter) != myElements.end())
368     {
369       common->myElements.insert(*anIter);
370       myElements.erase(*anIter);
371       by->myElements.erase(anIter++);
372     }
373     else
374       anIter++;
375   }
376
377   if (!common->IsEmpty())
378   {
379     // Groups list
380     common->myGroupNames = myGroupNames;
381     set<string>::iterator aGrNamesIter = by->myGroupNames.begin();
382     for (; aGrNamesIter != by->myGroupNames.end(); aGrNamesIter++)
383     {
384       common->myGroupNames.insert(*aGrNamesIter);
385     }
386
387     // Type
388     common->myType = myType;
389   }
390 }