]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
Duplication of nodes along submesh.
authorageay <ageay>
Fri, 8 Jun 2012 15:22:56 +0000 (15:22 +0000)
committerageay <ageay>
Fri, 8 Jun 2012 15:22:56 +0000 (15:22 +0000)
src/MEDCoupling/MEDCouplingUMesh.cxx
src/MEDCoupling/MEDCouplingUMesh.hxx
src/MEDCoupling_Swig/MEDCoupling.i

index 685ecbf96b0c15d11f3f165b78f11f2ef650f387..45da23b4535dc3e20b0a9a6d079ef2bc32032f5f 100644 (file)
@@ -966,13 +966,39 @@ void MEDCouplingUMesh::unPolyze()
   computeTypes();
 }
 
+/*!
+ * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
+ * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
+ * the format of returned DataArrayInt instance.
+ * 
+ * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
+ * \sa MEDCouplingUMesh::getNodeIdsInUse
+ */
+DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
+{
+  checkFullyDefined();
+  std::set<int> retS;
+  int nbOfCells=getNumberOfCells();
+  const int *connIndex=_nodal_connec_index->getConstPointer();
+  const int *conn=_nodal_connec->getConstPointer();
+  for(int i=0;i<nbOfCells;i++)
+    for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
+      if(conn[j]>=0)
+        retS.insert(conn[j]);
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc((int)retS.size(),1);
+  std::copy(retS.begin(),retS.end(),ret->getPointer());
+  return ret;
+}
+
 /*!
  * Array returned is the correspondance in \b old \b to \b new format (that's why 'nbrOfNodesInUse' is returned too).
  * The returned array is newly created and should be dealt by the caller.
  * To retrieve the new to old format the user can use DataArrayInt::invertArrayO2N2N2O method.
  * The size of returned array is the number of nodes of 'this'.
  * -1 values in returned array means that the corresponding node never appear in any nodal connectivity of cells constituting 'this'.
- * @param nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
+ * @param [out] nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
+ * @return a newly allocated DataArrayInt that tells for each nodeid in \b this if it is unused (-1) or used (the corresponding new id)
  */
 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
 {
@@ -984,7 +1010,7 @@ DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const thro
   std::fill(traducer,traducer+nbOfNodes,-1);
   int nbOfCells=getNumberOfCells();
   const int *connIndex=_nodal_connec_index->getConstPointer();
-  int *conn=_nodal_connec->getPointer();
+  const int *conn=_nodal_connec->getConstPointer();
   for(int i=0;i<nbOfCells;i++)
     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
       if(conn[j]>=0)
@@ -1012,7 +1038,7 @@ DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Excepti
  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
  */
-bool MEDCouplingUMesh::areCellsEqual(int cell1, int cell2, int compType) const
+int MEDCouplingUMesh::areCellsEqual(int cell1, int cell2, int compType) const
 {
   switch(compType)
     {
@@ -1022,6 +1048,8 @@ bool MEDCouplingUMesh::areCellsEqual(int cell1, int cell2, int compType) const
       return areCellsEqual1(cell1,cell2);
     case 2:
       return areCellsEqual2(cell1,cell2);
+    case 7:
+      return areCellsEqual7(cell1,cell2);
     }
   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1 or 2.");
 }
@@ -1029,19 +1057,19 @@ bool MEDCouplingUMesh::areCellsEqual(int cell1, int cell2, int compType) const
 /*!
  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
  */
-bool MEDCouplingUMesh::areCellsEqual0(int cell1, int cell2) const
+int MEDCouplingUMesh::areCellsEqual0(int cell1, int cell2) const
 {
   const int *conn=getNodalConnectivity()->getConstPointer();
   const int *connI=getNodalConnectivityIndex()->getConstPointer();
   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
-    return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1);
-  return false;
+    return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
+  return 0;
 }
 
 /*!
  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
  */
-bool MEDCouplingUMesh::areCellsEqual1(int cell1, int cell2) const
+int MEDCouplingUMesh::areCellsEqual1(int cell1, int cell2) const
 {
   const int *conn=getNodalConnectivity()->getConstPointer();
   const int *connI=getNodalConnectivityIndex()->getConstPointer();
@@ -1062,22 +1090,22 @@ bool MEDCouplingUMesh::areCellsEqual1(int cell1, int cell2) const
                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
                   work=std::search(tmp,tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
                   delete [] tmp;
-                  return work!=tmp+sz1;
+                  return work!=tmp+sz1?1:0;
                 }
               else
-                return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1);//case of SEG2 and SEG3
+                return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
             }
           else
             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areCellsEqual1 : not implemented yet for meshdim == 3 !");
         }
     }
-  return false;
+  return 0;
 }
 
 /*!
  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
  */
-bool MEDCouplingUMesh::areCellsEqual2(int cell1, int cell2) const
+int MEDCouplingUMesh::areCellsEqual2(int cell1, int cell2) const
 {
   const int *conn=getNodalConnectivity()->getConstPointer();
   const int *connI=getNodalConnectivityIndex()->getConstPointer();
@@ -1087,12 +1115,86 @@ bool MEDCouplingUMesh::areCellsEqual2(int cell1, int cell2) const
         {
           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
-          return s1==s2;
+          return s1==s2?1:0;
+        }
+    }
+  return 0;
+}
+
+/*!
+ * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
+ */
+int MEDCouplingUMesh::areCellsEqual7(int cell1, int cell2) const
+{
+  const int *conn=getNodalConnectivity()->getConstPointer();
+  const int *connI=getNodalConnectivityIndex()->getConstPointer();
+  int sz=connI[cell1+1]-connI[cell1];
+  if(sz==connI[cell2+1]-connI[cell2])
+    {
+      if(conn[connI[cell1]]==conn[connI[cell2]])
+        {
+          const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
+          unsigned dim=cm.getDimension();
+          if(dim!=3)
+            {
+              if(dim!=1)
+                {
+                  int sz1=2*(sz-1);
+                  int *tmp=new int[sz1];
+                  int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],tmp);
+                  std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
+                  work=std::search(tmp,tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
+                  if(work!=tmp+sz1)
+                    {
+                      delete [] tmp;
+                      return 1;
+                    }
+                  else
+                    {
+                      std::reverse_iterator<int *> it1(tmp+sz1);
+                      std::reverse_iterator<int *> it2(tmp);
+                      if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
+                        {
+                          delete [] tmp;
+                          return 2;
+                        }
+                      else
+                        {
+                          delete [] tmp;
+                          return 0;
+                        }
+                    }
+                  
+                  return work!=tmp+sz1?1:0;
+                }
+              else
+                {//case of SEG2 and SEG3
+                  if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
+                    return 1;
+                  if(!cm.isQuadratic())
+                    {
+                      std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
+                      std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
+                      if(std::equal(it1,it2,conn+connI[cell2]+1))
+                        return 2;
+                      return 0;
+                    }
+                  else
+                    {
+                      if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
+                        return 2;
+                      return 0;
+                    }
+                }
+            }
+          else
+            throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areCellsEqual7 : not implemented yet for meshdim == 3 !");
         }
     }
-  return false;
+  return 0;
 }
 
+
 /*!
  * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
  * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
@@ -1134,22 +1236,23 @@ bool MEDCouplingUMesh::areCellsEqualInPool(const std::vector<int>& candidates, i
   cand.erase(-1);
   if(cand.size()<=1)
     return false;
-  std::set<int>::const_iterator end=cand.end(); end--;
   bool ret=false;
-  for(std::set<int>::const_iterator iter=cand.begin();iter!=end && !ret;iter++)
+  std::set<int>::const_iterator iter=cand.begin();
+  int start=(*iter++);
+  for(;iter!=cand.end();iter++)
     {
-      std::set<int>::const_iterator begin2=iter; begin2++;
-      for(std::set<int>::const_iterator iter2=begin2;iter2!=cand.end();iter2++)
+      int status=areCellsEqual(start,*iter,compType);
+      if(status!=0)
         {
-          if(areCellsEqual(*iter,*iter2,compType))
+          if(!ret)
             {
-              if(!ret)
-                {
-                  result.push_back(*iter);
-                  ret=true;
-                }
-              result.push_back(*iter2);
+              result.push_back(start);
+              ret=true;
             }
+          if(status==1)
+            result.push_back(*iter);
+          else
+            result.push_back(status==2?(*iter+1):-(*iter+1));
         }
     }
   return ret;
@@ -1316,6 +1419,71 @@ bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int com
   return arr->getMaxValue(tmp)<nbOfCells;
 }
 
+/*!
+ * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
+ * This method tries to determine if \b other is fully included in \b this.
+ * The main difference is that this method is not expected to throw exception.
+ * This method has two outputs :
+ *
+ * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
+ * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
+ */
+bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
+  int spaceDim=mesh->getSpaceDimension();
+  std::vector<int> commonCells;
+  std::vector<int> commonCellsI;
+  switch(spaceDim)
+    {
+    case 3:
+      {
+        findCommonCellsBase<3>(7,commonCells,commonCellsI);
+        break;
+      }
+    case 2:
+      {
+        findCommonCellsBase<2>(7,commonCells,commonCellsI);
+        break;
+      }
+    case 1:
+      {
+        findCommonCellsBase<1>(7,commonCells,commonCellsI);
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("Invalid spaceDimension : must be 1, 2 or 3.");
+    }
+  int thisNbCells=getNumberOfCells();
+  int otherNbCells=other->getNumberOfCells();
+  int nbOfCells=mesh->getNumberOfCells();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
+  arr2->alloc(otherNbCells,1);
+  arr2->fillWithZero();
+  int *arr2Ptr=arr2->getPointer();
+  int nbOfCommon=(int)commonCellsI.size()-1;
+  for(int i=0;i<nbOfCommon;i++)
+    {
+      int start=commonCells[commonCellsI[i]];
+      if(start<thisNbCells)
+        {
+          for(int j=commonCellsI[i]+1;j!=commonCellsI[i+1];j++)
+            {
+              int sig=commonCells[j]>0?1:-1;
+              int val=std::abs(commonCells[j])-1;
+              if(val>=thisNbCells)
+                arr2Ptr[val-thisNbCells]=sig*(start+1);
+            }
+        }
+    }
+  arr2->setName(other->getName());
+  if(arr2->presenceOfValue(0))
+    return false;
+  arr=arr2;
+  arr2->incrRef();
+  return true;
+}
+
 /*!
  * @param areNodesMerged if at least two nodes have been merged.
  * @return old to new node correspondance.
index 6077e64dcd44a9a7c31c2c1a8c309675065c716a..1db439bcc02dfe3e8377e20c74db136e65fb65aa 100644 (file)
@@ -88,19 +88,22 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT std::string getVTKDataSetType() const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception);
     //tools
-    MEDCOUPLING_EXPORT bool areCellsEqual(int cell1, int cell2, int compType) const;
-    MEDCOUPLING_EXPORT bool areCellsEqual0(int cell1, int cell2) const;
-    MEDCOUPLING_EXPORT bool areCellsEqual1(int cell1, int cell2) const;
-    MEDCOUPLING_EXPORT bool areCellsEqual2(int cell1, int cell2) const;
+    MEDCOUPLING_EXPORT int areCellsEqual(int cell1, int cell2, int compType) const;
+    MEDCOUPLING_EXPORT int areCellsEqual0(int cell1, int cell2) const;
+    MEDCOUPLING_EXPORT int areCellsEqual1(int cell1, int cell2) const;
+    MEDCOUPLING_EXPORT int areCellsEqual2(int cell1, int cell2) const;
+    MEDCOUPLING_EXPORT int areCellsEqual7(int cell1, int cell2) const;
     MEDCOUPLING_EXPORT bool areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const;
     MEDCOUPLING_EXPORT void convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd);
     MEDCOUPLING_EXPORT void convertAllToPoly();
     MEDCOUPLING_EXPORT void convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void unPolyze();
+    MEDCOUPLING_EXPORT DataArrayInt *computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT DataArrayInt *getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT DataArrayInt *zipCoordsTraducer() throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT DataArrayInt *zipConnectivityTraducer(int compType) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT bool areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT bool areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT MEDCouplingUMesh *buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT MEDCouplingUMesh *buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception);
index bdfaf736838fcc67e5d6440610df22cb940a0c32..3a007ff18c625d298b5fee798537dc396163bcdd 100644 (file)
@@ -257,6 +257,7 @@ using namespace INTERP_KERNEL;
 %newobject ParaMEDMEM::MEDCouplingUMesh::rearrange2ConsecutiveCellTypes;
 %newobject ParaMEDMEM::MEDCouplingUMesh::sortCellsInMEDFileFrmt;
 %newobject ParaMEDMEM::MEDCouplingUMesh::convertCellArrayPerGeoType;
+%newobject ParaMEDMEM::MEDCouplingUMesh::computeFetchedNodeIds;
 %newobject ParaMEDMEM::MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec;
 %newobject ParaMEDMEM::MEDCouplingUMesh::buildDirectionVectorField;
 %newobject ParaMEDMEM::MEDCouplingUMesh::getEdgeRatioField;
@@ -1066,6 +1067,7 @@ namespace ParaMEDMEM
     DataArrayInt *rearrange2ConsecutiveCellTypes() throw(INTERP_KERNEL::Exception);
     DataArrayInt *sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception);
     DataArrayInt *convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception);
+    DataArrayInt *computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception);
     DataArrayInt *zipConnectivityTraducer(int compType) throw(INTERP_KERNEL::Exception);
     MEDCouplingUMesh *buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception);
     MEDCouplingUMesh *buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception);
@@ -1402,6 +1404,18 @@ namespace ParaMEDMEM
         return ret;
       }
 
+      PyObject *areCellsIncludedIn2(const MEDCouplingUMesh *other) const throw(INTERP_KERNEL::Exception)
+      {
+        DataArrayInt *ret1;
+        bool ret0=self->areCellsIncludedIn2(other,ret1);
+        PyObject *ret=PyTuple_New(2);
+        PyObject *ret0Py=ret0?Py_True:Py_False;
+        Py_XINCREF(ret0Py);
+        PyTuple_SetItem(ret,0,ret0Py);
+        PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 ));
+        return ret;
+      }
+
       PyObject *buildDescendingConnectivity() const throw(INTERP_KERNEL::Exception)
       {
         MEDCouplingAutoRefCountObjectPtr<DataArrayInt> d0=DataArrayInt::New();