From 5e01d1ac989eec334632a1010d1c346d98815eb1 Mon Sep 17 00:00:00 2001 From: ageay Date: Tue, 19 Jun 2012 09:04:33 +0000 Subject: [PATCH] fam ids renumbering. --- src/MEDLoader/MEDFileMesh.cxx | 258 +++++++++++++++++++++++++++++++++ src/MEDLoader/MEDFileMesh.hxx | 6 + src/MEDLoader/Swig/MEDLoader.i | 7 + 3 files changed, 271 insertions(+) diff --git a/src/MEDLoader/MEDFileMesh.cxx b/src/MEDLoader/MEDFileMesh.cxx index f34755503..d0a2f2937 100644 --- a/src/MEDLoader/MEDFileMesh.cxx +++ b/src/MEDLoader/MEDFileMesh.cxx @@ -553,6 +553,21 @@ void MEDFileMesh::setFamilyId(const char *familyName, int id) _families[fname]=id; } +void MEDFileMesh::setFamilyIdUnique(const char *familyName, int id) throw(INTERP_KERNEL::Exception) +{ + std::string fname(familyName); + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + if((*it).second==id) + { + if((*it).first!=familyName) + { + std::ostringstream oss; oss << "MEDFileMesh::setFamilyIdUnique : Family id #" << id << " is already belonging to family with name \"" << (*it).first << "\" !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + _families[fname]=id; +} + /*! * This method appends a new entry in _families attribute. An exception is thrown if either the famId is already * kept by an another familyName. An exception is thrown if name 'familyName' is alreadyset with a different 'famId'. @@ -804,6 +819,249 @@ int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception) return ret; } +int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception) +{ + if(_families.empty()) + throw INTERP_KERNEL::Exception("MEDFileUMesh::getMinFamilyId : no families set !"); + int ret=std::numeric_limits::max(); + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + { + ret=std::min((*it).second,ret); + } + return ret; +} + +DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); + std::set v; + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + v.insert((*it).second); + ret->alloc((int)v.size(),1); + std::copy(v.begin(),v.end(),ret->getPointer()); + ret->incrRef(); return ret; +} + +/*! + * true is returned if no modification has been needed. false if family + * renumbering has been needed. + */ +bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception) +{ + std::vector levs=getNonEmptyLevelsExt(); + std::set allFamIds; + int maxId=getMaxFamilyId()+1; + std::map > famIdsToRenum; + for(std::vector::const_iterator it=levs.begin();it!=levs.end();it++) + { + const DataArrayInt *fam=getFamilyFieldAtLevel(*it); + if(fam) + { + std::set tmp=fam->getDifferentValues(); + std::set r2; + std::set_intersection(tmp.begin(),tmp.end(),allFamIds.begin(),allFamIds.end(),std::inserter(r2,r2.end())); + if(!r2.empty()) + famIdsToRenum[*it].insert(famIdsToRenum[*it].end(),r2.begin(),r2.end()); + std::set r3; + std::set_union(tmp.begin(),tmp.end(),allFamIds.begin(),allFamIds.end(),std::inserter(r3,r3.end())); + } + } + if(famIdsToRenum.empty()) + return true; + MEDCouplingAutoRefCountObjectPtr allIds=getAllFamiliesIdsReferenced(); + for(std::map >::const_iterator it2=famIdsToRenum.begin();it2!=famIdsToRenum.end();it2++) + { + DataArrayInt *fam=const_cast(getFamilyFieldAtLevel((*it2).first)); + int *famIdsToChange=fam->getPointer(); + std::map ren; + for(std::vector::const_iterator it3=(*it2).second.begin();it3!=(*it2).second.end();it3++,maxId++) + { + if(allIds->presenceOfValue(*it3)) + { + std::string famName=getFamilyNameGivenId(*it3); + std::vector grps=getGroupsOnFamily(famName.c_str()); + ren[*it3]=maxId; + bool dummy; + std::string newFam=findOrCreateAndGiveFamilyWithId(maxId,dummy); + for(std::vector::const_iterator it4=grps.begin();it4!=grps.end();it4++) + addFamilyOnGrp((*it4).c_str(),newFam.c_str()); + } + } + MEDCouplingAutoRefCountObjectPtr ids=fam->getIdsEqualList(&(*it2).second[0],&(*it2).second[0]+(*it2).second.size()); + for(const int *id=ids->begin();id!=ids->end();id++) + famIdsToChange[*id]=ren[famIdsToChange[*id]]; + } + return false; +} + +/*! + * This method normalizes fam id with the policy explained underneath. This policy is close to those implemented in SMESH. + * Level #0 famids > 0, Level #-1 famids < 0, Level #-2 famids=0, Level #1 famids=0 + * This policy is those used by SMESH and Trio and that is the opposite of those in MED file. + * This method will throw an exception if a same family id is detected in different level. + * \warning This policy is the opposite of those in MED file documentation ... + */ +void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception) +{ + ensureDifferentFamIdsPerLevel(); + MEDCouplingAutoRefCountObjectPtr allIds=getAllFamiliesIdsReferenced(); + std::vector levs=getNonEmptyLevelsExt(); + std::set levsS(levs.begin(),levs.end()); + std::set famsFetched; + std::map families; + if(std::find(levs.begin(),levs.end(),0)!=levs.end()) + { + levsS.erase(0); + const DataArrayInt *fam=getFamilyFieldAtLevel(0); + if(fam) + { + int refId=1; + std::set tmp=fam->getDifferentValues(); + std::map ren; + for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++,refId++) + ren[*it]=refId; + int nbOfTuples=fam->getNumberOfTuples(); + int *start=const_cast(fam)->getPointer(); + for(int *w=start;w!=start+nbOfTuples;w++) + *w=ren[*w]; + for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++) + { + if(allIds->presenceOfValue(*it)) + { + std::string famName=getFamilyNameGivenId(*it); + families[famName]=ren[*it]; + famsFetched.insert(famName); + } + } + } + } + if(std::find(levs.begin(),levs.end(),-1)!=levs.end()) + { + levsS.erase(-1); + const DataArrayInt *fam=getFamilyFieldAtLevel(-1); + if(fam) + { + int refId=-1; + std::set tmp=fam->getDifferentValues(); + std::map ren; + for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++,refId--) + ren[*it]=refId; + int nbOfTuples=fam->getNumberOfTuples(); + int *start=const_cast(fam)->getPointer(); + for(int *w=start;w!=start+nbOfTuples;w++) + *w=ren[*w]; + for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++) + { + if(allIds->presenceOfValue(*it)) + { + std::string famName=getFamilyNameGivenId(*it); + families[famName]=ren[*it]; + famsFetched.insert(famName); + } + } + } + } + for(std::set::const_iterator it2=levsS.begin();it2!=levsS.end();it2++) + { + DataArrayInt *fam=const_cast(getFamilyFieldAtLevel(*it2)); + if(fam) + { + std::set tmp=fam->getDifferentValues(); + fam->fillWithZero(); + for(std::set::const_iterator it3=tmp.begin();it3!=tmp.end();it3++) + if(allIds->presenceOfValue(*it3)) + { + std::string famName=getFamilyNameGivenId(*it3); + families[famName]=0; + famsFetched.insert(famName); + } + } + } + // + std::vector allFams=getFamiliesNames(); + std::set allFamsS(allFams.begin(),allFams.end()); + std::set unFetchedIds; + std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end())); + for(std::set::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++) + families[*it4]=_families[*it4]; + _families=families; +} + +/*! + * This method normalizes fam id with the following policy. + * Level #0 famids < 0, Level #-1 famids < 0 and for Level #1 famids >= 0 + * This policy is those used by SMESH and Trio and that is the opposite of those in MED file. + * This method will throw an exception if a same family id is detected in different level. + */ +void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception) +{ + ensureDifferentFamIdsPerLevel(); + MEDCouplingAutoRefCountObjectPtr allIds=getAllFamiliesIdsReferenced(); + std::vector levs=getNonEmptyLevelsExt(); + std::set levsS(levs.begin(),levs.end()); + std::set famsFetched; + std::map families; + int refId=1; + if(std::find(levs.begin(),levs.end(),1)!=levs.end()) + { + levsS.erase(1); + const DataArrayInt *fam=getFamilyFieldAtLevel(1); + if(fam) + { + std::set tmp=fam->getDifferentValues(); + std::map ren; + for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++,refId++) + ren[*it]=refId; + int nbOfTuples=fam->getNumberOfTuples(); + int *start=const_cast(fam)->getPointer(); + for(int *w=start;w!=start+nbOfTuples;w++) + *w=ren[*w]; + for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++) + { + if(allIds->presenceOfValue(*it)) + { + std::string famName=getFamilyNameGivenId(*it); + families[famName]=ren[*it]; + famsFetched.insert(famName); + } + } + } + } + refId=-1; + for(std::set::const_reverse_iterator it2=levsS.rbegin();it2!=levsS.rend();it2++) + { + const DataArrayInt *fam=getFamilyFieldAtLevel(1); + if(fam) + { + std::set tmp=fam->getDifferentValues(); + std::map ren; + for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++,refId--) + ren[*it]=refId; + int nbOfTuples=fam->getNumberOfTuples(); + int *start=const_cast(fam)->getPointer(); + for(int *w=start;w!=start+nbOfTuples;w++) + *w=ren[*w]; + for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++) + { + if(allIds->presenceOfValue(*it)) + { + std::string famName=getFamilyNameGivenId(*it); + families[famName]=ren[*it]; + famsFetched.insert(famName); + } + } + } + } + // + std::vector allFams=getFamiliesNames(); + std::set allFamsS(allFams.begin(),allFams.end()); + std::set unFetchedIds; + std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end())); + for(std::set::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++) + families[*it4]=_families[*it4]; + _families=families; +} + /*! * Returns the first (in lexical order) family name having family id equal to 'id'. */ diff --git a/src/MEDLoader/MEDFileMesh.hxx b/src/MEDLoader/MEDFileMesh.hxx index 49e7c3b91..4b2d571b9 100644 --- a/src/MEDLoader/MEDFileMesh.hxx +++ b/src/MEDLoader/MEDFileMesh.hxx @@ -64,6 +64,7 @@ namespace ParaMEDMEM bool existsFamily(int famId) const; bool existsFamily(const char *familyName) const; void setFamilyId(const char *familyName, int id); + void setFamilyIdUnique(const char *familyName, int id) throw(INTERP_KERNEL::Exception); virtual void addFamily(const char *familyName, int id) throw(INTERP_KERNEL::Exception); virtual void createGroupOnAll(int meshDimRelToMaxExt, const char *groupName) throw(INTERP_KERNEL::Exception); virtual bool keepFamIdsOnlyOnLevs(const std::vector& famIds, const std::vector& levs) throw(INTERP_KERNEL::Exception); @@ -91,8 +92,13 @@ namespace ParaMEDMEM void changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exception); int getFamilyId(const char *name) const throw(INTERP_KERNEL::Exception); int getMaxFamilyId() const throw(INTERP_KERNEL::Exception); + int getMinFamilyId() const throw(INTERP_KERNEL::Exception); + DataArrayInt *getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception); std::vector getFamiliesIds(const std::vector& famNames) const throw(INTERP_KERNEL::Exception); std::string getFamilyNameGivenId(int id) const throw(INTERP_KERNEL::Exception); + bool ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception); + void normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception); + void normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception); virtual int getMeshDimension() const throw(INTERP_KERNEL::Exception) = 0; virtual std::string simpleRepr() const; virtual std::string advancedRepr() const = 0; diff --git a/src/MEDLoader/Swig/MEDLoader.i b/src/MEDLoader/Swig/MEDLoader.i index 642d61958..1aba14bb7 100644 --- a/src/MEDLoader/Swig/MEDLoader.i +++ b/src/MEDLoader/Swig/MEDLoader.i @@ -63,6 +63,7 @@ using namespace ParaMEDMEM; %newobject ParaMEDMEM::MEDFileMesh::getNodeGroupsArr; %newobject ParaMEDMEM::MEDFileMesh::getNodeFamilyArr; %newobject ParaMEDMEM::MEDFileMesh::getNodeFamiliesArr; +%newobject ParaMEDMEM::MEDFileMesh::getAllFamiliesIdsReferenced; %newobject ParaMEDMEM::MEDFileUMesh::New; %newobject ParaMEDMEM::MEDFileUMesh::getCoords; %newobject ParaMEDMEM::MEDFileUMesh::getGroup; @@ -339,6 +340,7 @@ namespace ParaMEDMEM bool existsFamily(int famId) const; bool existsFamily(const char *familyName) const; void setFamilyId(const char *familyName, int id); + void setFamilyIdUnique(const char *familyName, int id) throw(INTERP_KERNEL::Exception); void addFamily(const char *familyName, int id) throw(INTERP_KERNEL::Exception); void addFamilyOnGrp(const char *grpName, const char *famName) throw(INTERP_KERNEL::Exception); virtual void createGroupOnAll(int meshDimRelToMaxExt, const char *groupName) throw(INTERP_KERNEL::Exception); @@ -365,8 +367,13 @@ namespace ParaMEDMEM void setGroupInfo(const std::map >&info); int getFamilyId(const char *name) const throw(INTERP_KERNEL::Exception); int getMaxFamilyId() const throw(INTERP_KERNEL::Exception); + int getMinFamilyId() const throw(INTERP_KERNEL::Exception); + DataArrayInt *getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception); std::vector getFamiliesIds(const std::vector& famNames) const throw(INTERP_KERNEL::Exception); std::string getFamilyNameGivenId(int id) const throw(INTERP_KERNEL::Exception); + bool ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception); + void normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception); + void normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception); virtual int getMeshDimension() const throw(INTERP_KERNEL::Exception); virtual std::string simpleRepr() const = 0; virtual std::string advancedRepr() const = 0; -- 2.39.2