Salome HOME
Bug with FindClosestTupleIdAlg fixed (preventing the threshold to be null)
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
index 05eaf2661ff20381fc6c6d5738560d04e8cd5249..a890398e76df2b7f2822927b956d4c1d0cc6c2a0 100755 (executable)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -47,6 +47,7 @@
 #include <sstream>
 #include <fstream>
 #include <numeric>
+#include <memory>
 #include <cstring>
 #include <limits>
 #include <list>
@@ -56,8 +57,8 @@ using namespace MEDCoupling;
 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
 
 /// @cond INTERNAL
+
 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_PENTA18, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
-const mcIdType MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,32,-1,25,42,36,4};
 /// @endcond
 
 MEDCouplingUMesh *MEDCouplingUMesh::New()
@@ -1245,7 +1246,7 @@ bool MEDCouplingUMesh::unPolyze()
       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
-      mcIdType newLgth;
+      mcIdType newLgth=0;
       if(cm.isDynamic())
         {
           switch(cm.getDimension())
@@ -1264,11 +1265,12 @@ bool MEDCouplingUMesh::unPolyze()
                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
                 break;
               }
-            case 1:
+         /*   case 1:  // Not supported yet
               {
                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
                 break;
               }
+         */
           }
           ret=ret || (newType!=type);
           conn[newPos]=newType;
@@ -1662,8 +1664,6 @@ int MEDCouplingUMesh::AreCellsEqualPolicy7(const mcIdType *conn, const mcIdType
                       else
                         return 0;
                     }
-
-                  return work!=tmp+sz1?1:0;
                 }
               else
                 {//case of SEG2 and SEG3
@@ -1694,9 +1694,11 @@ int MEDCouplingUMesh::AreCellsEqualPolicy7(const mcIdType *conn, const mcIdType
 
 
 /*!
- * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
- * by \a compType.
- * This method keeps the coordiantes of \a this. This method is time consuming.
+ * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified by \a compType (see zipConnectivityTraducer).
+ * This method keeps the coordinates of \a this. The comparison starts at rank \a startCellId cell id (included).
+ * If \a startCellId is equal to 0 algorithm starts at cell #0 and for each cell candidates being searched have cell id higher than current cellId.
+ * If \a startCellId is greater than 0 algorithm starts at cell #startCellId but for each cell all candidates are considered.
+ * This method is time consuming.
  *
  * \param [in] compType input specifying the technique used to compare cells each other.
  *   - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
@@ -1707,7 +1709,6 @@ int MEDCouplingUMesh::AreCellsEqualPolicy7(const mcIdType *conn, const mcIdType
  * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
- * \return the correspondence array old to new in a newly allocated array.
  *
  */
 void MEDCouplingUMesh::findCommonCells(int compType, mcIdType startCellId, DataArrayIdType *& commonCellsArr, DataArrayIdType *& commonCellsIArr) const
@@ -1728,7 +1729,7 @@ void MEDCouplingUMesh::FindCommonCellsAlg(int compType, mcIdType startCellId, co
   std::vector<bool> isFetched(nbOfCells,false);
   if(startCellId==0)
     {
-      for(mcIdType i=0;i<nbOfCells;i++)
+      for(mcIdType i=startCellId;i<nbOfCells;i++)
         {
           if(!isFetched[i])
             {
@@ -1768,6 +1769,7 @@ void MEDCouplingUMesh::FindCommonCellsAlg(int compType, mcIdType startCellId, co
           if(!isFetched[i])
             {
               const mcIdType *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<mcIdType>(),-1));
+              // v2 contains the result of successive intersections using rev nodal on on each node of cell #i
               std::vector<mcIdType> v,v2;
               if(connOfNode!=connPtr+connIPtr[i+1])
                 {
@@ -1781,12 +1783,20 @@ void MEDCouplingUMesh::FindCommonCellsAlg(int compType, mcIdType startCellId, co
                     std::vector<mcIdType>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
                     v2.resize(std::distance(v2.begin(),it));
                   }
+              // v2 contains now candidates. Problem candidates are sorted using id rank.
               if(v2.size()>1)
                 {
+                  if(v2[0]!=i)
+                  {
+                    auto it(std::find(v2.begin(),v2.end(),i));
+                    std::swap(*v2.begin(),*it);
+                  }
                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
                     {
-                      mcIdType pos=commonCellsI->back();
-                      commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
+                      mcIdType newPos(commonCells->getNumberOfTuples());
+                      mcIdType pos(commonCellsI->back());
+                      std::sort(commonCells->getPointerSilent()+pos,commonCells->getPointerSilent()+newPos);
+                      commonCellsI->pushBackSilent(newPos);
                       for(const mcIdType *it=commonCells->begin()+pos;it!=commonCells->end();it++)
                         isFetched[*it]=true;
                     }
@@ -1834,13 +1844,30 @@ bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int com
       oss << " !";
       throw INTERP_KERNEL::Exception(oss.str());
     }
-  MCAuto<DataArrayIdType> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
-  arr=o2n->subArray(nbOfCells);
-  arr->setName(other->getName());
-  mcIdType tmp;
+  //
   if(other->getNumberOfCells()==0)
+  {
+    MCAuto<DataArrayIdType> dftRet(DataArrayIdType::New()); dftRet->alloc(0,1); arr=dftRet.retn(); arr->setName(other->getName());
     return true;
-  return arr->getMaxValue(tmp)<nbOfCells;
+  }
+  DataArrayIdType *commonCells(nullptr),*commonCellsI(nullptr);
+  mesh->findCommonCells(compType,nbOfCells,commonCells,commonCellsI);
+  MCAuto<DataArrayIdType> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
+  mcIdType newNbOfCells=-1;
+  MCAuto<DataArrayIdType> o2n = DataArrayIdType::ConvertIndexArrayToO2N(ToIdType(mesh->getNumberOfCells()),commonCells->begin(),commonCellsI->begin(),commonCellsI->end(),newNbOfCells);
+  MCAuto<DataArrayIdType> p0(o2n->selectByTupleIdSafeSlice(0,nbOfCells,1));
+  mcIdType maxPart(p0->getMaxValueInArray());
+  bool ret(maxPart==newNbOfCells-1);
+  MCAuto<DataArrayIdType> p1(p0->invertArrayO2N2N2O(newNbOfCells));
+  // fill p1 array in case of presence of cells in other not in this
+  mcIdType *pt(p1->getPointer());
+  for(mcIdType i = maxPart ; i < newNbOfCells-1 ; ++i )
+    pt[i+1] = i+1;
+  //
+  MCAuto<DataArrayIdType> p2(o2n->subArray(nbOfCells));
+  p2->transformWithIndArr(p1->begin(),p1->end()); p2->setName(other->getName());
+  arr = p2.retn();
+  return ret;
 }
 
 /*!
@@ -1906,9 +1933,9 @@ MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplin
  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
  * cellIds is not given explicitly but by a range python like.
  *
- * \param start
- * \param end
- * \param step
+ * \param start starting ID
+ * \param end end ID (excluded)
+ * \param step step size
  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
  * \return a newly allocated
  *
@@ -2203,7 +2230,7 @@ DataArrayIdType *MEDCouplingUMesh::findCellIdsOnBoundary() const
  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
  *
- * \param [in] otherDimM1OnSameCoords
+ * \param [in] otherDimM1OnSameCoords other mesh
  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
@@ -2609,7 +2636,7 @@ void MEDCouplingUMesh::duplicateNodesInConn(const mcIdType *nodeIdsToDuplicateBg
  * should be contained in[0;this->getNumberOfCells()).
  *
  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
- * \param check
+ * \param check whether to check content of old2NewBg
  */
 void MEDCouplingUMesh::renumberCells(const mcIdType *old2NewBg, bool check)
 {
@@ -3129,9 +3156,9 @@ bool MEDCouplingUMesh::isEmptyMesh(const std::vector<mcIdType>& tinyInfo) const
 /*!
  * Second step of serialization process.
  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
- * \param a1
- * \param a2
- * \param littleStrings
+ * \param a1 DataArrayDouble
+ * \param a2 DataArrayDouble
+ * \param littleStrings string vector
  */
 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<mcIdType>& tinyInfo, DataArrayIdType *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
 {
@@ -3309,8 +3336,8 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) cons
   mcIdType nbNodes=getNumberOfNodes();
   MCAuto<DataArrayDouble> nnpc;
   {
-    MCAuto<DataArrayIdType> tmp(computeNbOfNodesPerCell());
-    nnpc=tmp->convertToDblArr();
+    MCAuto<DataArrayIdType> tmp2(computeNbOfNodesPerCell());
+    nnpc=tmp2->convertToDblArr();
   }
   std::for_each(nnpc->rwBegin(),nnpc->rwEnd(),[](double& v) { v=1./v; });
   const double *nnpcPtr(nnpc->begin());
@@ -5782,7 +5809,7 @@ DataArrayIdType *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vect
  * The result is put in the array \a idsPerType. In the returned parameter \a code, foreach i \a code[3*i+2] refers (if different from -1) to a location into the \a idsPerType.
  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
  *
- * \param [in] profile
+ * \param [in] profile list of IDs constituing the profile
  * \param [out] code is a vector of size 3*n where n is the number of different geometric type in \a this \b reduced to the profile \a profile. \a code has exactly the same semantic than in MEDCouplingUMesh::checkTypeConsistencyAndContig method.
  * \param [out] idsInPflPerType is a vector of size of different geometric type in the subpart defined by \a profile of \a this ( equal to \a code.size()/3). For each i,
  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
@@ -6201,8 +6228,8 @@ DataArrayIdType *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh()
 /*!
  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
- * \param nodalConn
- * \param nodalConnI
+ * \param nodalConn nodal connectivity
+ * \param nodalConnIndex nodal connectivity indices
  */
 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayIdType *&nodalConn, DataArrayIdType *&nodalConnIndex) const
 {
@@ -7160,8 +7187,7 @@ bool MEDCouplingUMesh::IsPyra5WellOriented(const mcIdType *begin, const mcIdType
  *
  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
  * \param [in] coords the coordinates with nb of components exactly equal to 3
- * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
- * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
+ * \param [in] index begin of the nodal connectivity (geometric type included) of a single polyhedron cell
  * \param [out] res the result is put at the end of the vector without any alteration of the data.
  */
 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, mcIdType index, DataArrayIdType *res, MEDCouplingUMesh *faces,
@@ -7335,7 +7361,7 @@ void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(mcIdType *begin, mcIdTy
           nbOfEdgesInFace=std::distance(bgFace,endFace);
           if(!isPerm[i])
             {
-              bool b;
+              bool b=false;
               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
                 {
                   std::pair<mcIdType,mcIdType> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
@@ -7562,7 +7588,10 @@ void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData
           w4=std::copy(c.begin(),c.end(),w4);
         }
     }
-  types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
+  std::unique_ptr<mcIdType[]> medcoupling2vtkTypeTraducer_mcIdType(new mcIdType[MEDCOUPLING2VTKTYPETRADUCER_LGTH]);
+  for(auto ii = 0; ii<MEDCOUPLING2VTKTYPETRADUCER_LGTH ; ++ii)
+    medcoupling2vtkTypeTraducer_mcIdType[ii] = MEDCOUPLING2VTKTYPETRADUCER[ii]!=MEDCOUPLING2VTKTYPETRADUCER_NONE?MEDCOUPLING2VTKTYPETRADUCER[ii] : -1;
+  types->transformWithIndArr(medcoupling2vtkTypeTraducer_mcIdType.get(),medcoupling2vtkTypeTraducer_mcIdType.get()+MEDCOUPLING2VTKTYPETRADUCER_LGTH);
   types->writeVTK(ofs,8,"UInt8","types",byteData);
   std::string vtkTypeName = Traits<mcIdType>::VTKReprStr;
   offsets->writeVTK(ofs,8,vtkTypeName,"offsets",byteData);