Salome HOME
Merge branch 'master' of https://codev-tuleap.cea.fr/plugins/git/salome/medcoupling
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
index a496d0cd1454a73a83eefd46e89bca9e4c70aa12..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.
  */
@@ -1706,7 +1706,7 @@ int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, in
  * \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 correspondance array old to new in a newly allocated array.
+ * \return the correspondence array old to new in a newly allocated array.
  * 
  */
 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
@@ -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);
@@ -5928,7 +5985,7 @@ DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::Norma
 /*!
  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
  *
- * \return a new object containing the old to new correspondance.
+ * \return a new object containing the old to new correspondence.
  *
  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
  */
@@ -5957,7 +6014,7 @@ DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INT
  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
  *
- * \return the array giving the correspondance old to new.
+ * \return the array giving the correspondence old to new.
  */
 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
 {