Salome HOME
Management of the new kid of the block VTK_QUADRATIC_POLYGON in VTK
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMesh.cxx
index 95d450a9ceb22fa4ec49e2743d15bf3899c5efb5..4aae2aa584dbf839003236c034effd85c513489b 100644 (file)
@@ -37,13 +37,13 @@ MEDCouplingMesh::MEDCouplingMesh():_time(0.),_iteration(-1),_order(-1)
 {
 }
 
-MEDCouplingMesh::MEDCouplingMesh(const MEDCouplingMesh& other):_name(other._name),_description(other._description),
+MEDCouplingMesh::MEDCouplingMesh(const MEDCouplingMesh& other):RefCountObject(other),_name(other._name),_description(other._description),
                                                                _time(other._time),_iteration(other._iteration),
                                                                _order(other._order),_time_unit(other._time_unit)
 {
 }
 
-std::size_t MEDCouplingMesh::getHeapMemorySize() const
+std::size_t MEDCouplingMesh::getHeapMemorySizeWithoutChildren() const
 {
   return _name.capacity()+_description.capacity()+_time_unit.capacity();
 }
@@ -56,7 +56,7 @@ bool MEDCouplingMesh::isStructured() const
   return getType()==CARTESIAN;
 }
 
-bool MEDCouplingMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
+bool MEDCouplingMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
 {
   if(!other)
     throw INTERP_KERNEL::Exception("MEDCouplingMesh::isEqualIfNotWhy : other instance is NULL !");
@@ -106,7 +106,7 @@ bool MEDCouplingMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec,
  *  \param [in] prec - precision value used to compare node coordinates.
  *  \return bool - \c true if the two meshes are equal, \c false else.
  */
-bool MEDCouplingMesh::isEqual(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
+bool MEDCouplingMesh::isEqual(const MEDCouplingMesh *other, double prec) const
 {
   std::string tmp;
   return isEqualIfNotWhy(other,prec,tmp);
@@ -224,8 +224,10 @@ DataArrayInt *MEDCouplingMesh::getCellIdsFullyIncludedInNodeIds(const int *partB
 /*!
  * This method checks fastly that \a this and \a other are equal. All common checks are done here.
  */
-void MEDCouplingMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
+void MEDCouplingMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
 {
+  if(!other)
+    throw INTERP_KERNEL::Exception("MEDCouplingMesh::checkFastEquivalWith : input mesh is null !");
   if(getMeshDimension()!=other->getMeshDimension())
     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Mesh dimensions are not equal !");
   if(getSpaceDimension()!=other->getSpaceDimension())
@@ -239,6 +241,8 @@ void MEDCouplingMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double
  */
 bool MEDCouplingMesh::areCompatibleForMerge(const MEDCouplingMesh *other) const
 {
+  if(!other)
+    throw INTERP_KERNEL::Exception("MEDCouplingMesh::areCompatibleForMerge : input mesh is null !");
   if(getMeshDimension()!=other->getMeshDimension())
     return false;
   if(getSpaceDimension()!=other->getSpaceDimension())
@@ -248,13 +252,26 @@ bool MEDCouplingMesh::areCompatibleForMerge(const MEDCouplingMesh *other) const
 
 /*!
  * This method is equivalent to MEDCouplingMesh::buildPart method except that here the cell ids are specified using slice \a beginCellIds \a endCellIds and \a stepCellIds.
+ * \b WARNING , there is a big difference compared to MEDCouplingMesh::buildPart method.
+ * If the input range is equal all cells in \a this, \a this is returned !
+ *
+ * \return a new ref to be managed by the caller. Warning this ref can be equal to \a this if input slice is exactly equal to the whole cells in the same order.
  *
  * \sa MEDCouplingMesh::buildPart
  */
-MEDCouplingMesh *MEDCouplingMesh::buildPartRange(int beginCellIds, int endCellIds, int stepCellIds) const throw(INTERP_KERNEL::Exception)
+MEDCouplingMesh *MEDCouplingMesh::buildPartRange(int beginCellIds, int endCellIds, int stepCellIds) const
 {
-  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
-  return buildPart(cellIds->begin(),cellIds->end());
+  if(beginCellIds==0 && endCellIds==getNumberOfCells() && stepCellIds==1)
+    {
+      MEDCouplingMesh *ret(const_cast<MEDCouplingMesh *>(this));
+      ret->incrRef();
+      return ret;
+    }
+  else
+    {
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
+      return buildPart(cellIds->begin(),cellIds->end());
+    }
 }
 
 /*!
@@ -262,7 +279,7 @@ MEDCouplingMesh *MEDCouplingMesh::buildPartRange(int beginCellIds, int endCellId
  *
  * \sa MEDCouplingMesh::buildPartAndReduceNodes
  */
-MEDCouplingMesh *MEDCouplingMesh::buildPartRangeAndReduceNodes(int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt*& arr) const throw(INTERP_KERNEL::Exception)
+MEDCouplingMesh *MEDCouplingMesh::buildPartRangeAndReduceNodes(int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt*& arr) const
 {
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
   return buildPartAndReduceNodes(cellIds->begin(),cellIds->end(),arr);
@@ -297,8 +314,10 @@ MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbO
  * This method copyies all tiny strings from other (name and components name).
  * @throw if other and this have not same mesh type.
  */
-void MEDCouplingMesh::copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception)
+void MEDCouplingMesh::copyTinyStringsFrom(const MEDCouplingMesh *other)
 {
+  if(!other)
+    throw INTERP_KERNEL::Exception("MEDCouplingMesh::copyTinyStringsFrom : input mesh is null !");
   _name=other->_name;
   _description=other->_description;
   _time_unit=other->_time_unit;
@@ -308,7 +327,7 @@ void MEDCouplingMesh::copyTinyStringsFrom(const MEDCouplingMesh *other) throw(IN
  * This method copies all attributes that are \b NOT arrays in this.
  * All tiny attributes not usefully for state of \a this are ignored.
  */
-void MEDCouplingMesh::copyTinyInfoFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception)
+void MEDCouplingMesh::copyTinyInfoFrom(const MEDCouplingMesh *other)
 {
   copyTinyStringsFrom(other);
   _time=other->_time;
@@ -478,7 +497,7 @@ MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic3(TypeOfField t, int nb
  *          is no more needed.
  *  \throw If the meshes are of different mesh type.
  */
-MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(const MEDCouplingMesh *mesh1, const MEDCouplingMesh *mesh2) throw(INTERP_KERNEL::Exception)
+MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(const MEDCouplingMesh *mesh1, const MEDCouplingMesh *mesh2)
 {
   if(!mesh1)
     throw INTERP_KERNEL::Exception("MEDCouplingMesh::MergeMeshes : first parameter is an empty mesh !");
@@ -505,7 +524,7 @@ MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(const MEDCouplingMesh *mesh1, cons
  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
  */
-MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(std::vector<const MEDCouplingMesh *>& meshes) throw(INTERP_KERNEL::Exception)
+MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(std::vector<const MEDCouplingMesh *>& meshes)
 {
   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms1(meshes.size());
   std::vector< const MEDCouplingUMesh * > ms2(meshes.size());
@@ -534,7 +553,7 @@ MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(std::vector<const MEDCouplingMesh
  * 
  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
  */
-INTERP_KERNEL::NormalizedCellType MEDCouplingMesh::GetCorrespondingPolyType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
+INTERP_KERNEL::NormalizedCellType MEDCouplingMesh::GetCorrespondingPolyType(INTERP_KERNEL::NormalizedCellType type)
 {
   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
   return cm.getCorrespondingPolyType();
@@ -547,7 +566,7 @@ INTERP_KERNEL::NormalizedCellType MEDCouplingMesh::GetCorrespondingPolyType(INTE
  * \throw if type is dynamic as \c INTERP_KERNEL::NORM_POLYHED , \c INTERP_KERNEL::NORM_POLYGON , \c INTERP_KERNEL::NORM_QPOLYG
  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
  */
-int MEDCouplingMesh::GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
+int MEDCouplingMesh::GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NormalizedCellType type)
 {
   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
   if(cm.isDynamic())
@@ -561,13 +580,13 @@ int MEDCouplingMesh::GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NormalizedCe
  * 
  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
  */
-bool MEDCouplingMesh::IsStaticGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
+bool MEDCouplingMesh::IsStaticGeometricType(INTERP_KERNEL::NormalizedCellType type)
 {
   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
   return !cm.isDynamic();
 }
 
-bool MEDCouplingMesh::IsLinearGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
+bool MEDCouplingMesh::IsLinearGeometricType(INTERP_KERNEL::NormalizedCellType type)
 {
   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
   return !cm.isQuadratic();
@@ -579,7 +598,7 @@ bool MEDCouplingMesh::IsLinearGeometricType(INTERP_KERNEL::NormalizedCellType ty
  * 
  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
  */
-int MEDCouplingMesh::GetDimensionOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
+int MEDCouplingMesh::GetDimensionOfGeometricType(INTERP_KERNEL::NormalizedCellType type)
 {
   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
   return (int) cm.getDimension();
@@ -591,7 +610,7 @@ int MEDCouplingMesh::GetDimensionOfGeometricType(INTERP_KERNEL::NormalizedCellTy
  * 
  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
  */
-const char *MEDCouplingMesh::GetReprOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
+const char *MEDCouplingMesh::GetReprOfGeometricType(INTERP_KERNEL::NormalizedCellType type)
 {
   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
   return cm.getRepr();
@@ -625,8 +644,8 @@ void MEDCouplingMesh::getCellsContainingPoint(const double *pos, double eps, std
  *         this->getSpaceDimension() * \a nbOfPoints 
  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
  *  \param [in] eps - radius of balls (i.e. the precision).
- *  \param [in,out] elts - vector returning ids of found cells.
- *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
+ *  \param [out] elts - vector returning ids of found cells.
+ *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
  *         dividing cell ids in \a elts into groups each referring to one
  *         point. Its every element (except the last one) is an index pointing to the
  *         first id of a group of cells. For example cells in contact with the *i*-th
@@ -639,23 +658,22 @@ void MEDCouplingMesh::getCellsContainingPoint(const double *pos, double eps, std
  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
  */
-void MEDCouplingMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
+void MEDCouplingMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
 {
-  eltsIndex.resize(nbOfPoints+1);
-  eltsIndex[0]=0;
-  elts.clear();
-  int spaceDim=getSpaceDimension();
-  const double *work=pos;
+  eltsIndex=DataArrayInt::New(); elts=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
+  int *eltsIndexPtr(eltsIndex->getPointer());
+  int spaceDim(getSpaceDimension());
+  const double *work(pos);
   for(int i=0;i<nbOfPoints;i++,work+=spaceDim)
     {
       int ret=getCellContainingPoint(work,eps);
       if(ret>=0)
         {
-          elts.push_back(ret);
-          eltsIndex[i+1]=eltsIndex[i]+1;
+          elts->pushBackSilent(ret);
+          eltsIndexPtr[i+1]=eltsIndexPtr[i]+1;
         }
       else
-        eltsIndex[i+1]=eltsIndex[i];
+        eltsIndexPtr[i+1]=eltsIndexPtr[i];
     }
 }
 
@@ -664,17 +682,31 @@ void MEDCouplingMesh::getCellsContainingPoints(const double *pos, int nbOfPoints
  *  \param [in] fileName - the name of the file to write in.
  *  \throw If \a fileName is not a writable file.
  */
-void MEDCouplingMesh::writeVTK(const char *fileName) const throw(INTERP_KERNEL::Exception)
+void MEDCouplingMesh::writeVTK(const char *fileName, bool isBinary) const
 {
   std::string cda,pda;
-  writeVTKAdvanced(fileName,cda,pda);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayByte> byteArr;
+  if(isBinary)
+    { byteArr=DataArrayByte::New(); byteArr->alloc(0,1); }
+  writeVTKAdvanced(fileName,cda,pda,byteArr);
 }
 
-void MEDCouplingMesh::writeVTKAdvanced(const char *fileName, const std::string& cda, const std::string& pda) const throw(INTERP_KERNEL::Exception)
+void MEDCouplingMesh::writeVTKAdvanced(const char *fileName, const std::string& cda, const std::string& pda, DataArrayByte *byteData) const
 {
   std::ofstream ofs(fileName);
-  ofs << "<VTKFile type=\""  << getVTKDataSetType() << "\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
-  writeVTKLL(ofs,cda,pda);
-  ofs << "</VTKFile>\n";
-  ofs.close();
+  ofs << "<VTKFile type=\""  << getVTKDataSetType() << "\" version=\"0.1\" byte_order=\"" << MEDCouplingByteOrderStr() << "\">\n";
+  writeVTKLL(ofs,cda,pda,byteData);
+  if(byteData)
+    {
+      ofs << "<AppendedData encoding=\"raw\">\n_1234";
+      ofs << std::flush; ofs.close();
+      std::ofstream ofs2(fileName,std::ios_base::binary | std::ios_base::app);
+      ofs2.write(byteData->begin(),byteData->getNbOfElems()); ofs2 << std::flush; ofs2.close();
+      std::ofstream ofs3(fileName,std::ios_base::app); ofs3 << "\n</AppendedData>\n</VTKFile>\n"; ofs3.close();
+    }
+  else
+    {
+      ofs << "</VTKFile>\n";
+      ofs.close();
+    }
 }