X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDLoader%2FMEDFileMesh.cxx;h=49d4755ae2f54b4e6003d36b6e23d7c220aabc70;hb=8bae03a55f48814db1d747c9ef8a8ee51d64e6d4;hp=8cdf00b688f3e4ce13bea4a21d0cc77e96021e8c;hpb=44cbe7017677491d4647595d804e5d8f5d489c82;p=tools%2Fmedcoupling.git diff --git a/src/MEDLoader/MEDFileMesh.cxx b/src/MEDLoader/MEDFileMesh.cxx index 8cdf00b68..49d4755ae 100644 --- a/src/MEDLoader/MEDFileMesh.cxx +++ b/src/MEDLoader/MEDFileMesh.cxx @@ -766,7 +766,7 @@ std::vector MEDFileMesh::removeOrphanGroups() * family field whatever its level. Groups are updated in consequence, that is to say all groups lying on orphan family, will see their families list modified. * * \return - The list of removed families names. - * \sa MEDFileMesh::removeOrphanGroups. + * \sa MEDFileMesh::removeOrphanGroups , MEDFileMesh::removeFamiliesReferedByNoGroups */ std::vector MEDFileMesh::removeOrphanFamilies() { @@ -807,6 +807,7 @@ std::vector MEDFileMesh::removeOrphanFamilies() * this family is orphan or not. * * \warning this method is different from removeOrphanFamilies that scans family field array to find orphan families. + * \sa MEDFileMesh::removeOrphanFamilies */ void MEDFileMesh::removeFamiliesReferedByNoGroups() { @@ -829,7 +830,7 @@ void MEDFileMesh::removeFamiliesReferedByNoGroups() * * This method also raises an exception if a family belonging to a group has also id 0 (which is not right in MED file format). You should never encounter this case using addGroup method. * - * \sa MEDFileMesh::removeOrphanFamilies + * \sa MEDFileMesh::removeOrphanFamilies, MEDFileMesh::zipFamilies */ void MEDFileMesh::rearrangeFamilies() { @@ -874,6 +875,83 @@ void MEDFileMesh::rearrangeFamilies() removeOrphanFamilies(); } +/*! + * This method has no impact on existing groups. This method has only impact on families behind the groups. + * This method is especially useful for MED file structures having used too much families to define their groups and that need to be merged without modification of their groups. + * To zip families, firstly this method first removes families refered by no groups (see MEDFileMesh::removeFamiliesReferedByNoGroups), then this method puts together families lying on a same set of groups. If the set of families having same groups has a length higher than 1, the families are merged into a single family + * having the name of the first family appearing in family definition and with the corresponding family ID. + */ +void MEDFileMesh::zipFamilies() +{ + checkOrphanFamilyZero(); + removeFamiliesReferedByNoGroups(); + std::map< std::set , std::vector > setOfFamilies; + // firstly, store in setOfFamilies as key the common set of groups, and as value the families having such same set of groups + for(auto fam : _families) + { + std::vector grps( this->getGroupsOnFamily( fam.first ) ); + std::set sgrps(grps.begin(),grps.end()); + setOfFamilies[sgrps].push_back(fam.first); + } + // + std::map > newGroups(_groups); + std::map newFams(_families); + std::vector levels(getNonEmptyLevelsExt()); + std::map > famIdsToSubstitute; + // iterate on all different set of groups + std::set familiesToKill; + for(auto setOfCommonGrp : setOfFamilies) + { + if( setOfCommonGrp.second.size()<=1 ) + continue; + for(auto fam=setOfCommonGrp.second.begin()+1 ; fam != setOfCommonGrp.second.end() ; fam++) + familiesToKill.insert(*fam); + } + // iterate on all different set of groups + for(auto setOfCommonGrp : setOfFamilies) + { + if( setOfCommonGrp.second.size()<=1 ) + continue; + std::string newFamName(setOfCommonGrp.second[0]); + auto newFamID(_families[newFamName]); + for(auto grpToBeModified : setOfCommonGrp.first) + { + std::vector newFamiliesForCurGrp(1,newFamName); + const std::vector& familiesOnCurGrp(_groups[grpToBeModified]); + const std::vector& familiesToZip(setOfCommonGrp.second); + std::for_each(familiesToZip.begin(),familiesToZip.end(),[&famIdsToSubstitute,this,newFamID](const std::string& elt) { famIdsToSubstitute[newFamID].push_back(this->getFamilyId(elt)); }); + // for each family shared by the current group only keep those not sharing setOfCommonGrp.second + std::for_each(familiesOnCurGrp.begin(),familiesOnCurGrp.end(),[&familiesToKill,&newFamiliesForCurGrp](const std::string& elt) + { if( familiesToKill.find(elt) == familiesToKill.end() ) { newFamiliesForCurGrp.push_back(elt); } }); + newGroups[grpToBeModified] = newFamiliesForCurGrp; + } + for(auto familyToKill = setOfCommonGrp.second.begin()+1 ; familyToKill != setOfCommonGrp.second.end(); ++familyToKill) + { + newFams.erase( newFams.find(*familyToKill) ); + } + + } + // apply modifications in datastructure + for(auto famIdsSubstSession : famIdsToSubstitute) + { + for(std::vector::const_iterator it=levels.begin();it!=levels.end();it++) + { + DataArrayInt *fams(nullptr); + try + { + fams=getFamilyFieldAtLevel(*it); + } + catch(INTERP_KERNEL::Exception& e) { } + if(!fams) + continue; + MCAuto idsToModif(fams->findIdsEqualList(famIdsSubstSession.second.data(),famIdsSubstSession.second.data()+famIdsSubstSession.second.size())); + fams->setPartOfValuesSimple3(famIdsSubstSession.first,idsToModif->begin(),idsToModif->end(),0,1,1); + } + } + _groups = newGroups; + _families = newFams; +} + /*! * This method only checks that "FAMILLE_ZERO" is orphan (not belonging to a group). */ @@ -4666,6 +4744,11 @@ MCAuto MEDFileUMesh::symmetry3DPlane(const double point[3], const return ret; } +/*! + * Aggregate the given MEDFileUMesh objects into a single mesh. When groups are present, those are + * merged in such a way that the final mesh contain all of them. + * \return a new object. + */ MCAuto MEDFileUMesh::Aggregate(const std::vector& meshes) { if(meshes.empty()) @@ -4690,6 +4773,7 @@ MCAuto MEDFileUMesh::Aggregate(const std::vector famNumMap; std::map famNumMap_rev; std::map > grpFamMap; + std::set< MCAuto > mem_cleanup; // Memory clean-up. At set deletion (end of method), arrays will be deallocated. // Identify min family number used: int min_fam_num(0); @@ -4765,7 +4849,8 @@ MCAuto MEDFileUMesh::Aggregate(const std::vectorgetFamilyFieldAtLevel(level)->deepCopy()); // Need a copy + DataArrayInt* dai(msh->getFamilyFieldAtLevel(level)->deepCopy()); // Need a copy + mem_cleanup.insert(MCAuto(dai)); // Make sure array will decrRef() at end of method for (const auto& subN : substituteN) dai->changeValue(subN.first, subN.second); m_fam[level].push_back(dai); @@ -4777,17 +4862,30 @@ MCAuto MEDFileUMesh::Aggregate(const std::vector >& locMap2(msh->getGroupInfo()); for(const auto& grpItem : locMap2) { - const auto& famLst = grpItem.second; + const std::string& grpName = grpItem.first; + std::vector famLst; // Substitute family name in group description if needed: if (fam_conflict) { - std::vector newLst(famLst); // Copy needed. + famLst = grpItem.second; for (const auto& sub : substitute) - std::replace(newLst.begin(), newLst.end(), sub.first, sub.second); - grpFamMap[grpItem.first]=newLst; + std::replace(famLst.begin(), famLst.end(), sub.first, sub.second); } else - grpFamMap[grpItem.first]=famLst; + famLst = grpItem.second; + + // Potentially merge groups (if same name): + const auto& it = grpFamMap.find(grpName); + if (it != grpFamMap.end()) + { + // Group already exists, merge should be done. Normally we whould never + // have twice the same family name in famLstCur and famLst since we dealt with family number + // conflict just above ... + std::vector& famLstCur = (*it).second; + famLstCur.insert(famLstCur.end(), famLst.begin(), famLst.end()); + } + else + grpFamMap[grpName] = famLst; } } // Easy part : nodes @@ -5916,7 +6014,7 @@ void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArra { int nbCells=mesh->getNumberOfCellsOfSubLevelMesh(); nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !"); - _names_cells=nameArr; + _names_faces=nameArr; } default: throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");