]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
MEDFileMesh::createGroupOnAll
authorageay <ageay>
Tue, 6 Mar 2012 13:51:32 +0000 (13:51 +0000)
committerageay <ageay>
Tue, 6 Mar 2012 13:51:32 +0000 (13:51 +0000)
src/MEDLoader/MEDFileMesh.cxx
src/MEDLoader/MEDFileMesh.hxx
src/MEDLoader/Swig/MEDLoader.i
src/MEDLoader/Swig/MEDLoaderTest3.py

index a29ccb09145b44e53ae61ec6007c67e581dbddcb..dff6bf526e57d8fc4964b855e00c62aff1ab872d 100644 (file)
@@ -412,6 +412,10 @@ void MEDFileMesh::changeGroupName(const char *oldName, const char *newName) thro
   _groups[newName]=cpy;
 }
 
+/*!
+ * This method changes the family ids in 'this'. It leads to a modification into '_families' attributes \b and in
+ * ids stored in arrays. This method calls MEDFileMesh::changeFamilyIdArr method.
+ */
 void MEDFileMesh::changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exception)
 {
   changeFamilyIdArr(oldId,newId);
@@ -523,6 +527,12 @@ bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) cons
   return ret;
 }
 
+bool MEDFileMesh::existsGroup(const char *groupName) const
+{
+  std::string grpName(groupName);
+  return _groups.find(grpName)!=_groups.end();
+}
+
 bool MEDFileMesh::existsFamily(int famId) const
 {
   for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
@@ -573,12 +583,109 @@ void MEDFileMesh::addFamily(const char *familyName, int famId) throw(INTERP_KERN
     }
 }
 
-void MEDFileMesh::addGrpOnFamily(const char *grpName, const char *famName) throw(INTERP_KERNEL::Exception)
+/*!
+ * This method creates a new group called 'groupName' in 'this'. If it exists a group with the same name an INTERP_KERNEL::Exception will be thrown.
+ * If the 'meshDimRelToMaxExt' is not existing an INTERP_KERNEL::Exception will be thrown too.
+ * \b WARNING : This method does \b not garantee that 'groupName' lies only on a single level specified by 'meshDimRelToMaxExt'.
+ * in the case of a presence of one or more family id in family field at 'meshDimRelToMaxExt' level that appears in another level.
+ * If there is a risk of such case call MEDFileMesh::keepFamIdsOnlyOnLevs method \b before calling this method. 
+ * (call to MEDFileMesh::keepFamIdsOnlyOnLevs should be done with MEDFileMesh::getFamiliesIdsOnGroup('groupName' as first input ).
+ */
+void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const char *groupName) throw(INTERP_KERNEL::Exception)
+{
+  std::string grpName(groupName);
+  std::vector<int> levs=getNonEmptyLevelsExt();
+  if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
+    {
+      std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The relative ext dimension " << meshDimRelToMaxExt << " is not available !" << std::endl;
+      oss << "Available relative ext levels are : ";
+      std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  if(existsGroup(groupName))
+    {
+      std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The groups \"" << grpName << "\" already exists in this !" << std::endl;
+      oss << "Already existing groups are : ";
+      std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
+      oss << std::endl << "Please choose an another group name or call removeGroup(\"" << grpName << "\") method !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(meshDimRelToMaxExt);
+  if(fieldFamIds==0)
+    throw INTERP_KERNEL::Exception("MEDFileMesh::createGroupOnAll : Family field arr ids is not defined for this level !");
+  std::set<int> famIds=fieldFamIds->getDifferentValues();
+  std::vector<std::string> familiesOnWholeGroup;
+  for(std::set<int>::const_iterator it=famIds.begin();it!=famIds.end();it++)
+    {
+      bool tmp;
+      familiesOnWholeGroup.push_back(findOrCreateAndGiveFamilyWithId(*it,tmp));
+    }
+  _groups[grpName]=familiesOnWholeGroup;
+}
+
+/*!
+ * This method checks that family Ids in 'famIds' are not present in levels \b not in 'vMeshDimRelToMaxExt'.
+ * If it is the case true is returned and 'this' is not modified.
+ * If there is some levels not in 'vMeshDimRelToMaxExt' where one or more family ids in 'famIds' appear
+ * new families are created and groups are updated in consequence.
+ */
+bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std::vector<int>& vMeshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
+{
+  std::set<int> levsInput(vMeshDimRelToMaxExt.begin(),vMeshDimRelToMaxExt.end());
+  std::vector<int> levs=getNonEmptyLevelsExt();
+  std::set<int> levs2(levs.begin(),levs.end());
+  std::vector<int> levsToTest;
+  std::set_difference(levs2.begin(),levs2.end(),levsInput.begin(),levsInput.end(),std::back_insert_iterator< std::vector<int> >(levsToTest));
+  std::set<int> famIds2(famIds.begin(),famIds.end());
+  bool ret=true;
+  int maxFamId=1;
+  if(!_families.empty())
+    maxFamId=getMaxFamilyId()+1;
+  std::vector<std::string> allFams=getFamiliesNames();
+  for(std::vector<int>::const_iterator it=levsToTest.begin();it!=levsToTest.end();it++)
+    {
+      const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(*it);
+      if(fieldFamIds)
+        {
+          std::set<int> famIds3=fieldFamIds->getDifferentValues();
+          std::vector<int> tmp;
+          std::set_intersection(famIds3.begin(),famIds3.end(),famIds2.begin(),famIds2.end(),std::back_insert_iterator< std::vector<int> >(tmp));
+          for(std::vector<int>::const_iterator it2=tmp.begin();it2!=tmp.end();it2++)
+            {
+              ret=false;
+              std::string famName=getFamilyNameGivenId(*it2);
+              std::ostringstream oss; oss << "Family_" << maxFamId;
+              std::string zeName=CreateNameNotIn(oss.str(),allFams);
+              addFamilyOnAllGroupsHaving(famName.c_str(),zeName.c_str());
+              _families[zeName]=maxFamId;
+              (const_cast<DataArrayInt *>(fieldFamIds))->changeValue(*it2,maxFamId);
+              maxFamId++;
+            }
+        }
+    }
+  return ret;
+}
+
+/*!
+ * This method add into the family list of a group 'grpName' the family with name 'famName'.
+ * If the group 'grpName' does not exist it is created and 'famName' is added to the list.
+ * If the group 'grpName' already exists, 'famName' will be added into family list of the existing group.
+ * This method throws an INTERP_KERNEL::Exception if 'famName' does not exit.
+ */
+void MEDFileMesh::addFamilyOnGrp(const char *grpName, const char *famName) throw(INTERP_KERNEL::Exception)
 {
   std::string grpn(grpName);
   std::string famn(famName);
   if(grpn.empty() || famn.empty())
-    throw INTERP_KERNEL::Exception("MEDFileMesh::addGrpOnFamily : input strings must be non null !");
+    throw INTERP_KERNEL::Exception("MEDFileMesh::addFamilyOnGrp : input strings must be non null !");
+  std::vector<std::string> fams=getFamiliesNames();
+  if(std::find(fams.begin(),fams.end(),famn)==fams.end())
+    {
+      std::ostringstream oss; oss << "MEDFileMesh::addFamilyOnGrp : Family \"" << famn << "\" does not exist !" << std::endl;
+      oss << "Create this family or choose an existing one ! Existing fams are : ";
+      std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," ")); oss << ".";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(grpn);
   if(it==_groups.end())
     {
@@ -592,6 +699,56 @@ void MEDFileMesh::addGrpOnFamily(const char *grpName, const char *famName) throw
     }
 }
 
+/*!
+ * This method adds to all groups lying on family with name 'famName' the other family name 'otherFamName'.
+ * This method is quite underground because it can lead to unconsistency because family 'otherFamName' is \b not added into _families.
+ * This method is used by MEDFileMesh::keepFamIdsOnlyOnLevs method.
+ */
+void MEDFileMesh::addFamilyOnAllGroupsHaving(const char *famName, const char *otherFamName) throw(INTERP_KERNEL::Exception)
+{
+  std::string famNameCpp(famName);
+  std::string otherCpp(otherFamName);
+  for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
+    {
+      std::vector<std::string>& v=(*it).second;
+      if(std::find(v.begin(),v.end(),famNameCpp)!=v.end())
+        {
+          v.push_back(otherCpp);
+        }
+    }
+}
+
+/*!
+ * If it exists a family whose family id is equal to 'id' this method behaves as MEDFileMesh::getFamilyNameGivenId.
+ * In this case, 'this' internal states remains unchanged and 'created' out parameter will be set to false.
+ * If there is no family whose family id is equal to 'id' a family is created with a name different from those
+ * already existing. In this case 'created' will be returned with a value set to true, and internal state
+ * will be modified.
+ * This method will throws an exception if it is not possible to create a unique family name.
+ */
+std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created) throw(INTERP_KERNEL::Exception)
+{
+  std::vector<std::string> famAlreadyExisting(_families.size());
+  int ii=0;
+  for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++,ii++)
+    {
+      if((*it).second!=id)
+        {
+          famAlreadyExisting[ii]=(*it).first;
+        }
+      else
+        {
+          created=false;
+          return (*it).first;
+        }
+    }
+  created=true;
+  std::ostringstream oss; oss << "Family_" << id;
+  std::string ret=CreateNameNotIn(oss.str(),famAlreadyExisting);
+  _families[ret]=id;
+  return ret;
+}
+
 void MEDFileMesh::setFamilyInfo(const std::map<std::string,int>& info)
 {
   _families=info;
@@ -796,6 +953,44 @@ void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vect
     std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus<int>(),offset));
 }
 
+/*!
+ * Warning no check is done on 'nameTry' in parameter. It should be non empty.
+ * This method returns a name close to 'nameTry' so that it is not already into 'namesToAvoid'.
+ * If this method fails to find such a name it will throw an exception.
+ */
+std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector<std::string>& namesToAvoid) throw(INTERP_KERNEL::Exception)
+{
+  //attempt #0
+  if(std::find(namesToAvoid.begin(),namesToAvoid.end(),nameTry)==namesToAvoid.end())
+    return nameTry;
+  //attempt #1
+  std::size_t len=nameTry.length();
+  for(std::size_t ii=1;ii<len;ii++)
+    {
+      std::string tmp=nameTry.substr(ii,len-ii);
+      if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp)==namesToAvoid.end())
+        return tmp;
+    }
+  //attempt #2
+  if(len>=1)
+    {
+      for(std::size_t i=1;i<30;i++)
+        {
+          std::string tmp1(nameTry.at(0),i);
+          tmp1+=nameTry;
+          if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp1)==namesToAvoid.end())
+            return tmp1;
+        }
+    }
+  //attempt #3
+  std::string tmp2;
+  for(std::vector<std::string>::const_iterator it2=namesToAvoid.begin();it2!=namesToAvoid.end();it2++)
+    tmp2+=(*it2);
+  if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp2)==namesToAvoid.end())
+    return tmp2;
+  throw INTERP_KERNEL::Exception("MEDFileMesh::CreateNameNotIn : impossible to find a not already used name !");
+}
+
 /*!
  * This method should be called by any set* method of subclasses to deal automatically with _name attribute.
  * If _name attribute is empty the name of 'm' if taken as _name attribute.
@@ -1525,11 +1720,6 @@ void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception)
     _groups.erase(*it);
 }
 
-void MEDFileUMesh::setFamilyField(DataArrayInt *arr, const std::vector< std::vector< int > > &userfids, const std::vector<std::string>& grpNames, bool renum) throw(INTERP_KERNEL::Exception)
-{
-  
-}
-
 void MEDFileUMesh::addNodeGroup(const std::string& name, const std::vector<int>& ids) throw(INTERP_KERNEL::Exception)
 {
   const DataArrayDouble *coords=_coords;
@@ -1707,6 +1897,9 @@ void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
       (*it)->synchronizeTinyInfo(*this);
 }
 
+/*!
+ * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
+ */
 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
 {
   DataArrayInt *arr=_fam_coords;
index 99bb2ba25ccecfb31c5451e946304179b4508c26..f25b1ef0e09eca73b72514c79766c95defb6339b 100644 (file)
@@ -60,11 +60,15 @@ namespace ParaMEDMEM
     //
     bool areFamsEqual(const MEDFileMesh *other, std::string& what) const;
     bool areGrpsEqual(const MEDFileMesh *other, std::string& what) const;
+    bool existsGroup(const char *groupName) const;
     bool existsFamily(int famId) const;
     bool existsFamily(const char *familyName) const;
     void setFamilyId(const char *familyName, int id);
     virtual void addFamily(const char *familyName, int id) throw(INTERP_KERNEL::Exception);
-    void addGrpOnFamily(const char *grpName, const char *famName) throw(INTERP_KERNEL::Exception);
+    virtual void createGroupOnAll(int meshDimRelToMaxExt, const char *groupName) throw(INTERP_KERNEL::Exception);
+    virtual bool keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception);
+    void addFamilyOnGrp(const char *grpName, const char *famName) throw(INTERP_KERNEL::Exception);
+    std::string findOrCreateAndGiveFamilyWithId(int id, bool& created) throw(INTERP_KERNEL::Exception);
     void setFamilyInfo(const std::map<std::string,int>& info);
     void setGroupInfo(const std::map<std::string, std::vector<std::string> >&info);
     void copyFamGrpMapsFrom(const MEDFileMesh& other);
@@ -109,6 +113,7 @@ namespace ParaMEDMEM
     virtual DataArrayInt *getNodeFamiliesArr(const std::vector<std::string>& fams, bool renum=false) const throw(INTERP_KERNEL::Exception);
   protected:
     MEDFileMesh();
+    void addFamilyOnAllGroupsHaving(const char *famName, const char *otherFamName) throw(INTERP_KERNEL::Exception);
     virtual void writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) = 0;
     void dealWithTinyInfo(const MEDCouplingMesh *m) throw(INTERP_KERNEL::Exception);
     virtual void synchronizeTinyInfoOnLeaves() const = 0;
@@ -116,6 +121,7 @@ namespace ParaMEDMEM
     virtual void appendFamilyEntries(const std::set<int>& famIds, const std::vector< std::vector<int> >& fidsOfGrps, const std::vector<std::string>& grpNames);
     virtual void changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception) = 0;
     static void TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vector< std::vector<int> >& famIdsPerGrp);
+    static std::string CreateNameNotIn(const std::string& nameTry, const std::vector<std::string>& namesToAvoid) throw(INTERP_KERNEL::Exception);
   protected:
     int _order;
     int _iteration;
@@ -177,7 +183,6 @@ namespace ParaMEDMEM
     void setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception);
     void setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception);
     void eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception);
-    void setFamilyField(DataArrayInt *arr, const std::vector< std::vector< int > > &userfids, const std::vector<std::string>& grpNames, bool renum=false) throw(INTERP_KERNEL::Exception);
     void setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception);
     void setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception);
     void addNodeGroup(const std::string& name, const std::vector<int>& ids) throw(INTERP_KERNEL::Exception);
index e3d52a0636becf89f519bd62571ad34f14c2ec2d..d0903d3c3ba7cf1ff5a7a3181c1e102c87f2def5 100644 (file)
@@ -335,11 +335,14 @@ namespace ParaMEDMEM
     void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception);
     int getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception);
     //
+    bool existsGroup(const char *groupName) const;
     bool existsFamily(int famId) const;
     bool existsFamily(const char *familyName) const;
     void setFamilyId(const char *familyName, int id);
     void addFamily(const char *familyName, int id) throw(INTERP_KERNEL::Exception);
-    void addGrpOnFamily(const char *grpName, const char *famName) 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);
+    virtual bool keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception);
     void copyFamGrpMapsFrom(const MEDFileMesh& other);
     const std::map<std::string,int>& getFamilyInfo() const;
     const std::map<std::string, std::vector<std::string> >& getGroupInfo() const;
@@ -448,6 +451,16 @@ namespace ParaMEDMEM
              tmp->incrRef();
            return SWIG_NewPointerObj(SWIG_as_voidptr(tmp),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 );
          }
+
+         PyObject *findOrCreateAndGiveFamilyWithId(int id, bool& created) throw(INTERP_KERNEL::Exception)
+         {
+           bool ret1;
+           std::string ret0=self->findOrCreateAndGiveFamilyWithId(id,ret1);
+           PyObject *ret=PyTuple_New(2);
+           PyTuple_SetItem(ret,0,PyString_FromString(ret0.c_str()));
+           PyTuple_SetItem(ret,1,SWIG_From_bool(ret1));
+           return ret;
+         }
        }
   };
 
@@ -490,7 +503,6 @@ namespace ParaMEDMEM
     void setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception);
     void setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception);
     void eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception);
-    void setFamilyField(DataArrayInt *arr, const std::vector< std::vector< int > > &userfids, const std::vector<std::string>& grpNames, bool renum=false) throw(INTERP_KERNEL::Exception);
     void addNodeGroup(const std::string& name, const std::vector<int>& ids) throw(INTERP_KERNEL::Exception);
     void removeMeshAtLevel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception);
     void setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld=false) throw(INTERP_KERNEL::Exception);
index 08b84a70bac6ae8e5320f094a3e07d0e89070371..15f3afaf815bed5dc49d6cce442fe138af87457c 100644 (file)
@@ -145,6 +145,7 @@ class MEDLoaderTest(unittest.TestCase):
         g2_N.setValues(range(9),9,1)
         g2_N.setName("G2")
         mm.setGroupsAtLevel(1,[g1_N,g2_N],False)
+        mm.createGroupOnAll(0,"GrpOnAllCell")
         # check content of mm
         t=mm.getGroupArr(0,"G1",False)
         self.assertTrue(g1_2.isEqual(t));
@@ -158,6 +159,9 @@ class MEDLoaderTest(unittest.TestCase):
         self.assertTrue(g1_N.isEqual(t));
         t=mm.getGroupArr(1,"G2",False)
         self.assertTrue(g2_N.isEqual(t));
+        self.assertTrue(mm.existsGroup("GrpOnAllCell"));
+        t=mm.getGroupArr(0,"GrpOnAllCell")
+        self.assertTrue(t.getValues()==range(5))
         #
         mm.write(outFileName,2);
         #
@@ -252,11 +256,28 @@ class MEDLoaderTest(unittest.TestCase):
         self.assertTrue(g1_1.isEqual(t));
         t=mm.getGroupArr(-1,"G2",True)
         self.assertTrue(g2_1.isEqual(t));
+        self.assertTrue(not mm.existsGroup("GrpOnAllCell"));
         #
         mm.write(outFileName,2);
         mm2=MEDFileMesh.New(outFileName)
         res=mm.isEqual(mm2,1e-12)
         self.assertTrue(res[0])
+        l=list(mm2.getFamiliesOnGroup("G2")) ; l.sort()
+        self.assertEqual(['Family_10','Family_11','Family_3','Family_4','Family_7'],l)
+        mm2.keepFamIdsOnlyOnLevs([3],[-1])
+        for lev in mm.getGrpNonEmptyLevelsExt("G2"):
+            self.assertEqual(mm.getGroupArr(lev,"G2").getValues(),mm2.getGroupArr(lev,"G2").getValues())
+            pass
+        l=list(mm2.getFamiliesOnGroup("G2")) ; l.sort()
+        self.assertEqual(['Family_10','Family_11','Family_12','Family_3','Family_4','Family_7'],l)
+        #
+        self.assertEqual([7,7,6],mm2.getFamilyFieldAtLevel(-1).getValues())
+        mm2.getFamilyFieldAtLevel(-1).setIJ(1,0,8)
+        self.assertEqual([7,8,6],mm2.getFamilyFieldAtLevel(-1).getValues())
+        self.assertTrue(not mm2.existsFamily("Family_8"))
+        mm2.createGroupOnAll(-1,"GrpOnAllFace")
+        self.assertTrue(mm2.existsFamily("Family_8"))
+        self.assertEqual(range(3),mm2.getGroupArr(-1,"GrpOnAllFace").getValues())
         pass
 
     #testing persistence of retrieved arrays