X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingUMesh.cxx;h=7a4aae408c4ec5742cdfd77c61269c1eab2ead3c;hb=659f8c67d0348350e12fde38fe8c4de1ff95dffe;hp=8443998f0adefdfc1ca001a2e2a11fbc3c6e8e52;hpb=29f721b8ca46ed5d7872a8a23dd891c46d74ba10;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index 8443998f0..7a4aae408 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -1,9 +1,9 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -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,12 +27,13 @@ #include "InterpolationUtils.hxx" #include "PointLocatorAlgos.txx" #include "BBTree.txx" +#include "BBTreeDst.txx" #include "SplitterTetra.hxx" #include "DirectedBoundingBox.hxx" +#include "InterpKernelMatrixTools.hxx" #include "InterpKernelMeshQuality.hxx" #include "InterpKernelCellSimplify.hxx" #include "InterpKernelGeo2DEdgeArcCircle.hxx" -#include "MEDCouplingAutoRefCountObjectPtr.hxx" #include "InterpKernelAutoPtr.hxx" #include "InterpKernelGeo2DNode.hxx" #include "InterpKernelGeo2DEdgeLin.hxx" @@ -56,7 +58,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::New() return new MEDCouplingUMesh; } -MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim) +MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim) { MEDCouplingUMesh *ret=new MEDCouplingUMesh; ret->setName(meshName); @@ -64,24 +66,70 @@ 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); } -std::size_t MEDCouplingUMesh::getHeapMemorySize() const +/*! + * 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 +{ + 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) +{ + 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::getHeapMemorySizeWithoutChildren() const +{ + std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren()); + return ret; +} + +std::vector MEDCouplingUMesh::getDirectChildren() const { - std::size_t ret=0; + std::vector ret(MEDCouplingPointSet::getDirectChildren()); if(_nodal_connec) - ret+=_nodal_connec->getHeapMemorySize(); + ret.push_back(_nodal_connec); if(_nodal_connec_index) - ret+=_nodal_connec_index->getHeapMemorySize(); - return MEDCouplingPointSet::getHeapMemorySize()+ret; + ret.push_back(_nodal_connec_index); + return ret; } void MEDCouplingUMesh::updateTime() const @@ -102,12 +150,19 @@ MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_conne } /*! - * 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) +void MEDCouplingUMesh::checkCoherency() const { if(_mesh_dim<-1) throw INTERP_KERNEL::Exception("No mesh dimension specified !"); @@ -129,6 +184,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) @@ -136,14 +194,28 @@ 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 !"); } /*! - * 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. + * 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) +void MEDCouplingUMesh::checkCoherency1(double eps) const { checkCoherency(); if(_mesh_dim==-1) @@ -199,21 +271,56 @@ void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Ex } } -void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception) + +/*! + * 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 { 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(); @@ -232,12 +339,16 @@ void MEDCouplingUMesh::allocateCells(int nbOfCells) } /*! - * 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) +void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type); if(_nodal_connec_index==0) @@ -267,7 +378,11 @@ 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() { @@ -289,27 +404,59 @@ 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. */ -MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception) +MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() { if(!checkConsecutiveCellTypes()) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !"); 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. + * \sa MEDCouplingUMesh::getAllGeoTypesSorted + */ std::set MEDCouplingUMesh::getAllGeoTypes() const { return _types; } /*! - * This method is a method that compares 'this' and 'other'. + * This method returns the sorted list of geometric types in \a this. + * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this + * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type. + * + * \throw if connectivity in \a this is not correctly defined. + * + * \sa MEDCouplingMesh::getAllGeoTypes + */ +std::vector MEDCouplingUMesh::getAllGeoTypesSorted() const +{ + std::vector ret; + checkConnectivityFullyDefined(); + int nbOfCells(getNumberOfCells()); + if(nbOfCells==0) + return ret; + if(getMeshLength()<1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !"); + const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()); + ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]); + for(int i=1;i(other); @@ -393,116 +548,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'. + * 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::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec, - DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception) +void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const { - const MEDCouplingUMesh *otherC=dynamic_cast(other); + MEDCouplingPointSet::checkFastEquivalWith(other,prec); + 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=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1); - nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn(); - cellCor=cellCor2->isIdentity()?0:cellCor2.retn(); -} - -/*! - * 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 ! + 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. * - * 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'. + * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".
+ * \ref py_mcumesh_getReverseNodalConnectivity "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(); -} - -/*! - * This method checks fastly that 'this' and 'other' are equal. - */ -void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception) -{ - 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. - */ -void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception) +void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const { 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(); @@ -520,8 +609,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) +MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const { - 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 +{ + 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) +MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const { - return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer); + return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer); } /*! @@ -605,7 +803,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *d * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx. * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors. */ -void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception) +void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const { MEDCouplingAutoRefCountObjectPtr desc=DataArrayInt::New(); MEDCouplingAutoRefCountObjectPtr descIndx=DataArrayInt::New(); @@ -668,8 +866,11 @@ 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. */ -MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception) +template +MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const { + 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(); @@ -678,7 +879,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt const int *conn=_nodal_connec->getConstPointer(); const int *connIndex=_nodal_connec_index->getConstPointer(); std::string name="Mesh constituent of "; name+=getName(); - MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-1); + MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA); ret->setCoords(getCoords()); ret->allocateCells(2*nbOfCells); descIndx->alloc(nbOfCells+1,1); @@ -689,12 +890,13 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt int pos=connIndex[eltId]; int posP1=connIndex[eltId+1]; const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]); - unsigned nbOfSons=cm.getNumberOfSons2(conn+pos+1,posP1-pos-1); + SonsGenerator sg(cm); + unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1); INTERP_KERNEL::AutoPtr tmp=new int[posP1-pos]; for(unsigned i=0;i=0) revNodalIndxPtr[tmp[k]+1]++; @@ -786,20 +988,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) { @@ -817,7 +1025,7 @@ void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const i if(*iter>=0 && *iter