1 // Copyright (C) 2007-2012 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
23 // SMESH DriverMED : tool to split groups on families
24 // File : DriverMED_Family.cxx
25 // Author : Julia DOROVSKIKH
29 #include "DriverMED_Family.h"
30 #include "MED_Factory.hxx"
36 //=============================================================================
40 //=============================================================================
47 //=============================================================================
50 ::GetElements () const
64 ::SetId (const int theId)
71 ::AddElement(const SMDS_MeshElement* theElement)
73 myElements.insert(theElement);
78 ::AddGroupName(std::string theGroupName)
80 myGroupNames.insert(theGroupName);
85 ::SetType(const SMDSAbs_ElementType theType)
87 myTypes.insert( myType = theType );
97 const std::set< SMDSAbs_ElementType >&
106 ::MemberOf(std::string theGroupName) const
108 return myGroupNames.find(theGroupName) != myGroupNames.end();
111 const MED::TStringSet&
113 ::GetGroupNames () const
121 ::GetGroupAttributVal() const
123 return myGroupAttributVal;
128 ::SetGroupAttributVal( int theValue)
130 myGroupAttributVal = theValue;
137 return myElements.empty();
140 //=============================================================================
142 * Split each group from list <aGroups> on some parts (families)
143 * on the basis of the elements membership in other groups from this list.
144 * Resulting families have no common elements.
146 //=============================================================================
147 DriverMED_FamilyPtrList
149 ::MakeFamilies(const SMESHDS_SubMeshPtrMap& theSubMeshes,
150 const SMESHDS_GroupBasePtrList& theGroups,
151 const bool doGroupOfNodes,
152 const bool doGroupOfEdges,
153 const bool doGroupOfFaces,
154 const bool doGroupOfVolumes)
156 DriverMED_FamilyPtrList aFamilies;
158 string anAllNodesGroupName = "Group_Of_All_Nodes";
159 string anAllEdgesGroupName = "Group_Of_All_Edges";
160 string anAllFacesGroupName = "Group_Of_All_Faces";
161 string anAllVolumesGroupName = "Group_Of_All_Volumes";
163 // Reserve four ids for families of free elements
164 // (1 - nodes, -1 - edges, -2 - faces, -3 - volumes).
165 // 'Free' means here not belonging to any group.
166 int aNodeFamId = FIRST_NODE_FAMILY;
167 int aElemFamId = FIRST_ELEM_FAMILY;
169 // Process sub-meshes
170 SMESHDS_SubMeshPtrMap::const_iterator aSMIter = theSubMeshes.begin();
171 for (; aSMIter != theSubMeshes.end(); aSMIter++)
173 const int anId = aSMIter->first;
174 SMESHDS_SubMesh* aSubMesh = aSMIter->second;
175 if ( aSubMesh->IsComplexSubmesh() )
176 continue; // submesh containing other submeshs
177 DriverMED_FamilyPtrList aSMFams = SplitByType(aSubMesh,anId);
178 DriverMED_FamilyPtrList::iterator aSMFamsIter = aSMFams.begin();
179 for (; aSMFamsIter != aSMFams.end(); aSMFamsIter++)
181 DriverMED_FamilyPtr aFam2 = (*aSMFamsIter);
182 DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
183 while (aFamsIter != aFamilies.end())
185 DriverMED_FamilyPtr aFam1 = *aFamsIter;
186 DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
187 if (aFam1->myType == aFam2->myType)
189 DriverMED_FamilyPtr aCommon (new DriverMED_Family);
190 aFam1->Split(aFam2, aCommon);
191 if (!aCommon->IsEmpty())
193 aFamilies.push_back(aCommon);
195 if (aFam1->IsEmpty())
197 aFamilies.erase(aCurrIter);
199 if (aFam2->IsEmpty())
203 // The rest elements of family
204 if (!aFam2->IsEmpty())
206 aFamilies.push_back(aFam2);
212 SMESHDS_GroupBasePtrList::const_iterator aGroupsIter = theGroups.begin();
213 for (; aGroupsIter != theGroups.end(); aGroupsIter++)
215 DriverMED_FamilyPtr aFam2 (new DriverMED_Family);
216 aFam2->Init(*aGroupsIter);
218 DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
219 while (aFamsIter != aFamilies.end())
221 DriverMED_FamilyPtr aFam1 = *aFamsIter;
222 DriverMED_FamilyPtrList::iterator aCurrIter = aFamsIter++;
223 if (aFam1->myType == aFam2->myType)
225 DriverMED_FamilyPtr aCommon (new DriverMED_Family);
226 aFam1->Split(aFam2, aCommon);
227 if (!aCommon->IsEmpty())
229 aCommon->SetGroupAttributVal(0);
230 aFamilies.push_back(aCommon);
232 if (aFam1->IsEmpty())
234 aFamilies.erase(aCurrIter);
236 if (aFam2->IsEmpty())
240 // The rest elements of group
241 if (!aFam2->IsEmpty())
243 aFamilies.push_back(aFam2);
247 DriverMED_FamilyPtrList::iterator aFamsIter = aFamilies.begin();
248 for (; aFamsIter != aFamilies.end(); aFamsIter++)
250 DriverMED_FamilyPtr aFam = *aFamsIter;
251 if (aFam->myType == SMDSAbs_Node) {
252 aFam->SetId(aNodeFamId++);
253 if (doGroupOfNodes) aFam->myGroupNames.insert(anAllNodesGroupName);
256 aFam->SetId(aElemFamId--);
257 if (aFam->myType == SMDSAbs_Edge) {
258 if (doGroupOfEdges) aFam->myGroupNames.insert(anAllEdgesGroupName);
260 else if (aFam->myType == SMDSAbs_Face) {
261 if (doGroupOfFaces) aFam->myGroupNames.insert(anAllFacesGroupName);
263 else if (aFam->myType == SMDSAbs_Volume) {
264 if (doGroupOfVolumes) aFam->myGroupNames.insert(anAllVolumesGroupName);
269 // Create families for elements, not belonging to any group
272 DriverMED_FamilyPtr aFreeNodesFam (new DriverMED_Family);
273 aFreeNodesFam->SetId(REST_NODES_FAMILY);
274 aFreeNodesFam->myType = SMDSAbs_Node;
275 aFreeNodesFam->myGroupNames.insert(anAllNodesGroupName);
276 aFamilies.push_back(aFreeNodesFam);
281 DriverMED_FamilyPtr aFreeEdgesFam (new DriverMED_Family);
282 aFreeEdgesFam->SetId(REST_EDGES_FAMILY);
283 aFreeEdgesFam->myType = SMDSAbs_Edge;
284 aFreeEdgesFam->myGroupNames.insert(anAllEdgesGroupName);
285 aFamilies.push_back(aFreeEdgesFam);
290 DriverMED_FamilyPtr aFreeFacesFam (new DriverMED_Family);
291 aFreeFacesFam->SetId(REST_FACES_FAMILY);
292 aFreeFacesFam->myType = SMDSAbs_Face;
293 aFreeFacesFam->myGroupNames.insert(anAllFacesGroupName);
294 aFamilies.push_back(aFreeFacesFam);
297 if (doGroupOfVolumes)
299 DriverMED_FamilyPtr aFreeVolumesFam (new DriverMED_Family);
300 aFreeVolumesFam->SetId(REST_VOLUMES_FAMILY);
301 aFreeVolumesFam->myType = SMDSAbs_Volume;
302 aFreeVolumesFam->myGroupNames.insert(anAllVolumesGroupName);
303 aFamilies.push_back(aFreeVolumesFam);
306 DriverMED_FamilyPtr aNullFam (new DriverMED_Family);
308 aNullFam->myType = SMDSAbs_All;
309 aFamilies.push_back(aNullFam);
314 //=============================================================================
316 * Create TFamilyInfo for this family
318 //=============================================================================
320 DriverMED_Family::GetFamilyInfo(const MED::PWrapper& theWrapper,
321 const MED::PMeshInfo& theMeshInfo) const
324 aStr << "FAM_" << myId;
325 set<string>::const_iterator aGrIter = myGroupNames.begin();
326 for(; aGrIter != myGroupNames.end(); aGrIter++){
327 aStr << "_" << *aGrIter;
329 string aValue = aStr.str();
330 // PAL19785,0019867 - med forbids whitespace to be the last char in the name
332 if ( theWrapper->GetVersion() == MED::eV2_1 )
333 maxSize = MED::GetNOMLength<MED::eV2_1>();
335 maxSize = MED::GetNOMLength<MED::eV2_2>();
336 int lastCharPos = min( maxSize, (int) aValue.size() ) - 1;
337 while ( isspace( aValue[ lastCharPos ] ))
338 aValue.resize( lastCharPos-- );
340 MED::PFamilyInfo anInfo;
341 if(myId == 0 || myGroupAttributVal == 0){
342 anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
347 MED::TStringVector anAttrDescs (1, ""); // 1 attribute with empty description,
348 MED::TIntVector anAttrIds (1, myId); // Id=0,
349 MED::TIntVector anAttrVals (1, myGroupAttributVal);
350 anInfo = theWrapper->CrFamilyInfo(theMeshInfo,
360 // cout << "Groups: ";
361 // set<string>::iterator aGrIter = myGroupNames.begin();
362 // for (; aGrIter != myGroupNames.end(); aGrIter++)
364 // cout << " " << *aGrIter;
368 // cout << "Elements: ";
369 // set<const SMDS_MeshElement *>::iterator anIter = myElements.begin();
370 // for (; anIter != myElements.end(); anIter++)
372 // cout << " " << (*anIter)->GetID();
379 //=============================================================================
381 * Initialize the tool by SMESHDS_GroupBase
383 //=============================================================================
384 void DriverMED_Family::Init (SMESHDS_GroupBase* theGroup)
388 SMDS_ElemIteratorPtr elemIt = theGroup->GetElements();
389 while (elemIt->more())
391 myElements.insert(elemIt->next());
395 myType = theGroup->GetType();
398 myGroupNames.clear();
399 myGroupNames.insert(string(theGroup->GetStoreName()));
401 Quantity_Color aColor = theGroup->GetColor();
402 double aRed = aColor.Red();
403 double aGreen = aColor.Green();
404 double aBlue = aColor.Blue();
405 int aR = int( aRed*255 );
406 int aG = int( aGreen*255 );
407 int aB = int( aBlue*255 );
408 // cout << "aRed = " << aR << endl;
409 // cout << "aGreen = " << aG << endl;
410 // cout << "aBlue = " << aB << endl;
411 myGroupAttributVal = (int)(aR*1000000 + aG*1000 + aB);
412 //cout << "myGroupAttributVal = " << myGroupAttributVal << endl;
415 //=============================================================================
417 * Split <theSubMesh> on some parts (families)
418 * on the basis of the elements type.
420 //=============================================================================
421 DriverMED_FamilyPtrList
423 ::SplitByType (SMESHDS_SubMesh* theSubMesh,
426 DriverMED_FamilyPtrList aFamilies;
427 DriverMED_FamilyPtr aNodesFamily (new DriverMED_Family);
428 DriverMED_FamilyPtr anEdgesFamily (new DriverMED_Family);
429 DriverMED_FamilyPtr aFacesFamily (new DriverMED_Family);
430 DriverMED_FamilyPtr aVolumesFamily (new DriverMED_Family);
432 char submeshGrpName[ 30 ];
433 sprintf( submeshGrpName, "SubMesh %d", theId );
435 SMDS_NodeIteratorPtr aNodesIter = theSubMesh->GetNodes();
436 while (aNodesIter->more())
438 const SMDS_MeshNode* aNode = aNodesIter->next();
439 aNodesFamily->AddElement(aNode);
442 SMDS_ElemIteratorPtr anElemsIter = theSubMesh->GetElements();
443 while (anElemsIter->more())
445 const SMDS_MeshElement* anElem = anElemsIter->next();
446 switch (anElem->GetType())
449 anEdgesFamily->AddElement(anElem);
452 aFacesFamily->AddElement(anElem);
455 aVolumesFamily->AddElement(anElem);
462 if (!aNodesFamily->IsEmpty()) {
463 aNodesFamily->SetType(SMDSAbs_Node);
464 aNodesFamily->AddGroupName(submeshGrpName);
465 aFamilies.push_back(aNodesFamily);
467 if (!anEdgesFamily->IsEmpty()) {
468 anEdgesFamily->SetType(SMDSAbs_Edge);
469 anEdgesFamily->AddGroupName(submeshGrpName);
470 aFamilies.push_back(anEdgesFamily);
472 if (!aFacesFamily->IsEmpty()) {
473 aFacesFamily->SetType(SMDSAbs_Face);
474 aFacesFamily->AddGroupName(submeshGrpName);
475 aFamilies.push_back(aFacesFamily);
477 if (!aVolumesFamily->IsEmpty()) {
478 aVolumesFamily->SetType(SMDSAbs_Volume);
479 aVolumesFamily->AddGroupName(submeshGrpName);
480 aFamilies.push_back(aVolumesFamily);
486 //=============================================================================
488 * Remove from <myElements> elements, common with <by>,
489 * Remove from <by> elements, common with <myElements>,
490 * Create family <common> from common elements, with combined groups list.
492 //=============================================================================
493 void DriverMED_Family::Split (DriverMED_FamilyPtr by,
494 DriverMED_FamilyPtr common)
497 ElementsSet::iterator anIter = by->myElements.begin();
498 while ( anIter != by->myElements.end())
500 if (myElements.find(*anIter) != myElements.end())
502 common->myElements.insert(*anIter);
503 myElements.erase(*anIter);
504 by->myElements.erase(anIter++);
510 if (!common->IsEmpty())
513 common->myGroupNames = myGroupNames;
514 MED::TStringSet::iterator aGrNamesIter = by->myGroupNames.begin();
515 for (; aGrNamesIter != by->myGroupNames.end(); aGrNamesIter++)
517 common->myGroupNames.insert(*aGrNamesIter);
521 common->myType = myType;