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