1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // SMESH DriverMED : tool to split groups on families
23 // File : DriverMED_Family.cxx
24 // Author : Julia DOROVSKIKH
28 #include "DriverMED_Family.h"
29 #include "MED_Factory.hxx"
35 //=============================================================================
39 //=============================================================================
46 //=============================================================================
49 ::GetElements () const
63 ::SetId (const int theId)
70 ::AddElement(const SMDS_MeshElement* theElement)
72 myElements.insert(theElement);
77 ::AddGroupName(std::string theGroupName)
79 myGroupNames.insert(theGroupName);
84 ::SetType(const SMDSAbs_ElementType theType)
98 ::MemberOf(std::string theGroupName) const
100 return myGroupNames.find(theGroupName) != myGroupNames.end();
103 const MED::TStringSet&
105 ::GetGroupNames () const
113 ::GetGroupAttributVal() const
115 return myGroupAttributVal;
120 ::SetGroupAttributVal( int theValue)
122 myGroupAttributVal = theValue;
129 return myElements.empty();
132 //=============================================================================
134 * Split each group from list <aGroups> on some parts (families)
135 * on the basis of the elements membership in other groups from this list.
136 * Resulting families have no common elements.
138 //=============================================================================
139 DriverMED_FamilyPtrList
141 ::MakeFamilies(const SMESHDS_SubMeshPtrMap& theSubMeshes,
142 const SMESHDS_GroupBasePtrList& theGroups,
143 const bool doGroupOfNodes,
144 const bool doGroupOfEdges,
145 const bool doGroupOfFaces,
146 const bool doGroupOfVolumes)
148 DriverMED_FamilyPtrList aFamilies;
150 string anAllNodesGroupName = "Group_Of_All_Nodes";
151 string anAllEdgesGroupName = "Group_Of_All_Edges";
152 string anAllFacesGroupName = "Group_Of_All_Faces";
153 string anAllVolumesGroupName = "Group_Of_All_Volumes";
155 // Reserve four ids for families of free elements
156 // (1 - nodes, -1 - edges, -2 - faces, -3 - volumes).
157 // 'Free' means here not belonging to any group.
158 int aNodeFamId = FIRST_NODE_FAMILY;
159 int aElemFamId = FIRST_ELEM_FAMILY;
161 // Process sub-meshes
162 SMESHDS_SubMeshPtrMap::const_iterator aSMIter = theSubMeshes.begin();
163 for (; aSMIter != theSubMeshes.end(); aSMIter++)
165 const int anId = aSMIter->first;
166 SMESHDS_SubMesh* aSubMesh = aSMIter->second;
167 if ( aSubMesh->IsComplexSubmesh() )
168 continue; // submesh containing other submeshs
169 DriverMED_FamilyPtrList aSMFams = SplitByType(aSubMesh,anId);
170 DriverMED_FamilyPtrList::iterator aSMFamsIter = aSMFams.begin();
171 for (; aSMFamsIter != aSMFams.end(); aSMFamsIter++)
173 DriverMED_FamilyPtr aFam2 = (*aSMFamsIter);
174 DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
175 while (aFamsIter != aFamilies.end())
177 DriverMED_FamilyPtr aFam1 = *aFamsIter;
178 DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
179 if (aFam1->myType == aFam2->myType)
181 DriverMED_FamilyPtr aCommon (new DriverMED_Family);
182 aFam1->Split(aFam2, aCommon);
183 if (!aCommon->IsEmpty())
185 aFamilies.push_back(aCommon);
187 if (aFam1->IsEmpty())
189 aFamilies.erase(aCurrIter);
191 if (aFam2->IsEmpty())
195 // The rest elements of family
196 if (!aFam2->IsEmpty())
198 aFamilies.push_back(aFam2);
204 SMESHDS_GroupBasePtrList::const_iterator aGroupsIter = theGroups.begin();
205 for (; aGroupsIter != theGroups.end(); aGroupsIter++)
207 DriverMED_FamilyPtr aFam2 (new DriverMED_Family);
208 aFam2->Init(*aGroupsIter);
210 DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
211 while (aFamsIter != aFamilies.end())
213 DriverMED_FamilyPtr aFam1 = *aFamsIter;
214 DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
215 if (aFam1->myType == aFam2->myType)
217 DriverMED_FamilyPtr aCommon (new DriverMED_Family);
218 aFam1->Split(aFam2, aCommon);
219 if (!aCommon->IsEmpty())
221 aCommon->SetGroupAttributVal(0);
222 aFamilies.push_back(aCommon);
224 if (aFam1->IsEmpty())
226 aFamilies.erase(aCurrIter);
228 if (aFam2->IsEmpty())
232 // The rest elements of group
233 if (!aFam2->IsEmpty())
235 aFamilies.push_back(aFam2);
239 DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
240 for (; aFamsIter != aFamilies.end(); aFamsIter++)
242 DriverMED_FamilyPtr aFam = *aFamsIter;
243 if (aFam->myType == SMDSAbs_Node) {
244 aFam->SetId(aNodeFamId++);
245 if (doGroupOfNodes) aFam->myGroupNames.insert(anAllNodesGroupName);
248 aFam->SetId(aElemFamId--);
249 if (aFam->myType == SMDSAbs_Edge) {
250 if (doGroupOfEdges) aFam->myGroupNames.insert(anAllEdgesGroupName);
252 else if (aFam->myType == SMDSAbs_Face) {
253 if (doGroupOfFaces) aFam->myGroupNames.insert(anAllFacesGroupName);
255 else if (aFam->myType == SMDSAbs_Volume) {
256 if (doGroupOfVolumes) aFam->myGroupNames.insert(anAllVolumesGroupName);
261 // Create families for elements, not belonging to any group
264 DriverMED_FamilyPtr aFreeNodesFam (new DriverMED_Family);
265 aFreeNodesFam->SetId(REST_NODES_FAMILY);
266 aFreeNodesFam->myType = SMDSAbs_Node;
267 aFreeNodesFam->myGroupNames.insert(anAllNodesGroupName);
268 aFamilies.push_back(aFreeNodesFam);
273 DriverMED_FamilyPtr aFreeEdgesFam (new DriverMED_Family);
274 aFreeEdgesFam->SetId(REST_EDGES_FAMILY);
275 aFreeEdgesFam->myType = SMDSAbs_Edge;
276 aFreeEdgesFam->myGroupNames.insert(anAllEdgesGroupName);
277 aFamilies.push_back(aFreeEdgesFam);
282 DriverMED_FamilyPtr aFreeFacesFam (new DriverMED_Family);
283 aFreeFacesFam->SetId(REST_FACES_FAMILY);
284 aFreeFacesFam->myType = SMDSAbs_Face;
285 aFreeFacesFam->myGroupNames.insert(anAllFacesGroupName);
286 aFamilies.push_back(aFreeFacesFam);
289 if (doGroupOfVolumes)
291 DriverMED_FamilyPtr aFreeVolumesFam (new DriverMED_Family);
292 aFreeVolumesFam->SetId(REST_VOLUMES_FAMILY);
293 aFreeVolumesFam->myType = SMDSAbs_Volume;
294 aFreeVolumesFam->myGroupNames.insert(anAllVolumesGroupName);
295 aFamilies.push_back(aFreeVolumesFam);
298 DriverMED_FamilyPtr aNullFam (new DriverMED_Family);
300 aNullFam->myType = SMDSAbs_All;
301 aFamilies.push_back(aNullFam);
306 //=============================================================================
308 * Create TFamilyInfo for this family
310 //=============================================================================
312 DriverMED_Family::GetFamilyInfo(const MED::PWrapper& theWrapper,
313 const MED::PMeshInfo& theMeshInfo) const
316 aStr << "FAM_" << myId;
317 set<string>::const_iterator aGrIter = myGroupNames.begin();
318 for(; aGrIter != myGroupNames.end(); aGrIter++){
319 aStr << "_" << *aGrIter;
321 string aValue = aStr.str();
322 // PAL19785,0019867 - med forbids whitespace to be the last char in the name
324 if ( theWrapper->GetVersion() == MED::eV2_1 )
325 maxSize = MED::GetNOMLength<MED::eV2_1>();
327 maxSize = MED::GetNOMLength<MED::eV2_2>();
328 int lastCharPos = min( maxSize, (int) aValue.size() ) - 1;
329 while ( isspace( aValue[ lastCharPos ] ))
330 aValue.resize( lastCharPos-- );
332 MED::PFamilyInfo anInfo;
333 if(myId == 0 || myGroupAttributVal == 0){
334 anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
339 MED::TStringVector anAttrDescs (1, ""); // 1 attribute with empty description,
340 MED::TIntVector anAttrIds (1, myId); // Id=0,
341 MED::TIntVector anAttrVals (1, myGroupAttributVal);
342 anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
352 // cout << "Groups: ";
353 // set<string>::iterator aGrIter = myGroupNames.begin();
354 // for (; aGrIter != myGroupNames.end(); aGrIter++)
356 // cout << " " << *aGrIter;
360 // cout << "Elements: ";
361 // set<const SMDS_MeshElement *>::iterator anIter = myElements.begin();
362 // for (; anIter != myElements.end(); anIter++)
364 // cout << " " << (*anIter)->GetID();
371 //=============================================================================
373 * Initialize the tool by SMESHDS_GroupBase
375 //=============================================================================
376 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup)
380 SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
381 while (elemIt->more())
383 myElements.insert(elemIt->next());
387 myType = theGroup->GetType();
390 myGroupNames.clear();
391 myGroupNames.insert(string(theGroup->GetStoreName()));
393 Quantity_Color aColor = theGroup->GetColor();
394 double aRed = aColor.Red();
395 double aGreen = aColor.Green();
396 double aBlue = aColor.Blue();
397 int aR = int( aRed*255 );
398 int aG = int( aGreen*255 );
399 int aB = int( aBlue*255 );
400 // cout << "aRed = " << aR << endl;
401 // cout << "aGreen = " << aG << endl;
402 // cout << "aBlue = " << aB << endl;
403 myGroupAttributVal = (int)(aR*1000000 + aG*1000 + aB);
404 //cout << "myGroupAttributVal = " << myGroupAttributVal << endl;
407 //=============================================================================
409 * Split <theSubMesh> on some parts (families)
410 * on the basis of the elements type.
412 //=============================================================================
413 DriverMED_FamilyPtrList
415 ::SplitByType (SMESHDS_SubMesh* theSubMesh,
418 DriverMED_FamilyPtrList aFamilies;
419 DriverMED_FamilyPtr aNodesFamily (new DriverMED_Family);
420 DriverMED_FamilyPtr anEdgesFamily (new DriverMED_Family);
421 DriverMED_FamilyPtr aFacesFamily (new DriverMED_Family);
422 DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
424 char submeshGrpName[ 30 ];
425 sprintf( submeshGrpName, "SubMesh %d", theId );
427 SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
428 while (aNodesIter->more())
430 const SMDS_MeshNode* aNode = aNodesIter->next();
431 aNodesFamily->AddElement(aNode);
434 SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
435 while (anElemsIter->more())
437 const SMDS_MeshElement* anElem = anElemsIter->next();
438 switch (anElem->GetType())
441 anEdgesFamily->AddElement(anElem);
444 aFacesFamily->AddElement(anElem);
447 aVolumesFamily->AddElement(anElem);
454 if (!aNodesFamily->IsEmpty()) {
455 aNodesFamily->SetType(SMDSAbs_Node);
456 aNodesFamily->AddGroupName(submeshGrpName);
457 aFamilies.push_back(aNodesFamily);
459 if (!anEdgesFamily->IsEmpty()) {
460 anEdgesFamily->SetType(SMDSAbs_Edge);
461 anEdgesFamily->AddGroupName(submeshGrpName);
462 aFamilies.push_back(anEdgesFamily);
464 if (!aFacesFamily->IsEmpty()) {
465 aFacesFamily->SetType(SMDSAbs_Face);
466 aFacesFamily->AddGroupName(submeshGrpName);
467 aFamilies.push_back(aFacesFamily);
469 if (!aVolumesFamily->IsEmpty()) {
470 aVolumesFamily->SetType(SMDSAbs_Volume);
471 aVolumesFamily->AddGroupName(submeshGrpName);
472 aFamilies.push_back(aVolumesFamily);
478 //=============================================================================
480 * Remove from <myElements> elements, common with <by>,
481 * Remove from <by> elements, common with <myElements>,
482 * Create family <common> from common elements, with combined groups list.
484 //=============================================================================
485 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
486 DriverMED_FamilyPtr common)
489 ElementsSet::iterator anIter = by->myElements.begin();
490 while ( anIter != by->myElements.end())
492 if (myElements.find(*anIter) != myElements.end())
494 common->myElements.insert(*anIter);
495 myElements.erase(*anIter);
496 by->myElements.erase(anIter++);
502 if (!common->IsEmpty())
505 common->myGroupNames = myGroupNames;
506 MED::TStringSet::iterator aGrNamesIter = by->myGroupNames.begin();
507 for (; aGrNamesIter != by->myGroupNames.end(); aGrNamesIter++)
509 common->myGroupNames.insert(*aGrNamesIter);
513 common->myType = myType;