X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingUMesh.cxx;h=fca3d1aa2a65063a3c2487722807e5616d3fde70;hb=b79f750df5fc807078f4efbf89d88587a88f7548;hp=dae38283f988e8ce48a70638fe7c81cc4942ac6f;hpb=c66a21a11fed90a9536b758a162785908cfe87da;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index dae38283f..fca3d1aa2 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D +// Copyright (C) 2007-2013 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 @@ -19,6 +19,7 @@ // Author : Anthony Geay (CEA/DEN) #include "MEDCouplingUMesh.hxx" +#include "MEDCoupling1GTUMesh.hxx" #include "MEDCouplingMemArray.txx" #include "MEDCouplingFieldDouble.hxx" #include "CellModel.hxx" @@ -26,6 +27,8 @@ #include "InterpolationUtils.hxx" #include "PointLocatorAlgos.txx" #include "BBTree.txx" +#include "BBTreeDst.txx" +#include "SplitterTetra.hxx" #include "DirectedBoundingBox.hxx" #include "InterpKernelMeshQuality.hxx" #include "InterpKernelCellSimplify.hxx" @@ -46,8 +49,6 @@ using namespace ParaMEDMEM; -const char MEDCouplingUMesh::PART_OF_NAME[]="PartOf_"; - double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14; 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_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED }; @@ -65,16 +66,66 @@ MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim) return ret; } +/*! + * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared + * between \a this and the new mesh. + * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to + * delete this mesh using decrRef() as it is no more needed. + */ MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const { return clone(true); } +/*! + * Returns a new MEDCouplingMesh which is a copy of \a this one. + * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a + * this mesh are shared by the new mesh. + * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to + * delete this mesh using decrRef() as it is no more needed. + */ MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const { return new MEDCouplingUMesh(*this,recDeepCpy); } +/*! + * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied. + * The coordinates are shared between \a this and the returned instance. + * + * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes) + * \sa MEDCouplingUMesh::deepCpy + */ +MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const throw(INTERP_KERNEL::Exception) +{ + checkConnectivityFullyDefined(); + MEDCouplingAutoRefCountObjectPtr ret=clone(false); + MEDCouplingAutoRefCountObjectPtr c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy()); + ret->setConnectivity(c,ci); + return ret.retn(); +} + +void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception) +{ + if(!other) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !"); + const MEDCouplingUMesh *otherC=dynamic_cast(other); + if(!otherC) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !"); + MEDCouplingUMesh *otherC2=const_cast(otherC);//sorry :( + setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true); +} + +std::size_t MEDCouplingUMesh::getHeapMemorySize() const +{ + std::size_t ret=0; + if(_nodal_connec) + ret+=_nodal_connec->getHeapMemorySize(); + if(_nodal_connec_index) + ret+=_nodal_connec_index->getHeapMemorySize(); + return MEDCouplingPointSet::getHeapMemorySize()+ret; +} + void MEDCouplingUMesh::updateTime() const { MEDCouplingPointSet::updateTime(); @@ -88,21 +139,29 @@ void MEDCouplingUMesh::updateTime() const } } -MEDCouplingUMesh::MEDCouplingUMesh():_iterator(-1),_mesh_dim(-2), - _nodal_connec(0),_nodal_connec_index(0) +MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0) { } /*! - * This method checks that this is correctly designed. For example le coordinates are set, nodal connectivity. - * When this method returns without throwing any exception, 'this' is expected to be writable, exchangeable and to be - * available for most of algorithm. When a mesh has been constructed from scratch it is a good habits to call this method to check - * that all is in order in 'this'. + * Checks if \a this mesh is well defined. If no exception is thrown by this method, + * then \a this mesh is most probably is writable, exchangeable and available for most + * of algorithms. When a mesh is constructed from scratch, it is a good habit to call + * this method to check that all is in order with \a this mesh. + * \throw If the mesh dimension is not set. + * \throw If the coordinates array is not set (if mesh dimension != -1 ). + * \throw If \a this mesh contains elements of dimension different from the mesh dimension. + * \throw If the connectivity data array has more than one component. + * \throw If the connectivity data array has a named component. + * \throw If the connectivity index data array has more than one component. + * \throw If the connectivity index data array has a named component. */ void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception) { if(_mesh_dim<-1) - throw INTERP_KERNEL::Exception("No mesh dimension specified !"); + throw INTERP_KERNEL::Exception("No mesh dimension specified !"); + if(_mesh_dim!=-1) + MEDCouplingPointSet::checkCoherency(); for(std::set::const_iterator iter=_types.begin();iter!=_types.end();iter++) { if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim) @@ -119,6 +178,9 @@ void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception) if(_nodal_connec->getInfoOnComponent(0)!="") throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !"); } + else + if(_mesh_dim!=-1) + throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !"); if(_nodal_connec_index) { if(_nodal_connec_index->getNumberOfComponents()!=1) @@ -126,16 +188,26 @@ void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception) if(_nodal_connec_index->getInfoOnComponent(0)!="") throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !"); } - if(_iterator!=-1) - { - throw INTERP_KERNEL::Exception("It appears that finishInsertingCells method has not been invoked after a insertNextCell session !"); - } -} - -/*! - * This method performs deeper checking in 'this' than MEDCouplingUMesh::checkCoherency does. - * So this method is more time-consuming. This method checks that nodal connectivity points to valid node ids. - * No geometrical aspects are checked here. These aspects are done in MEDCouplingUMesh::checkCoherency2. + else + if(_mesh_dim!=-1) + throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !"); +} + +/*! + * Checks if \a this mesh is well defined. If no exception is thrown by this method, + * then \a this mesh is most probably is writable, exchangeable and available for all + * algorithms.
In addition to the checks performed by checkCoherency(), this + * method thoroughly checks the nodal connectivity. + * \param [in] eps - a not used parameter. + * \throw If the mesh dimension is not set. + * \throw If the coordinates array is not set (if mesh dimension != -1 ). + * \throw If \a this mesh contains elements of dimension different from the mesh dimension. + * \throw If the connectivity data array has more than one component. + * \throw If the connectivity data array has a named component. + * \throw If the connectivity index data array has more than one component. + * \throw If the connectivity index data array has a named component. + * \throw If number of nodes defining an element does not correspond to the type of element. + * \throw If the nodal connectivity includes an invalid node id. */ void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception) { @@ -193,21 +265,56 @@ void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Ex } } + +/*! + * Checks if \a this mesh is well defined. If no exception is thrown by this method, + * then \a this mesh is most probably is writable, exchangeable and available for all + * algorithms.
This method performs the same checks as checkCoherency1() does. + * \param [in] eps - a not used parameter. + * \throw If the mesh dimension is not set. + * \throw If the coordinates array is not set (if mesh dimension != -1 ). + * \throw If \a this mesh contains elements of dimension different from the mesh dimension. + * \throw If the connectivity data array has more than one component. + * \throw If the connectivity data array has a named component. + * \throw If the connectivity index data array has more than one component. + * \throw If the connectivity index data array has a named component. + * \throw If number of nodes defining an element does not correspond to the type of element. + * \throw If the nodal connectivity includes an invalid node id. + */ void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception) { checkCoherency1(eps); } +/*! + * Sets dimension of \a this mesh. The mesh dimension in general depends on types of + * elements contained in the mesh. For more info on the mesh dimension see + * \ref MEDCouplingUMeshPage. + * \param [in] meshDim - a new mesh dimension. + * \throw If \a meshDim is invalid. A valid range is -1 <= meshDim <= 3. + */ void MEDCouplingUMesh::setMeshDimension(int meshDim) { - if(meshDim<-1) - throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 !"); + if(meshDim<-1 || meshDim>3) + throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !"); _mesh_dim=meshDim; declareAsNew(); } +/*! + * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted, + * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter. + * If a nodal connectivity previouly existed before the call of this method, it will be reset. + * + * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain. + * + * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".
+ * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example". + */ void MEDCouplingUMesh::allocateCells(int nbOfCells) { + if(nbOfCells<0) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !"); if(_nodal_connec_index) { _nodal_connec_index->decrRef(); @@ -216,23 +323,24 @@ void MEDCouplingUMesh::allocateCells(int nbOfCells) { _nodal_connec->decrRef(); } - _nodal_connec_index=DataArrayInt::New(); - _nodal_connec_index->alloc(nbOfCells+1,1); - int *pt=_nodal_connec_index->getPointer(); - pt[0]=0; + _nodal_connec_index->reserve(nbOfCells+1); + _nodal_connec_index->pushBackSilent(0); _nodal_connec=DataArrayInt::New(); - _nodal_connec->alloc(2*nbOfCells,1); - _iterator=0; + _nodal_connec->reserve(2*nbOfCells); _types.clear(); declareAsNew(); } /*! - * Appends a cell in connectivity array. - * @param type type of cell to add. - * @param size number of nodes constituting this cell. - * @param nodalConnOfCell the connectivity of the cell to add. + * Appends a cell to the connectivity array. For deeper understanding what is + * happening see \ref MEDCouplingUMeshNodalConnectivity. + * \param [in] type - type of cell to add. + * \param [in] size - number of nodes constituting this cell. + * \param [in] nodalConnOfCell - the connectivity of the cell to add. + * + * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".
+ * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example". */ void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception) { @@ -241,15 +349,18 @@ void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, in throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !"); if((int)cm.getDimension()==_mesh_dim) { - int nbOfElems=_nodal_connec_index->getNbOfElems()-1; - if(_iterator>=nbOfElems) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : allocation of cells was wide enough ! Call insertNextCell with higher value or call finishInsertingCells !"); - int *pt=_nodal_connec_index->getPointer(); - int idx=pt[_iterator]; - + if(!cm.isDynamic()) + if(size!=(int)cm.getNumberOfNodes()) + { + std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size; + oss << " ! Expecting " << cm.getNumberOfNodes() << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + int idx=_nodal_connec_index->back(); + int val=idx+size+1; + _nodal_connec_index->pushBackSilent(val); _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size); _types.insert(type); - pt[++_iterator]=idx+size+1; } else { @@ -261,16 +372,16 @@ void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, in } /*! - * Method to be called to cloture the insertion of cells using this->insertNextCell. + * Compacts data arrays to release unused memory. This method is to be called after + * finishing cell insertion using \a this->insertNextCell(). + * + * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".
+ * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example". */ void MEDCouplingUMesh::finishInsertingCells() { - const int *pt=_nodal_connec_index->getConstPointer(); - int idx=pt[_iterator]; - - _nodal_connec->reAlloc(idx); - _nodal_connec_index->reAlloc(_iterator+1); - _iterator=-1; + _nodal_connec->pack(); + _nodal_connec_index->pack(); _nodal_connec->declareAsNew(); _nodal_connec_index->declareAsNew(); updateTime(); @@ -287,7 +398,7 @@ MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator() /*! * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated. - * If '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 that 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. */ @@ -298,13 +409,18 @@ MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KE return new MEDCouplingUMeshCellByTypeEntry(this); } +/*! + * Returns a set of all cell types available in \a this mesh. + * \return std::set - the set of cell types. + * \warning this method does not throw any exception even if \a this is not defined. + */ std::set MEDCouplingUMesh::getAllGeoTypes() const { return _types; } /*! - * This method is a method that compares 'this' and 'other'. + * This method is a method that compares \a this and \a other. * This method compares \b all attributes, even names and component names. */ bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception) @@ -364,6 +480,14 @@ bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec return true; } +/*! + * Checks if data arrays of this mesh (node coordinates, nodal + * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are + * not considered. + * \param [in] other - the mesh to compare with. + * \param [in] prec - precision value used to compare node coordinates. + * \return bool - \a true if the two meshes are same. + */ bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const { const MEDCouplingUMesh *otherC=dynamic_cast(other); @@ -391,122 +515,50 @@ bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other } /*! - * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one - * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. - * - * In case of success cellCor and nodeCor are informed both. - * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method. - * @param cellCor output array giving the correspondance of cells from 'other' to 'this'. - * @param nodeCor output array giving the correspondance of nodes from 'other' to 'this'. - */ -void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec, - DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception) -{ - const MEDCouplingUMesh *otherC=dynamic_cast(other); - if(!otherC) - throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !"); - MEDCouplingMesh::checkFastEquivalWith(other,prec); - if(_types!=otherC->_types) - throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !"); - MEDCouplingAutoRefCountObjectPtr m=MergeUMeshes(this,otherC); - bool areNodesMerged; - int newNbOfNodes; - int oldNbOfNodes=getNumberOfNodes(); - MEDCouplingAutoRefCountObjectPtr da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes); - //mergeNodes - if(!areNodesMerged) - throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! "); - const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater(),oldNbOfNodes-1)); - if(pt!=da->getConstPointer()+da->getNbOfElems()) - throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !"); - m->renumberNodes(da->getConstPointer(),newNbOfNodes); - // - MEDCouplingAutoRefCountObjectPtr nodeCor2=da->substr(oldNbOfNodes); - da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes); - - // - da=m->zipConnectivityTraducer(cellCompPol); - int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells()); - pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater(),maxId)); - if(pt!=da->getConstPointer()+da->getNbOfElems()) - throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !"); - MEDCouplingAutoRefCountObjectPtr cellCor2=DataArrayInt::New(); - cellCor2->alloc(otherC->getNumberOfCells(),1); - std::copy(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),cellCor2->getPointer()); - bool nident=nodeCor2->isIdentity(); - bool cident=cellCor2->isIdentity(); - if(!nident) { nodeCor=nodeCor2; nodeCor2->incrRef(); } else nodeCor=0; - if(!cident) { cellCor=cellCor2; cellCor2->incrRef(); } else cellCor=0; -} - -/*! - * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one - * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. The difference with MEDCouplingUMesh::checkDeepEquivalWith method is that - * coordinates of 'this' and 'other' are expected to be the same. If not an exception will be thrown. - * This method is close to MEDCouplingUMesh::areCellsIncludedIn except that this method throws exception ! - * - * In case of success cellCor are informed both. - * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method. - * @param cellCor output array giving the correspondance of cells from 'other' to 'this'. - */ -void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec, - DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception) -{ - const MEDCouplingUMesh *otherC=dynamic_cast(other); - if(!otherC) - throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !"); - MEDCouplingMesh::checkFastEquivalWith(other,prec); - if(_types!=otherC->_types) - throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !"); - if(_coords!=otherC->_coords) - throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !"); - std::vector ms(2); - ms[0]=this; - ms[1]=otherC; - MEDCouplingAutoRefCountObjectPtr m=MergeUMeshesOnSameCoords(ms); - MEDCouplingAutoRefCountObjectPtr da=m->zipConnectivityTraducer(cellCompPol); - int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells()); - const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater(),maxId)); - if(pt!=da->getConstPointer()+da->getNbOfElems()) - { - throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !"); - } - MEDCouplingAutoRefCountObjectPtr cellCor2=DataArrayInt::New(); - cellCor2->alloc(otherC->getNumberOfCells(),1); - std::copy(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),cellCor2->getPointer()); - if(!cellCor2->isIdentity()) { cellCor=cellCor2; cellCor2->incrRef(); } else cellCor=0; -} - -/*! - * This method checks fastly that 'this' and 'other' are equal. + * Checks if \a this and \a other meshes are geometrically equivalent with high + * probability, else an exception is thrown. The meshes are considered equivalent if + * (1) meshes contain the same number of nodes and the same number of elements of the + * same types (2) three cells of the two meshes (first, last and middle) are based + * on coincident nodes (with a specified precision). + * \param [in] other - the mesh to compare with. + * \param [in] prec - the precision used to compare nodes of the two meshes. + * \throw If the two meshes do not match. */ void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception) { - const MEDCouplingUMesh *otherC=dynamic_cast(other); + MEDCouplingPointSet::checkFastEquivalWith(other,prec); + const MEDCouplingUMesh *otherC=dynamic_cast(other); if(!otherC) - throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !"); - MEDCouplingPointSet::checkFastEquivalWith(other,prec); - int nbOfCells=getNumberOfCells(); - if(nbOfCells<1) - return ; - bool status=true; - status&=areCellsFrom2MeshEqual(otherC,0,prec); - status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec); - status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec); - if(!status) - throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !"); -} - -/*! - * \b WARNING this method do the assumption that connectivity lies on the coordinates set. - * For speed reasons no check of this will be done. + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); +} + +/*! + * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates + * cells each node belongs to. + * \warning For speed reasons, this method does not check if node ids in the nodal + * connectivity correspond to the size of node coordinates array. + * \param [in,out] revNodal - an array holding ids of cells sharing each node. + * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1, + * dividing cell ids in \a revNodal into groups each referring to one + * node. Its every element (except the last one) is an index pointing to the + * first id of a group of cells. For example cells sharing the node #1 are + * described by following range of indices: + * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are + * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ... + * Number of cells sharing the *i*-th node is + * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ]. + * \throw If the coordinates array is not set. + * \throw If the nodal connectivity of cells is not defined. + * + * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".
+ * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example". */ void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception) { checkFullyDefined(); int nbOfNodes=getNumberOfNodes(); - int *revNodalIndxPtr=new int[nbOfNodes+1]; - revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1); + int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int)); + revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1); std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0); const int *conn=_nodal_connec->getConstPointer(); const int *connIndex=_nodal_connec_index->getConstPointer(); @@ -524,8 +576,8 @@ void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataA } } std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus()); - int *revNodalPtr=new int[nbOfEltsInRevNodal]; - revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1); + int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int)); + revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1); std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1); for(int eltId=0;eltIdgetMeshDimension(), that bound cells of \a this mesh. In addition arrays + * describing correspondence between cells of \a this and the result meshes are + * returned. The arrays \a desc and \a descIndx describe the descending connectivity, + * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The + * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity, + * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh. + * \warning For speed reasons, this method does not check if node ids in the nodal + * connectivity correspond to the size of node coordinates array. + * \warning Cells of the result mesh are \b not sorted by geometric type, hence, + * to write this mesh to the MED file, its cells must be sorted using + * sortCellsInMEDFileFrmt(). + * \param [in,out] desc - the array containing cell ids of the result mesh bounding + * each cell of \a this mesh. + * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1, + * dividing cell ids in \a desc into groups each referring to one + * cell of \a this mesh. Its every element (except the last one) is an index + * pointing to the first id of a group of cells. For example cells of the + * result mesh bounding the cell #1 of \a this mesh are described by following + * range of indices: + * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are + * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ... + * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is + * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ]. + * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded + * by each cell of the result mesh. + * \param [in,out] revDescIndx - the array, of length one more than number of cells + * in the result mesh, + * dividing cell ids in \a revDesc into groups each referring to one + * cell of the result mesh the same way as \a descIndx divides \a desc. + * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to + * delete this mesh using decrRef() as it is no more needed. + * \throw If the coordinates array is not set. + * \throw If the nodal connectivity of cells is node defined. + * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a + * revDescIndx == NULL. + * + * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".
+ * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example". + * \sa buildDescendingConnectivity2() */ MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception) { - return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer); + return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer); } /*! - * WARNING this method do the assumption that connectivity lies on the coordinates set. - * For speed reasons no check of this will be done. - * This method differs from MEDCouplingUMesh::buildDescendingConnectivity method in that 'desc' is in different format. - * This method is more precise because it returns in descending connectivity giving the direction. If value is positive the n-1 dim element is taken in the same direction, - * if it is in the opposite direction it is retrieved negative. So the problem is for elemt #0 in C convention. That's why this method is the only one that retrieves - * an array in relative "FORTRAN" mode. - * - * \warning This method returns a mesh whose geometric type order in are \b not sorted. - * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary. + * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown. + * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1) + * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity. + * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does. + * \sa MEDCouplingUMesh::buildDescendingConnectivity + */ +MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception) +{ + checkFullyDefined(); + if(getMeshDimension()!=3) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !"); + return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer); +} + +/*! + * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a + * this->getMeshDimension(), that bound cells of \a this mesh. In + * addition arrays describing correspondence between cells of \a this and the result + * meshes are returned. The arrays \a desc and \a descIndx describe the descending + * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this + * mesh. This method differs from buildDescendingConnectivity() in that apart + * from cell ids, \a desc returns mutual orientation of cells in \a this and the + * result meshes. So a positive id means that order of nodes in corresponding cells + * of two meshes is same, and a negative id means a reverse order of nodes. Since a + * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode, + * i.e. cell ids are one-based. + * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity, + * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh. + * \warning For speed reasons, this method does not check if node ids in the nodal + * connectivity correspond to the size of node coordinates array. + * \warning Cells of the result mesh are \b not sorted by geometric type, hence, + * to write this mesh to the MED file, its cells must be sorted using + * sortCellsInMEDFileFrmt(). + * \param [in,out] desc - the array containing cell ids of the result mesh bounding + * each cell of \a this mesh. + * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1, + * dividing cell ids in \a desc into groups each referring to one + * cell of \a this mesh. Its every element (except the last one) is an index + * pointing to the first id of a group of cells. For example cells of the + * result mesh bounding the cell #1 of \a this mesh are described by following + * range of indices: + * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are + * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ... + * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is + * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ]. + * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded + * by each cell of the result mesh. + * \param [in,out] revDescIndx - the array, of length one more than number of cells + * in the result mesh, + * dividing cell ids in \a revDesc into groups each referring to one + * cell of the result mesh the same way as \a descIndx divides \a desc. + * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh + * shares the node coordinates array with \a this mesh. The caller is to + * delete this mesh using decrRef() as it is no more needed. + * \throw If the coordinates array is not set. + * \throw If the nodal connectivity of cells is node defined. + * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a + * revDescIndx == NULL. + * + * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".
+ * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example". + * \sa buildDescendingConnectivity() */ MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception) { - return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer); + return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer); } /*! @@ -651,22 +812,19 @@ void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, cons MEDCouplingAutoRefCountObjectPtr out1=DataArrayInt::New(); out1->alloc(nbCells+1,1); int *out1Ptr=out1->getPointer(); *out1Ptr++=0; - std::vector out0v; - out0v.reserve(desc->getNumberOfTuples()); + out0->reserve(desc->getNumberOfTuples()); for(int i=0;i s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]); s.erase(i); - out0v.insert(out0v.end(),s.begin(),s.end()); + out0->insertAtTheEnd(s.begin(),s.end()); } - *out1Ptr=out0v.size(); + *out1Ptr=out0->getNumberOfTuples(); } - out0->alloc((int)out0v.size(),1); - std::copy(out0v.begin(),out0v.end(),out0->getPointer()); - neighbors=out0; out0->incrRef(); - neighborsIndx=out1; out1->incrRef(); + neighbors=out0.retn(); + neighborsIndx=out1.retn(); } /// @cond INTERNAL @@ -675,105 +833,117 @@ void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, cons * \b WARNING this method do the assumption that connectivity lies on the coordinates set. * For speed reasons no check of this will be done. */ +template MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception) { + if(!desc || !descIndx || !revDesc || !revDescIndx) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !"); checkConnectivityFullyDefined(); int nbOfCells=getNumberOfCells(); int nbOfNodes=getNumberOfNodes(); + MEDCouplingAutoRefCountObjectPtr revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero(); + int *revNodalIndxPtr=revNodalIndx->getPointer(); const int *conn=_nodal_connec->getConstPointer(); const int *connIndex=_nodal_connec_index->getConstPointer(); - std::vector< std::vector > descMeshConnB(nbOfCells); - std::vector< std::vector > revDescMeshConnB; - std::vector< std::vector > revNodalB(nbOfNodes); - std::vector meshDM1Conn; - std::vector meshDM1ConnIndex(1); meshDM1ConnIndex[0]=0; - std::vector meshDM1Type; - for(int eltId=0;eltId ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA); + ret->setCoords(getCoords()); + ret->allocateCells(2*nbOfCells); + descIndx->alloc(nbOfCells+1,1); + MEDCouplingAutoRefCountObjectPtr revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells); + int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0; + for(int eltId=0;eltId tmp=new int[posP1-pos]; for(unsigned i=0;i shareableCells(revNodalB[tmp[0]].begin(),revNodalB[tmp[0]].end()); - for(unsigned j=1;j tmp2(revNodalB[tmp[j]].begin(),revNodalB[tmp[j]].end()); - std::set tmp3; - std::set_intersection(tmp2.begin(),tmp2.end(),shareableCells.begin(),shareableCells.end(),inserter(tmp3,tmp3.begin())); - shareableCells=tmp3; - } - std::list shareableCellsL(shareableCells.begin(),shareableCells.end()); - std::set ref(tmp,tmp+nbOfNodesSon); - for(std::list::iterator iter=shareableCellsL.begin();iter!=shareableCellsL.end();) - { - if(cms.isCompatibleWith((INTERP_KERNEL::NormalizedCellType)meshDM1Type[*iter])) - { - std::set ref2(meshDM1Conn.begin()+meshDM1ConnIndex[*iter],meshDM1Conn.begin()+meshDM1ConnIndex[(*iter)+1]); - if(ref==ref2) - break; - else - iter=shareableCellsL.erase(iter); - } - else - iter=shareableCellsL.erase(iter); - } - if(shareableCellsL.empty()) + unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId); + for(unsigned k=0;k=0) + revNodalIndxPtr[tmp[k]+1]++; + ret->insertNextCell(cmsId,nbOfNodesSon,tmp); + revDesc2->pushBackSilent(eltId); + } + descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons; + } + int nbOfCellsM1=ret->getNumberOfCells(); + std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus()); + MEDCouplingAutoRefCountObjectPtr revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1); + std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1); + int *revNodalPtr=revNodal->getPointer(); + const int *connM1=ret->getNodalConnectivity()->getConstPointer(); + const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer(); + for(int eltId=0;eltId=0)//for polyhedrons + *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to(),-1))=eltId; + } + // + DataArrayInt *commonCells=0,*commonCellsI=0; + FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI); + MEDCouplingAutoRefCountObjectPtr commonCellsTmp(commonCells),commonCellsITmp(commonCellsI); + const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer()); + int newNbOfCellsM1=-1; + MEDCouplingAutoRefCountObjectPtr o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(), + commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1); + std::vector isImpacted(nbOfCellsM1,false); + for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++) + for(int work2=work[0];work2!=work[1];work2++) + isImpacted[commonCellsPtr[work2]]=true; + const int *o2nM1Ptr=o2nM1->getConstPointer(); + MEDCouplingAutoRefCountObjectPtr n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1); + const int *n2oM1Ptr=n2oM1->getConstPointer(); + MEDCouplingAutoRefCountObjectPtr ret2=static_cast(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true)); + ret2->copyTinyInfoFrom(this); + desc->alloc(descIndx->back(),1); + int *descPtr=desc->getPointer(); + const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1); + for(int i=0;isetCoords(getCoords()); - int nbOfCellsInConstituent=(int)meshDM1Type.size(); - ret->allocateCells(nbOfCellsInConstituent); - revDescIndx->alloc(nbOfCellsInConstituent+1,1); - int *tmp3=revDescIndx->getPointer(); tmp3[0]=0; - for(int ii=0;iireserve(newNbOfCellsM1); + revDescIndx->alloc(newNbOfCellsM1+1,1); + int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0; + const int *revDesc2Ptr=revDesc2->getConstPointer(); + for(int i=0;iinsertNextCell((INTERP_KERNEL::NormalizedCellType)meshDM1Type[ii],meshDM1ConnIndex[ii+1]-meshDM1ConnIndex[ii],&meshDM1Conn[meshDM1ConnIndex[ii]]); - tmp3[ii+1]=tmp3[ii]+((int)revDescMeshConnB[ii].size()); + int oldCellIdM1=n2oM1Ptr[i]; + if(!isImpacted[oldCellIdM1]) + { + revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]); + revDescIndxPtr[0]=revDescIndxPtr[-1]+1; + } + else + { + for(int j=commonCellsIPtr[0];jpushBackSilent(revDesc2Ptr[commonCellsPtr[j]]); + revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0]; + commonCellsIPtr++; + } } - ret->finishInsertingCells(); - revDesc->alloc(tmp3[nbOfCellsInConstituent],1); - tmp3=revDesc->getPointer(); - for(std::vector< std::vector >::const_iterator iter2=revDescMeshConnB.begin();iter2!=revDescMeshConnB.end();iter2++) - tmp3=std::copy((*iter2).begin(),(*iter2).end(),tmp3); - meshDM1Type.clear(); meshDM1ConnIndex.clear(); meshDM1Conn.clear(); - descIndx->alloc(nbOfCells+1,1); - tmp3=descIndx->getPointer(); tmp3[0]=0; - for(int jj=0;jjalloc(tmp3[nbOfCells],1); - tmp3=desc->getPointer(); - for(std::vector< std::vector >::const_iterator iter3=descMeshConnB.begin();iter3!=descMeshConnB.end();iter3++) - tmp3=std::copy((*iter3).begin(),(*iter3).end(),tmp3); // - return ret; + return ret2.retn(); } struct MEDCouplingAccVisit @@ -785,20 +955,26 @@ struct MEDCouplingAccVisit /// @endcond - /*! - * This method convert cell with ids in ['cellIdsToConvertBg','cellIdsToConvertEnd') into 'this' into dynamic types without changing geometry. - * That is to say if 'this' is a 2D, mesh after the invocation of this method it will contain only polygons. - * If 'this' is a 3D mesh after the invocation of this method it will contain only polyhedra. - * If mesh dimension is not in [2,3] an exception is thrown. - * Of course pay attention that the resulting mesh is slower than previous one. - * If in ['cellIdsToConvertBg','cellIdsToConvertEnd') there is a cell id not in [0,'this->getNumberOfCells()') an exception will be thrown. - * In this case if meshDim==2 the mesh is still valid and only cells treated before throw will be converted into polygon. - * If mesh==3, after throw the mesh is \b unconsistent ! - * This method is above all designed to test more extensively algorithms able to deal with polygons/polyhedra. - * - * \warning This method modifies can modify significantly the geometric type order in \a this. - * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary. + * Converts specified cells to either polygons (if \a this is a 2D mesh) or + * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an + * array of cell ids. Pay attention that after conversion all algorithms work slower + * with \a this mesh than before conversion.
If an exception is thrown during the + * conversion due presence of invalid ids in the array of cells to convert, as a + * result \a this mesh contains some already converted elements. In this case the 2D + * mesh remains valid but 3D mesh becomes \b inconsistent! + * \warning This method can significantly modify the order of geometric types in \a this, + * hence, to write this mesh to the MED file, its cells must be sorted using + * sortCellsInMEDFileFrmt(). + * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert. + * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a + * cellIdsToConvertBg. + * \throw If the coordinates array is not set. + * \throw If the nodal connectivity of cells is node defined. + * \throw If dimension of \a this mesh is not either 2 or 3. + * + * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".
+ * \ref py_mcumesh_convertToPolyTypes "Here is a Python example". */ void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd) { @@ -816,7 +992,7 @@ void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const i if(*iter>=0 && *iter