X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingUMesh.cxx;h=d594c82ab143ee3afe9f3fe8cdb16bf1dce804e0;hb=5f64369e27eb852fd111d1ccdd17a9d583fe8473;hp=9a5f212005663dbc7870803492c32a37132d8897;hpb=77bd05418520f5ddc7ce7977776e8da183841e60;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index 9a5f21200..d594c82ab 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -19,6 +19,7 @@ // Author : Anthony Geay (CEA/DEN) #include "MEDCouplingUMesh.hxx" +#include "MEDCoupling1GTUMesh.hxx" #include "MEDCouplingMemArray.txx" #include "MEDCouplingFieldDouble.hxx" #include "CellModel.hxx" @@ -88,6 +89,33 @@ 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; @@ -150,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) @@ -157,6 +188,9 @@ 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 !"); } + else + if(_mesh_dim!=-1) + throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !"); } /*! @@ -268,14 +302,19 @@ void MEDCouplingUMesh::setMeshDimension(int meshDim) } /*! - * Allocates memory to store given number of cells. - * \param [in] nbOfCells - number of cell \a this mesh will contain. + * 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(); @@ -475,108 +514,6 @@ bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other return true; } -/*! - * Checks if \a this and \a other meshes are geometrically equivalent, else an - * exception is thrown. The meshes are - * considered equivalent if (1) \a this mesh contains the same nodes as the \a other - * mesh (with a specified precision) and (2) \a this mesh contains the same cells as - * the \a other mesh (with use of a specified cell comparison technique). The mapping - * from \a other to \a this for nodes and cells is returned via out parameters. - * \param [in] other - the mesh to compare with. - * \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of - * each method in description of MEDCouplingUMesh::zipConnectivityTraducer(). - * \param [in] prec - the precision used to compare nodes of the two meshes. - * \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is - * to delete this array using decrRef() as it is no more needed. - * \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is - * to delete this array using decrRef() as it is no more needed. - * \throw If the two meshes do not match. - * - * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".
- * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example". - */ -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 nbCells=getNumberOfCells(); - int maxId=-1; - if(nbCells!=0) - maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells); - pt=std::find_if(da->getConstPointer()+nbCells,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=da->selectByTupleId2(nbCells,da->getNbOfElems(),1); - nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn(); - cellCor=cellCor2->isIdentity()?0:cellCor2.retn(); -} - -/*! - * Checks if \a this and \a other meshes are geometrically equivalent, else an - * exception is thrown. The meshes are considered equivalent if (1) they share one - * node coordinates array and (2) they contain the same cells (with use of a specified - * cell comparison technique). The mapping from cells of the \a other to ones of \a this - * is returned via an out parameter. - * \param [in] other - the mesh to compare with. - * \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of - * each method in description of MEDCouplingUMesh::zipConnectivityTraducer(). - * \param [in] prec - a not used parameter. - * \param [out] cellCor - the permutation array in "Old to New" mode. The caller is - * to delete this array using decrRef() as it is no more needed. - * \throw If the two meshes do not match. - * - * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".
- * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example". - */ -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=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1); - cellCor=cellCor2->isIdentity()?0:cellCor2.retn(); -} - /*! * 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 @@ -589,19 +526,10 @@ void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *ot */ 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 !"); + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); } /*! @@ -1463,6 +1391,7 @@ DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const thro * So for pohyhedrons some nodes can be counted several times in the returned result. * * \return a newly allocated array + * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell */ DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception) { @@ -1483,6 +1412,36 @@ DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KER return ret.retn(); } +/*! + * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell, + * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method. + * + * \return DataArrayInt * - new object to be deallocated by the caller. + * \sa MEDCouplingUMesh::computeNbOfNodesPerCell + */ +DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception) +{ + checkConnectivityFullyDefined(); + int nbOfCells=getNumberOfCells(); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); + ret->alloc(nbOfCells,1); + int *retPtr=ret->getPointer(); + const int *conn=getNodalConnectivity()->getConstPointer(); + const int *connI=getNodalConnectivityIndex()->getConstPointer(); + for(int i=0;i s(conn+connI[i]+1,conn+connI[i+1]); + if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED) + *retPtr=(int)s.size(); + else + { + s.erase(-1); + *retPtr=(int)s.size(); + } + } + return ret.retn(); +} + /*! * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component. * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed. @@ -1522,15 +1481,12 @@ DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KER */ DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception) { - int newNbOfNodes=-1; - DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes); - renumberNodes(traducer->getConstPointer(),newNbOfNodes); - return traducer; + return MEDCouplingPointSet::zipCoordsTraducer(); } /*! * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy. - * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method. + * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method. */ int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType) { @@ -1551,7 +1507,7 @@ int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1 } /*! - * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0. + * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0. */ int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2) { @@ -1561,7 +1517,7 @@ int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell } /*! - * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1. + * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1. */ int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2) { @@ -1594,7 +1550,7 @@ int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell } /*! - * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2. + * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2. */ int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2) { @@ -1625,7 +1581,7 @@ int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell } /*! - * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7. + * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7. */ int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2) { @@ -1686,39 +1642,11 @@ int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell return 0; } - -/*! - * This method compares 2 cells coming from two unstructured meshes : \a this and \a other. - * This method compares 2 cells having the same id 'cellId' in \a this and \a other. - */ -bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const -{ - if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId)) - return false; - std::vector c1,c2; - getNodeIdsOfCell(cellId,c1); - other->getNodeIdsOfCell(cellId,c2); - std::size_t sz=c1.size(); - if(sz!=c2.size()) - return false; - for(std::size_t i=0;i n1,n2; - getCoordinatesOfNode(c1[0],n1); - other->getCoordinatesOfNode(c2[0],n2); - std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus()); - std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun(fabs)); - if(*std::max_element(n1.begin(),n1.end())>prec) - return false; - } - return true; -} - /*! * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'. * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned * and result remains unchanged. - * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method. + * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method. * If in 'candidates' pool -1 value is considered as an empty value. * WARNING this method returns only ONE set of result ! */ @@ -1766,7 +1694,6 @@ bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector& candidates, i */ void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception) { - checkConnectivityFullyDefined(); MEDCouplingAutoRefCountObjectPtr revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New(); getReverseNodalConnectivity(revNodal,revNodalI); FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr); @@ -1853,49 +1780,6 @@ void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const D commonCellsIArr=commonCellsI.retn(); } -/*! - * Removes duplicates of cells from \a this mesh and returns an array mapping between - * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no - * equal cells found. - * \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] compType - specifies a cell comparison technique. Meaning of its - * valid values [0,1,2] is as follows. - * - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal - * connectivity and type. This is the strongest policy. - * - 1 : "permuted same orientation". Two cells are considered equal \c iff they - * are based on same nodes and have the same type and orientation. - * - 2 : "nodal". Two cells are considered equal \c iff they - * are based on same nodes and have the same type. This is the weakest - * policy, it can be used by users not sensitive to cell orientation. - * \param [in] startCellId - specifies the cell id at which search for equal cells - * starts. By default it is 0, which means that all cells in \a this will be - * scanned. - * \return DataArrayInt - a new instance of DataArrayInt, of length \a - * this->getNumberOfCells() before call of this method. The caller is to - * delete this array using decrRef() as it is no more needed. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * \throw If the nodal connectivity includes an invalid id. - * - * \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".
- * \ref py_mcumesh_zipConnectivityTraducer "Here is a Python example". - */ -DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception) -{ - DataArrayInt *commonCells=0,*commonCellsI=0; - findCommonCells(compType,startCellId,commonCells,commonCellsI); - MEDCouplingAutoRefCountObjectPtr commonCellsTmp(commonCells),commonCellsITmp(commonCellsI); - int newNbOfCells=-1; - MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(), - commonCellsI->end(),newNbOfCells); - MEDCouplingAutoRefCountObjectPtr ret2=ret->invertArrayO2N2N2O(newNbOfCells); - MEDCouplingAutoRefCountObjectPtr self=static_cast(buildPartOfMySelf(ret2->begin(),ret2->end(),true)); - setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true); - return ret.retn(); -} - /*! * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger @@ -1932,7 +1816,7 @@ bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int com } MEDCouplingAutoRefCountObjectPtr o2n=mesh->zipConnectivityTraducer(compType,nbOfCells); arr=o2n->substr(nbOfCells); - arr->setName(other->getName()); + arr->setName(other->getName().c_str()); int tmp; if(other->getNumberOfCells()==0) return true; @@ -1976,108 +1860,24 @@ bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataAr } } } - arr2->setName(other->getName()); + arr2->setName(other->getName().c_str()); if(arr2->presenceOfValue(0)) return false; arr=arr2.retn(); return true; } -/*! - * Merges nodes equal within \a precision and returns an array describing the - * permutation used to remove duplicate nodes. - * \param [in] precision - minimal absolute distance between two nodes at which they are - * considered not coincident. - * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed. - * \param [out] newNbOfNodes - number of nodes remaining after the removal. - * \return DataArrayInt * - the permutation array in "Old to New" mode. For more - * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller - * is to delete this array using decrRef() as it is no more needed. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * - * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".
- * \ref py_mcumesh_mergeNodes "Here is a Python example". - */ -DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes) -{ - DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes); - if(areNodesMerged) - renumberNodes(ret->getConstPointer(),newNbOfNodes); - return ret; -} - - -/*! - * Merges nodes equal within \a precision and returns an array describing the - * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location - * of merged nodes is changed to be at their barycenter. - * \param [in] precision - minimal absolute distance between two nodes at which they are - * considered not coincident. - * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed. - * \param [out] newNbOfNodes - number of nodes remaining after the removal. - * \return DataArrayInt * - the permutation array in "Old to New" mode. For more - * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller - * is to delete this array using decrRef() as it is no more needed. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * - * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".
- * \ref py_mcumesh_mergeNodes "Here is a Python example". - */ -DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes) -{ - DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes); - if(areNodesMerged) - renumberNodes2(ret->getConstPointer(),newNbOfNodes); - return ret; -} - -/*! - * Substitutes node coordinates array of \a this mesh with that of \a other mesh - * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two - * meshes match with a specified precision, else an exception is thrown and \a this - * remains unchanged. In case of success the nodal connectivity of \a this mesh - * is permuted according to new order of nodes. - * Contrary to tryToShareSameCoords() this method makes a deeper analysis of - * coordinates (and so more expensive) than simple equality. - * \param [in] other - the other mesh whose node coordinates array will be used by - * \a this mesh in case of their equality. - * \param [in] epsilon - the precision used to compare coordinates (using infinite norm). - * \throw If the coordinates array of \a this is not set. - * \throw If the coordinates array of \a other is not set. - * \throw If the coordinates of \a this and \a other do not match. - */ -void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception) +MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const { - const DataArrayDouble *coords=other.getCoords(); - if(!coords) - throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !"); - if(!_coords) - throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !"); - int otherNbOfNodes=other.getNumberOfNodes(); - MEDCouplingAutoRefCountObjectPtr newCoords=MergeNodesArray(&other,this); - _coords->incrRef(); - MEDCouplingAutoRefCountObjectPtr oldCoords=_coords; - setCoords(newCoords); - bool areNodesMerged; - int newNbOfNodes; - MEDCouplingAutoRefCountObjectPtr da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes); - if(!areNodesMerged) - { - setCoords(oldCoords); - throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !"); - } - int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes); - const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater(),maxId)); - if(pt!=da->getConstPointer()+da->getNbOfElems()) - { - setCoords(oldCoords); - throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !"); - } - setCoords(oldCoords); - renumberNodesInConn(da->getConstPointer()+otherNbOfNodes); - setCoords(coords); + if(!other) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !"); + const MEDCouplingUMesh *otherC=dynamic_cast(other); + if(!otherC) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !"); + std::vector ms(2); + ms[0]=this; + ms[1]=otherC; + return MergeUMeshesOnSameCoords(ms); } /*! @@ -2094,12 +1894,7 @@ void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& ot MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception) { if(getMeshDimension()!=-1) - { - MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step); - if(!keepCoords) - ret->zipCoords(); - return ret; - } + return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords); else { int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh "); @@ -2136,12 +1931,7 @@ MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, in MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const { if(getMeshDimension()!=-1) - { - MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end); - if(!keepCoords) - ret->zipCoords(); - return ret; - } + return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords); else { if(end-begin!=1) @@ -2156,13 +1946,13 @@ MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const /*! * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here. * - * This method allows to partially modify some cells in \b this (whose list is specified by [\b cellIdsBg, \b cellIdsEnd) ) with cells coming in \b otherOnSameCoordsThanThis. - * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis. + * This method allows to partially modify some cells in \b this (whose list is specified by [ \b cellIdsBg, \b cellIdsEnd ) ) with cells coming in \b otherOnSameCoordsThanThis. + * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis. * The number of cells of \b this will remain the same with this method. * * \param [in] begin begin of cell ids (included) of cells in this to assign * \param [in] end end of cell ids (excluded) of cells in this to assign - * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd). + * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd ). * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same */ void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception) @@ -2265,36 +2055,14 @@ void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDC } /*! - * Finds cells whose all nodes are in a given array of node ids. - * \param [in] partBg - the array of node ids. - * \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg. - * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found - * cells. The caller is to delete this array using decrRef() as it is no - * more needed. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * \throw If any cell id in \a partBg is not valid. - * - * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".
- * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example". - */ -DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const -{ - DataArrayInt *cellIdsKept=0; - fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept); - cellIdsKept->setName(getName()); - return cellIdsKept; -} - -/*! - * Keeps from \a this only cells which constituing point id are in the ids specified by ['begin','end'). + * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ). * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter. - * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not. - * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept. + * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not. + * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept. * * \param [in] begin input start of array of node ids. * \param [in] end input end of array of node ids. - * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in. + * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in. * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end. */ void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const @@ -2326,60 +2094,6 @@ void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int cellIdsKeptArr=cellIdsKept.retn(); } -/*! - * Finds cells whose all or some nodes are in a given array of node ids. - * \param [in] begin - the array of node ids. - * \param [in] end - a pointer to the (last+1)-th element of \a begin. - * \param [in] fullyIn - if \c true, then cells whose all nodes are in the - * array \a begin are returned only, else cells whose any node is in the - * array \a begin are returned. - * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found - * cells. The caller is to delete this array using decrRef() as it is no more - * needed. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * \throw If any cell id in \a begin is not valid. - * - * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".
- * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example". - */ -DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const -{ - DataArrayInt *cellIdsKept=0; - fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept); - cellIdsKept->setName(getName()); - return cellIdsKept; -} - -/*! - Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to - copy are selected basing on specified node ids and the value of \a fullyIn - parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the - array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its - node is in the array of node ids. The created mesh shares the node coordinates array - with \a this mesh. - * \param [in] begin - the array of node ids. - * \param [in] end - a pointer to the (last+1)-th element of \a begin. - * \param [in] fullyIn - if \c true, then cells whose all nodes are in the - * array \a begin are copied, else cells whose any node is in the - * array \a begin are copied. - * \return MEDCouplingPointSet * - 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 not defined. - * \throw If any node id in \a begin is not valid. - * - * \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".
- * \ref py_mcumesh_buildPartOfMySelfNode "Here is a Python example". - */ -MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const -{ - DataArrayInt *cellIdsKept=0; - fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept); - MEDCouplingAutoRefCountObjectPtr cellIdsKept2(cellIdsKept); - return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true); -} - /*! * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a * this->getMeshDimension(), that bound some cells of \a this mesh. @@ -2589,50 +2303,6 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNE return const_cast(this); } -/*! - * Permutes and possibly removes nodes as specified by \a newNodeNumbers array. - * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, - * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity - * array is modified accordingly. - * \param [in] newNodeNumbers - a permutation array, of length \a - * this->getNumberOfNodes(), in "Old to New" mode. - * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes. - * \param [in] newNbOfNodes - number of nodes remaining after renumbering. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * - * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".
- * \ref py_mcumesh_renumberNodes "Here is a Python example". - */ -void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes) -{ - MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes); - renumberNodesInConn(newNodeNumbers); -} - -/*! - * Permutes and possibly removes nodes as specified by \a newNodeNumbers array. - * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, - * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity - * array is modified accordingly. In contrast to renumberNodes(), location - * of merged nodes (whose new ids coincide) is changed to be at their barycenter. - * \param [in] newNodeNumbers - a permutation array, of length \a - * this->getNumberOfNodes(), in "Old to New" mode. - * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes. - * \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is - * actually one more than the maximal id in \a newNodeNumbers. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * - * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".
- * \ref py_mcumesh_renumberNodes "Here is a Python example". - */ -void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes) -{ - MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes); - renumberNodesInConn(newNodeNumbers); -} - /*! * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array. * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1. @@ -2693,7 +2363,7 @@ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1On /*! * This method operates a modification of the connectivity and coords in \b this. - * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this + * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)). * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1, @@ -2772,7 +2442,7 @@ void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Ex /*! * This method operates a modification of the connectivity in \b this. * Coordinates are \b NOT considered here and will remain unchanged by this method. this->_coords can ever been null for the needs of this method. - * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this + * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)). * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1, @@ -2783,7 +2453,7 @@ void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Ex * * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only - * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd). + * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). */ void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception) { @@ -2815,12 +2485,12 @@ void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, con * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell. * After the call of this method the number of cells remains the same as before. * - * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not - * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to + * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not + * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to * be strictly in [0;this->getNumberOfCells()). * - * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd). - * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and + * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ). + * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and * should be contained in[0;this->getNumberOfCells()). * * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells() @@ -3160,7 +2830,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const int mdim=getMeshDimension(); if(mdim<0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !"); - MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingUMesh::New(getName(),mdim); + MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingUMesh::New(getName().c_str(),mdim); MEDCouplingAutoRefCountObjectPtr tmp1,tmp2; bool needToCpyCT=true; if(!_nodal_connec) @@ -3443,7 +3113,7 @@ void MEDCouplingUMesh::unserialization(const std::vector& tinyInfoD, con * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2. * CellIds are given using range specified by a start an end and step. */ -MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const +MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const { checkFullyDefined(); int ncell=getNumberOfCells(); @@ -3485,12 +3155,12 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int /*! * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf. - * Keeps from \a this only cells which constituing point id are in the ids specified by ['begin','end'). + * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ). * The return newly allocated mesh will share the same coordinates as \a this. */ -MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const +MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const { - checkFullyDefined(); + checkConnectivityFullyDefined(); int ncell=getNumberOfCells(); MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingUMesh::New(); ret->_mesh_dim=_mesh_dim; @@ -5569,6 +5239,7 @@ void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Except * and \a this->getMeshDimension() != 3. * \throw If \a policy is not one of the four discussed above. * \throw If the nodal connectivity of cells is not defined. + * \sa MEDCouplingUMesh::tetrahedrize */ DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception) { @@ -6569,7 +6240,7 @@ namespace ParaMEDMEMImpl * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how * \a this is composed in cell types. * The returned array is of size 3*n where n is the number of different types present in \a this. - * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. + * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. * This parameter is kept only for compatibility with other methode listed above. */ std::vector MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception) @@ -6580,7 +6251,7 @@ std::vector MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_K const int *work=connI; int nbOfCells=getNumberOfCells(); std::size_t n=getAllTypes().size(); - std::vector ret(3*n,0); //ret[3*k+2]==0 because it has no sense here + std::vector ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here std::set types; for(std::size_t i=0;work!=connI+nbOfCells;i++) { @@ -6627,6 +6298,7 @@ DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector< throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !"); std::vector types; int nb=0; + bool isNoPflUsed=true; for(std::size_t i=0;i ret=DataArrayInt::New(); ret->alloc(nb,1); int *retPtr=ret->getPointer(); const int *connI=_nodal_connec_index->getConstPointer(); @@ -6656,21 +6329,50 @@ DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector< { i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it))); int offset=(int)std::distance(connI,i); + const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it))); + int nbOfCellsOfCurType=(int)std::distance(i,j); if(code[3*kk+2]==-1) - { - const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it))); - std::size_t pos2=std::distance(i,j); - for(std::size_t k=0;kgetConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(), - retPtr,std::bind2nd(std::plus(),offset)); + int idInIdsPerType=code[3*kk+2]; + if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size()) + { + const DataArrayInt *zePfl=idsPerType[idInIdsPerType]; + if(zePfl) + { + zePfl->checkAllocated(); + if(zePfl->getNumberOfComponents()==1) + { + for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++) + { + if(*k>=0 && *k MEDCouplingUMesh::splitByType() const { - checkFullyDefined(); + checkConnectivityFullyDefined(); const int *conn=_nodal_connec->getConstPointer(); const int *connI=_nodal_connec_index->getConstPointer(); int nbOfCells=getNumberOfCells(); @@ -7023,6 +6725,109 @@ std::vector MEDCouplingUMesh::splitByType() const return ret; } +/*! + * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured. + * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure, + * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this. + * + * \return a newly allocated instance, that the caller must manage. + * \throw If \a this contains more than one geometric type. + * \throw If the nodal connectivity of \a this is not fully defined. + * \throw If the internal data is not coherent. + */ +MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception) +{ + checkConnectivityFullyDefined(); + if(_types.size()!=1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !"); + INTERP_KERNEL::NormalizedCellType typ=*_types.begin(); + MEDCouplingAutoRefCountObjectPtr ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ); + ret->setCoords(getCoords()); + MEDCoupling1SGTUMesh *retC=dynamic_cast((MEDCoupling1GTUMesh*)ret); + if(retC) + { + MEDCouplingAutoRefCountObjectPtr c=convertNodalConnectivityToStaticGeoTypeMesh(); + retC->setNodalConnectivity(c); + } + else + { + MEDCoupling1DGTUMesh *retD=dynamic_cast((MEDCoupling1GTUMesh*)ret); + if(!retD) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !"); + DataArrayInt *c=0,*ci=0; + convertNodalConnectivityToDynamicGeoTypeMesh(c,ci); + MEDCouplingAutoRefCountObjectPtr cs(c),cis(ci); + retD->setNodalConnectivity(cs,cis); + } + return ret.retn(); +} + +DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception) +{ + checkConnectivityFullyDefined(); + if(_types.size()!=1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !"); + INTERP_KERNEL::NormalizedCellType typ=*_types.begin(); + const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ); + if(cm.isDynamic()) + { + std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but "; + oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + int nbCells=getNumberOfCells(); + int typi=(int)typ; + int nbNodesPerCell=(int)cm.getNumberOfNodes(); + MEDCouplingAutoRefCountObjectPtr connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1); + int *outPtr=connOut->getPointer(); + const int *conn=_nodal_connec->begin(); + const int *connI=_nodal_connec_index->begin(); + nbNodesPerCell++; + for(int i=0;igetNumberOfTuples(); + if(lgth c(DataArrayInt::New()),ci(DataArrayInt::New()); + c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1); + int *cp(c->getPointer()),*cip(ci->getPointer()); + const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin()); + cip[0]=0; + for(int i=0;i=1) + { + if((strt>=0 && strt=0 && stop<=lgth)) + cp=std::copy(incp+strt,incp+stop,cp); + else + throw INTERP_KERNEL::Exception(msg0); + } + else + throw INTERP_KERNEL::Exception(msg0); + cip[1]=cip[0]+delta; + } + nodalConn=c.retn(); nodalConnIndex=ci.retn(); +} + /*! * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions. * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt). @@ -7092,7 +6897,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(cons /*! * This method returns a newly created DataArrayInt instance. - * This method retrieves cell ids in [begin,end) that have the type 'type'. + * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type. */ DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception) { @@ -7635,7 +7440,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vectoralloc(curNbOfCells,1); std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer()); offset+=curNbOfCells; - tmp->setName(meshes[i]->getName()); + tmp->setName(meshes[i]->getName().c_str()); corr[i]=tmp; } return ret.retn(); @@ -7749,7 +7554,7 @@ void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vectorcheckAllocated(); arrIndxIn->checkAllocated(); + if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !"); std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd); const int *arrInPtr=arrIn->getConstPointer(); const int *arrIndxPtr=arrIndxIn->getConstPointer(); int nbOfGrps=arrIndxIn->getNumberOfTuples()-1; + if(nbOfGrps<0) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !"); int maxSizeOfArr=arrIn->getNumberOfTuples(); MEDCouplingAutoRefCountObjectPtr arro=DataArrayInt::New(); MEDCouplingAutoRefCountObjectPtr arrIo=DataArrayInt::New(); @@ -8988,17 +8799,89 @@ void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const arrIndexOut=arrIo.retn(); } +/*! + * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn. + * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ). + * The selection of extraction is done standardly in new2old format. + * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut). + * + * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included) + * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded) + * \param [in] arrIn arr origin array from which the extraction will be done. + * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn + * \param [out] arrOut the resulting array + * \param [out] arrIndexOut the index array of the resulting array \b arrOut + * \sa MEDCouplingUMesh::ExtractFromIndexedArrays + */ +void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, + DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception) +{ + if(!arrIn || !arrIndxIn) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !"); + arrIn->checkAllocated(); arrIndxIn->checkAllocated(); + if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !"); + int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice "); + const int *arrInPtr=arrIn->getConstPointer(); + const int *arrIndxPtr=arrIndxIn->getConstPointer(); + int nbOfGrps=arrIndxIn->getNumberOfTuples()-1; + if(nbOfGrps<0) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !"); + int maxSizeOfArr=arrIn->getNumberOfTuples(); + MEDCouplingAutoRefCountObjectPtr arro=DataArrayInt::New(); + MEDCouplingAutoRefCountObjectPtr arrIo=DataArrayInt::New(); + arrIo->alloc((int)(sz+1),1); + int idsIt=idsOfSelectStart; + int *work=arrIo->getPointer(); + *work++=0; + int lgth=0; + for(std::size_t i=0;i=0 && idsIt=work[-1]) + *work=lgth; + else + { + std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt; + oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + arro->alloc(lgth,1); + work=arro->getPointer(); + idsIt=idsOfSelectStart; + for(std::size_t i=0;i=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr) + work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work); + else + { + std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx["; + oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + arrOut=arro.retn(); + arrIndexOut=arrIo.retn(); +} + /*! * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn. - * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [\b idsOfSelectBg, \b idsOfSelectEnd) and for - * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex). + * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) and for + * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex). * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays. * * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included) * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded) * \param [in] arrIn arr origin array from which the extraction will be done. * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn - * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd) + * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd ) * \param [in] srcArrIndex index array of \b srcArr * \param [out] arrOut the resulting array * \param [out] arrIndexOut the index array of the resulting array \b arrOut @@ -9064,7 +8947,7 @@ void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const in * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded) * \param [in,out] arrInOut arr origin array from which the extraction will be done. * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn - * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd) + * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd ) * \param [in] srcArrIndex index array of \b srcArr * * \sa MEDCouplingUMesh::SetPartOfIndexedArrays @@ -9194,7 +9077,7 @@ DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vecto /*! * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn. - * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [\b idsOfSelectBg, \b idsOfSelectEnd) and for + * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) and for * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex). * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays. * @@ -9324,7 +9207,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTER std::vector partition=partitionBySpreadZone(); std::vector< MEDCouplingAutoRefCountObjectPtr > partitionAuto; partitionAuto.reserve(partition.size()); std::copy(partition.begin(),partition.end(),std::back_insert_iterator > >(partitionAuto)); - MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingUMesh::New(getName(),mdim); + MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingUMesh::New(getName().c_str(),mdim); ret->setCoords(getCoords()); ret->allocateCells((int)partition.size()); // @@ -9358,7 +9241,6 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTER */ std::vector MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception) { - //#if 0 int nbOfCellsCur=getNumberOfCells(); std::vector ret; if(nbOfCellsCur<=0) @@ -9378,36 +9260,6 @@ std::vector MEDCouplingUMesh::partitionBySpreadZone() const thro for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=ret2.begin();it!=ret2.end();it++) ret.push_back((*it).retn()); return ret; - //#endif -#if 0 - int nbOfCellsCur=getNumberOfCells(); - DataArrayInt *neigh=0,*neighI=0; - computeNeighborsOfCells(neigh,neighI); - MEDCouplingAutoRefCountObjectPtr neighAuto(neigh),neighIAuto(neighI); - MEDCouplingAutoRefCountObjectPtr ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota(); - std::vector ret; - std::vector< MEDCouplingAutoRefCountObjectPtr > ret2; - while(nbOfCellsCur>0) - { - MEDCouplingAutoRefCountObjectPtr tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto); - MEDCouplingAutoRefCountObjectPtr tmp3=tmp->buildComplement(nbOfCellsCur); - MEDCouplingAutoRefCountObjectPtr tmp2=ids->selectByTupleId(tmp->begin(),tmp->end()); - ret2.push_back(tmp2); ret.push_back(tmp2); - nbOfCellsCur=tmp3->getNumberOfTuples(); - if(nbOfCellsCur>0) - { - ids=ids->selectByTupleId(tmp3->begin(),tmp3->end()); - MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI); - neighAuto=neigh; - neighIAuto=neighI; - MEDCouplingAutoRefCountObjectPtr renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples()); - neighAuto->transformWithIndArr(renum->begin(),renum->end()); - } - } - for(std::vector::const_iterator it=ret.begin();it!=ret.end();it++) - (*it)->incrRef(); - return ret; -#endif } /*! @@ -9434,6 +9286,78 @@ DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vec return ret.retn(); } +/*! + * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set. + * All cells in \a this are expected to be linear 3D cells. + * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh. + * It leads to an increase to number of cells. + * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work. + * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints + * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh. + * + * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells. + * For all other cells, the splitting policy will be ignored. + * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added. + * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell, + * an id of old cell producing it. The caller is to delete this array using + * decrRef() as it is no more needed. + * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells. + * + * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3). + * \throw If \a this is not fully constituted with linear 3D cells. + * \sa MEDCouplingUMesh::simplexize + */ +MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception) +{ + INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy); + checkConnectivityFullyDefined(); + if(getMeshDimension()!=3 || getSpaceDimension()!=3) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !"); + int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes()); + MEDCouplingAutoRefCountObjectPtr ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4)); + MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(nbOfCells,1); + int *retPt(ret->getPointer()); + MEDCouplingAutoRefCountObjectPtr newConn(DataArrayInt::New()); newConn->alloc(0,1); + MEDCouplingAutoRefCountObjectPtr addPts(DataArrayDouble::New()); addPts->alloc(0,1); + const int *oldc(_nodal_connec->begin()); + const int *oldci(_nodal_connec_index->begin()); + const double *coords(_coords->begin()); + for(int i=0;i a; std::vector b; + INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b); + std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet; + const int *aa(&a[0]); + if(!b.empty()) + { + for(std::vector::iterator it=a.begin();it!=a.end();it++) + if(*it<0) + *it=(-(*(it))-1+nbNodes); + addPts->insertAtTheEnd(b.begin(),b.end()); + nbNodes+=(int)b.size()/3; + } + for(std::size_t j=0;jinsertAtTheEnd(aa,aa+4); + } + if(!addPts->empty()) + { + addPts->rearrange(3); + nbOfAdditionalPoints=addPts->getNumberOfTuples(); + addPts=DataArrayDouble::Aggregate(getCoords(),addPts); + ret0->setCoords(addPts); + } + else + { + nbOfAdditionalPoints=0; + ret0->setCoords(getCoords()); + } + ret0->setNodalConnectivity(newConn); + // + ret->computeOffsets2(); + n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1); + return ret0.retn(); +} + MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)), _own_cell(true),_cell_id(-1),_nb_cell(0) {