Salome HOME
Small but useful DataArrayInt::checkUniformAndGuess
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingCMesh.cxx
index 06876f548beb42a6f8d28de3059c66ec859b9621..f640504926209fefa8031892de5c73d5ee22faf5 100644 (file)
@@ -1,9 +1,9 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2016  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
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 #include "MEDCouplingCMesh.hxx"
 #include "MEDCouplingMemArray.hxx"
 #include "MEDCouplingFieldDouble.hxx"
+#include "MEDCouplingCurveLinearMesh.hxx"
+
+#include "InterpKernelAutoPtr.hxx"
 
 #include <functional>
 #include <algorithm>
 #include <sstream>
 #include <numeric>
 
-using namespace ParaMEDMEM;
+using namespace MEDCoupling;
 
 MEDCouplingCMesh::MEDCouplingCMesh():_x_array(0),_y_array(0),_z_array(0)
 {
@@ -38,15 +41,15 @@ MEDCouplingCMesh::MEDCouplingCMesh(const MEDCouplingCMesh& other, bool deepCopy)
   if(deepCopy)
     {
       if(other._x_array)
-        _x_array=other._x_array->deepCpy();
+        _x_array=other._x_array->deepCopy();
       else
         _x_array=0;
       if(other._y_array)
-        _y_array=other._y_array->deepCpy();
+        _y_array=other._y_array->deepCopy();
       else
         _y_array=0;
       if(other._z_array)
-        _z_array=other._z_array->deepCpy();
+        _z_array=other._z_array->deepCopy();
       else
         _z_array=0;
     }
@@ -81,12 +84,12 @@ MEDCouplingCMesh *MEDCouplingCMesh::New()
 
 MEDCouplingCMesh *MEDCouplingCMesh::New(const std::string& meshName)
 {
-  MEDCouplingCMesh *ret=new MEDCouplingCMesh;
+  MEDCouplingCMesh *ret(new MEDCouplingCMesh);
   ret->setName(meshName);
   return ret;
 }
 
-MEDCouplingMesh *MEDCouplingCMesh::deepCpy() const
+MEDCouplingCMesh *MEDCouplingCMesh::deepCopy() const
 {
   return clone(true);
 }
@@ -96,6 +99,25 @@ MEDCouplingCMesh *MEDCouplingCMesh::clone(bool recDeepCpy) const
   return new MEDCouplingCMesh(*this,recDeepCpy);
 }
 
+const DataArrayDouble *MEDCouplingCMesh::getDirectAccessOfCoordsArrIfInStructure() const
+{
+  throw INTERP_KERNEL::Exception("MEDCouplingCMesh::getDirectAccessOfCoordsArrIfInStructure : MEDCouplingCMesh does not aggregate array of coordinates !");
+}
+
+MEDCouplingCurveLinearMesh *MEDCouplingCMesh::buildCurveLinear() const
+{
+  checkConsistencyLight();
+  int dim(getSpaceDimension());
+  MCAuto<MEDCouplingCurveLinearMesh> ret(MEDCouplingCurveLinearMesh::New());
+  ret->MEDCouplingStructuredMesh::operator=(*this);
+  INTERP_KERNEL::AutoPtr<int> ngs(new int[dim]);
+  getNodeGridStructure(ngs);
+  ret->setNodeGridStructure(ngs,ngs+dim);
+  MCAuto<DataArrayDouble> coo(getCoordinatesAndOwner());
+  ret->setCoords(coo);
+  return ret.retn();
+}
+
 void MEDCouplingCMesh::updateTime() const
 {
   if(_x_array)
@@ -111,15 +133,12 @@ std::size_t MEDCouplingCMesh::getHeapMemorySizeWithoutChildren() const
   return MEDCouplingStructuredMesh::getHeapMemorySizeWithoutChildren();
 }
 
-std::vector<const BigMemoryObject *> MEDCouplingCMesh::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDCouplingCMesh::getDirectChildrenWithNull() const
 {
   std::vector<const BigMemoryObject *> ret;
-  if(_x_array)
-    ret.push_back(_x_array);
-  if(_y_array)
-    ret.push_back(_y_array);
-  if(_z_array)
-    ret.push_back(_z_array);
+  ret.push_back(_x_array);
+  ret.push_back(_y_array);
+  ret.push_back(_z_array);
   return ret;
 }
 
@@ -128,11 +147,11 @@ std::vector<const BigMemoryObject *> MEDCouplingCMesh::getDirectChildren() const
  * @throw if other and this have not same mesh type.
  */
 void MEDCouplingCMesh::copyTinyStringsFrom(const MEDCouplingMesh *other)
-{ 
-  const MEDCouplingCMesh *otherC=dynamic_cast<const MEDCouplingCMesh *>(other);
+{
+  MEDCouplingStructuredMesh::copyTinyStringsFrom(other);
+  const MEDCouplingCMesh *otherC(dynamic_cast<const MEDCouplingCMesh *>(other));
   if(!otherC)
     throw INTERP_KERNEL::Exception("MEDCouplingCMesh::copyTinyStringsFrom : meshes have not same type !");
-  MEDCouplingStructuredMesh::copyTinyStringsFrom(other);
   if(_x_array && otherC->_x_array)
     _x_array->copyStringInfoFrom(*otherC->_x_array);
   if(_y_array && otherC->_y_array)
@@ -151,7 +170,7 @@ bool MEDCouplingCMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec
       reason="mesh given in input is not castable in MEDCouplingCMesh !";
       return false;
     }
-  if(!MEDCouplingMesh::isEqualIfNotWhy(other,prec,reason))
+  if(!MEDCouplingStructuredMesh::isEqualIfNotWhy(other,prec,reason))
     return false;
   const DataArrayDouble *thisArr[3]={_x_array,_y_array,_z_array};
   const DataArrayDouble *otherArr[3]={otherC->_x_array,otherC->_y_array,otherC->_z_array};
@@ -194,25 +213,24 @@ bool MEDCouplingCMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other
 }
 
 void MEDCouplingCMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
-                                            DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
+                                            DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const
 {
   if(!isEqualWithoutConsideringStr(other,prec))
     throw INTERP_KERNEL::Exception("MEDCouplingCMesh::checkDeepEquivalWith : Meshes are not the same !");
 }
 
 /*!
- * Nothing is done here (except to check that the other is a ParaMEDMEM::MEDCouplingCMesh instance too).
- * The user intend that the nodes are the same, so by construction of ParaMEDMEM::MEDCouplingCMesh, 'this' and 'other' are the same !
+ * Nothing is done here (except to check that the other is a MEDCoupling::MEDCouplingCMesh instance too).
+ * The user intend that the nodes are the same, so by construction of MEDCoupling::MEDCouplingCMesh, \a this and \a other are the same !
  */
 void MEDCouplingCMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
-                                                       DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
+                                                       DataArrayInt *&cellCor) const
 {
-  const MEDCouplingCMesh *otherC=dynamic_cast<const MEDCouplingCMesh *>(other);
-  if(!otherC)
-    throw INTERP_KERNEL::Exception("MEDCouplingCMesh::checkDeepEquivalOnSameNodesWith : other is NOT a cartesian mesh ! Impossible to check equivalence !");
+  if(!isEqualWithoutConsideringStr(other,prec))
+    throw INTERP_KERNEL::Exception("MEDCouplingCMesh::checkDeepEquivalOnSameNodesWith : Meshes are not the same !");
 }
 
-void MEDCouplingCMesh::checkCoherency() const
+void MEDCouplingCMesh::checkConsistencyLight() const
 {
   const char msg0[]="Invalid ";
   const char msg1[]=" array ! Must contain more than 1 element.";
@@ -243,7 +261,6 @@ void MEDCouplingCMesh::checkCoherency() const
           std::ostringstream os; os << msg0 << 'Y' << msg2;
           throw INTERP_KERNEL::Exception(os.str().c_str());
         }
-      
     }
   if(_z_array)
     {
@@ -260,9 +277,9 @@ void MEDCouplingCMesh::checkCoherency() const
     }
 }
 
-void MEDCouplingCMesh::checkCoherency1(double eps) const
+void MEDCouplingCMesh::checkConsistency(double eps) const
 {
-  checkCoherency();
+  checkConsistencyLight();
   if(_x_array)
     _x_array->checkMonotonic(true, eps);
   if(_y_array)
@@ -271,86 +288,59 @@ void MEDCouplingCMesh::checkCoherency1(double eps) const
     _z_array->checkMonotonic(true, eps);
 }
 
-void MEDCouplingCMesh::checkCoherency2(double eps) const
-{
-  checkCoherency1(eps);
-}
-
-int MEDCouplingCMesh::getNumberOfCells() const
+void MEDCouplingCMesh::getNodeGridStructure(int *res) const
 {
-  int ret=1;
-  if(_x_array)
-    ret*=_x_array->getNbOfElems()-1;
-  if(_y_array)
-    ret*=_y_array->getNbOfElems()-1;
-  if(_z_array)
-    ret*=_z_array->getNbOfElems()-1;
-  return ret;
+  std::vector<int> ret(getNodeGridStructure());
+  std::copy(ret.begin(),ret.end(),res);
 }
 
-int MEDCouplingCMesh::getNumberOfNodes() const
+std::vector<int> MEDCouplingCMesh::getNodeGridStructure() const
 {
-  int ret=1;
+  static const char MSG[]="MEDCouplingCMesh::getNodeGridStructure : mesh is invalid ! null vectors (X, Y or Z) must be put contiguously at the end !";
+  std::vector<int> ret;
+  bool isOK(true);
   if(_x_array)
-    ret*=_x_array->getNbOfElems();
+    {
+      if(!_x_array->isAllocated() || _x_array->getNumberOfComponents()!=1)
+        throw INTERP_KERNEL::Exception("MEDCouplingCMesh::getNodeGridStructure : X array exits but it is not allocated or with nb of components equal to one !");
+      ret.push_back(_x_array->getNumberOfTuples());
+    }
+  else
+    isOK=false;
   if(_y_array)
-    ret*=_y_array->getNbOfElems();
-  if(_z_array)
-    ret*=_z_array->getNbOfElems();
-  return ret;
-}
-
-void MEDCouplingCMesh::getSplitCellValues(int *res) const
-{
-  int meshDim(getMeshDimension());
-  for(int l=0;l<meshDim;l++)
     {
-      int val=1;
-      for(int p=0;p<meshDim-l-1;p++)
-        val*=getCoordsAt(p)->getNbOfElems()-1;
-      res[meshDim-l-1]=val;
+      if(!_y_array->isAllocated() || _y_array->getNumberOfComponents()!=1)
+        throw INTERP_KERNEL::Exception("MEDCouplingCMesh::getNodeGridStructure : Y array exits but it is not allocated or with nb of components equal to one !");
+      if(!isOK)
+        throw INTERP_KERNEL::Exception(MSG);
+      ret.push_back(_y_array->getNumberOfTuples());
     }
-}
-
-void MEDCouplingCMesh::getSplitNodeValues(int *res) const
-{
-  int spaceDim(getSpaceDimension());
-  for(int l=0;l<spaceDim;l++)
+  else
+    isOK=false;
+  if(_z_array)
     {
-      int val=1;
-      for(int p=0;p<spaceDim-l-1;p++)
-        val*=getCoordsAt(p)->getNbOfElems();
-      res[spaceDim-l-1]=val;
+      if(!_z_array->isAllocated() || _z_array->getNumberOfComponents()!=1)
+        throw INTERP_KERNEL::Exception("MEDCouplingCMesh::getNodeGridStructure : Z array exits but it is not allocated or with nb of components equal to one !");
+      if(!isOK)
+        throw INTERP_KERNEL::Exception(MSG);
+      ret.push_back(_z_array->getNumberOfTuples());
     }
-}
-
-void MEDCouplingCMesh::getNodeGridStructure(int *res) const
-{
-  int spaceDim(getSpaceDimension());
-  for(int i=0;i<spaceDim;i++)
-    res[i]=getCoordsAt(i)->getNbOfElems();
-}
-
-std::vector<int> MEDCouplingCMesh::getNodeGridStructure() const
-{
-  std::vector<int> ret(getSpaceDimension());
-  getNodeGridStructure(&ret[0]);
   return ret;
 }
 
 MEDCouplingStructuredMesh *MEDCouplingCMesh::buildStructuredSubPart(const std::vector< std::pair<int,int> >& cellPart) const
 {
-  checkCoherency();
-  int dim(getMeshDimension());
+  checkConsistencyLight();
+  int dim(getSpaceDimension());
   if(dim!=(int)cellPart.size())
     {
-      std::ostringstream oss; oss << "MEDCouplingCMesh::buildStructuredSubPart : the mesh dimension is " << dim << " and cell part size is " << cellPart.size() << " !";
+      std::ostringstream oss; oss << "MEDCouplingCMesh::buildStructuredSubPart : the space dimension is " << dim << " and cell part size is " << cellPart.size() << " !";
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingCMesh> ret(dynamic_cast<MEDCouplingCMesh *>(deepCpy()));
+  MCAuto<MEDCouplingCMesh> ret(dynamic_cast<MEDCouplingCMesh *>(deepCopy()));
   for(int i=0;i<dim;i++)
     {
-      MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(ret->getCoordsAt(i)->selectByTupleId2(cellPart[i].first,cellPart[i].second+1,1));
+      MCAuto<DataArrayDouble> tmp(ret->getCoordsAt(i)->selectByTupleIdSafeSlice(cellPart[i].first,cellPart[i].second+1,1));
       ret->setCoordsAt(i,tmp);
     }
   return ret.retn();
@@ -358,59 +348,11 @@ MEDCouplingStructuredMesh *MEDCouplingCMesh::buildStructuredSubPart(const std::v
 
 /*!
  * Return the space dimension of \a this. It only considers the arrays along X, Y and Z to deduce that.
- * This method throws exceptions if the not null arrays defining this are not contiguouly at the end. For example X!=0,Y==0,Z!=0 will throw.
+ * This method throws exceptions if the not null arrays defining this are not contiguously at the end. For example X!=0,Y==0,Z!=0 will throw.
  */
 int MEDCouplingCMesh::getSpaceDimension() const
 {
-  static const char MSG[]="MEDCouplingCMesh::getSpaceDimension : mesh is invalid ! null vectors (X, Y or Z) must be put contiguously at the end !";
-  int ret(0);
-  bool isOK(true);
-  if(_x_array)
-    ret++;
-  else
-    isOK=false;
-  if(_y_array)
-    {
-      if(!isOK)
-        throw INTERP_KERNEL::Exception(MSG);
-      ret++;
-    }
-  else
-    isOK=false;
-  if(_z_array)
-    {
-      if(!isOK)
-        throw INTERP_KERNEL::Exception(MSG);
-      ret++;
-    }
-  return ret;
-}
-
-/*!
- * This method returns the mesh dimension of \a this. It can be different from space dimension in case of a not null dimension contains only one node.
- */
-int MEDCouplingCMesh::getMeshDimension() const
-{
-  int ret(getSpaceDimension());
-  if(_x_array)
-    {
-      if(_x_array->isAllocated())
-        if(_x_array->getNumberOfTuples()==1)
-          ret--;
-    }
-  if(_y_array)
-    {
-      if(_y_array->isAllocated())
-        if(_y_array->getNumberOfTuples()==1)
-          ret--;
-    }
-  if(_z_array)
-    {
-      if(_z_array->isAllocated())
-        if(_z_array->getNumberOfTuples()==1)
-          ret--;
-    }
-  return ret;
+  return (int)getNodeGridStructure().size();
 }
 
 void MEDCouplingCMesh::getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const
@@ -435,7 +377,7 @@ std::string MEDCouplingCMesh::simpleRepr() const
   double tt=getTime(tmpp1,tmpp2);
   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
-  ret << "Mesh and SpaceDimension dimension : " << getSpaceDimension() << "\n\nArrays :\n________\n\n";
+  ret << "Space dimension : " << getSpaceDimension() << "\n\nArrays :\n________\n\n";
   if(_x_array)
     {
       ret << "X Array :\n";
@@ -475,7 +417,7 @@ std::string MEDCouplingCMesh::advancedRepr() const
 const DataArrayDouble *MEDCouplingCMesh::getCoordsAt(int i) const
 {
   switch(i)
-    {
+  {
     case 0:
       return _x_array;
     case 1:
@@ -484,7 +426,7 @@ const DataArrayDouble *MEDCouplingCMesh::getCoordsAt(int i) const
       return _z_array;
     default:
       throw INTERP_KERNEL::Exception("Invalid rank specified must be 0 or 1 or 2.");
-    }
+  }
 }
 
 /*!
@@ -503,7 +445,7 @@ const DataArrayDouble *MEDCouplingCMesh::getCoordsAt(int i) const
 DataArrayDouble *MEDCouplingCMesh::getCoordsAt(int i)
 {
   switch(i)
-    {
+  {
     case 0:
       return _x_array;
     case 1:
@@ -512,7 +454,7 @@ DataArrayDouble *MEDCouplingCMesh::getCoordsAt(int i)
       return _z_array;
     default:
       throw INTERP_KERNEL::Exception("Invalid rank specified must be 0 or 1 or 2.");
-    }
+  }
 }
 
 /*!
@@ -691,9 +633,15 @@ int MEDCouplingCMesh::getCellContainingPoint(const double *pos, double eps) cons
   return ret;
 }
 
+void MEDCouplingCMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
+{
+  int ret(getCellContainingPoint(pos,eps));
+  elts.push_back(ret);
+}
+
 void MEDCouplingCMesh::rotate(const double *center, const double *vector, double angle)
 {
-  throw INTERP_KERNEL::Exception("No rotation available on CMesh : Traduce it to StructuredMesh to apply it !");
+  throw INTERP_KERNEL::Exception("No rotation available on CMesh : Traduce it to untructured mesh to apply it !");
 }
 
 /*!
@@ -754,11 +702,10 @@ MEDCouplingMesh *MEDCouplingCMesh::mergeMyselfWith(const MEDCouplingMesh *other)
  */
 DataArrayDouble *MEDCouplingCMesh::getCoordinatesAndOwner() const
 {
-  DataArrayDouble *ret=DataArrayDouble::New();
-  int spaceDim=getSpaceDimension();
-  int nbNodes=getNumberOfNodes();
+  MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
+  int spaceDim(getSpaceDimension()),nbNodes(getNumberOfNodes());
   ret->alloc(nbNodes,spaceDim);
-  double *pt=ret->getPointer();
+  double *pt(ret->getPointer());
   int tmp[3];
   getSplitNodeValues(tmp);
   const DataArrayDouble *tabs[3]={getCoordsAt(0),getCoordsAt(1),getCoordsAt(2)};
@@ -775,7 +722,7 @@ DataArrayDouble *MEDCouplingCMesh::getCoordinatesAndOwner() const
       for(int j=0;j<spaceDim;j++)
         pt[i*spaceDim+j]=tabsPtr[j][tmp2[j]];
     }
-  return ret;
+  return ret.retn();
 }
 
 /*!
@@ -786,7 +733,7 @@ DataArrayDouble *MEDCouplingCMesh::getCoordinatesAndOwner() const
  *          components. The caller is to delete this array using decrRef() as it is
  *          no more needed.
  */
-DataArrayDouble *MEDCouplingCMesh::getBarycenterAndOwner() const
+DataArrayDouble *MEDCouplingCMesh::computeCellCenterOfMass() const
 {
   DataArrayDouble *ret=DataArrayDouble::New();
   int spaceDim=getSpaceDimension();
@@ -818,7 +765,7 @@ DataArrayDouble *MEDCouplingCMesh::getBarycenterAndOwner() const
 
 DataArrayDouble *MEDCouplingCMesh::computeIsoBarycenterOfNodesPerCell() const
 {
-  return MEDCouplingCMesh::getBarycenterAndOwner();
+  return MEDCouplingCMesh::computeCellCenterOfMass();
 }
 
 void MEDCouplingCMesh::renumberCells(const int *old2NewBg, bool check)
@@ -929,7 +876,7 @@ void MEDCouplingCMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData
         thisArr[i]->writeVTK(ofs,8,"Array",byteData);
       else
         {
-          MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::New(); coo->alloc(1,1);
+          MCAuto<DataArrayDouble> coo=DataArrayDouble::New(); coo->alloc(1,1);
           coo->setIJ(0,0,0.);
           coo->writeVTK(ofs,8,"Array",byteData);
         }
@@ -985,7 +932,11 @@ void MEDCouplingCMesh::reprQuickOverview(std::ostream& stream) const
       if(isDef[i])
         stream << std::endl << stream2[i].str();
     }
-    
+}
+
+std::string MEDCouplingCMesh::getVTKFileExtension() const
+{
+  return std::string("vtr");
 }
 
 std::string MEDCouplingCMesh::getVTKDataSetType() const