Salome HOME
Merge branch 'master' of https://codev-tuleap.cea.fr/plugins/git/salome/medcoupling
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
index 1bb16f76b14af6e8962e49291568bd6e50192e7d..8a0293fd01c6bf82a4aa1a5d5358020414a45aa8 100644 (file)
@@ -404,7 +404,7 @@ MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
 
 /*!
  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
- * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
+ * If \a this is not so that the cells are grouped by geo types, this method will throw an exception.
  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
  * Useful for python users.
  */
@@ -4629,8 +4629,9 @@ bool MEDCouplingUMesh::areOnlySimplexCells() const
 /*!
  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
- * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
- * does \b not perform geometrical checks and checks only nodal connectivity of cells,
+ * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell.
+ * Quadratic cells in 2D are also handled. In those cells edges where start=end=midpoint are removed.
+ * This method does \b not perform geometrical checks and checks only nodal connectivity of cells,
  * so it can be useful to call mergeNodes() before calling this method.
  *  \throw If \a this->getMeshDimension() <= 1.
  *  \throw If the coordinates array is not set.
@@ -4667,6 +4668,62 @@ void MEDCouplingUMesh::convertDegeneratedCells()
   computeTypes();
 }
 
+/*!
+ * Same as MEDCouplingUMesh::convertDegeneratedCells() plus deletion of the flat cells.
+ * A cell is flat in the following cases:
+ *   - for a linear cell, all points in the connectivity are equal
+ *   - for a quadratic cell, either the above, or a quadratic polygon with two (linear) points and two
+ *   identical quadratic points
+ * \return a new instance of DataArrayInt holding ids of removed cells. The caller is to delete
+ *      this array using decrRef() as it is no more needed.
+ */
+DataArrayInt *MEDCouplingUMesh::convertDegeneratedCellsAndRemoveFlatOnes()
+{
+  checkFullyDefined();
+  if(getMeshDimension()<=1)
+    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
+  int nbOfCells=getNumberOfCells();
+  MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
+  if(nbOfCells<1)
+    return ret;
+  int initMeshLgth=getNodalConnectivityArrayLen();
+  int *conn=_nodal_connec->getPointer();
+  int *index=_nodal_connec_index->getPointer();
+  int posOfCurCell=0;
+  int newPos=0;
+  int lgthOfCurCell, nbDelCells(0);
+  for(int i=0;i<nbOfCells;i++)
+    {
+      lgthOfCurCell=index[i+1]-posOfCurCell;
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
+      int newLgth;
+      INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
+                                                                                                     conn+newPos+1,newLgth);
+      // Shall we delete the cell if it is completely degenerated:
+      bool delCell=INTERP_KERNEL::CellSimplify::isFlatCell(conn, newPos, newLgth, newType);
+      if (delCell)
+        {
+          nbDelCells++;
+          ret->pushBackSilent(i);
+        }
+      else   //if the cell is to be deleted, simply stay at the same place
+        {
+          conn[newPos]=newType;
+          newPos+=newLgth+1;
+        }
+      posOfCurCell=index[i+1];
+      index[i+1-nbDelCells]=newPos;
+    }
+  if(newPos!=initMeshLgth)
+    _nodal_connec->reAlloc(newPos);
+  const int nCellDel=ret->getNumberOfTuples();
+  if (nCellDel)
+    _nodal_connec_index->reAlloc(nbOfCells-nCellDel+1);
+  computeTypes();
+  return ret.retn();
+}
+
+
 /*!
  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
  * A cell is considered to be oriented correctly if an angle between its
@@ -5681,7 +5738,7 @@ DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<
  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
  * \throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if \a this is not fully defined
  */
-void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
+void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType, bool smartPflKiller) const
 {
   if(!profile)
     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
@@ -5723,7 +5780,7 @@ void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vec
       code[3*i]=(int)types[castId];
       code[3*i+1]=tmp3->getNumberOfTuples();
       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
-      if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
+      if(!smartPflKiller || !tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
         {
           tmp4->copyStringInfoFrom(*profile);
           idsPerType2.push_back(tmp4);