X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingUMesh.cxx;h=05eaf2661ff20381fc6c6d5738560d04e8cd5249;hb=b219559763498c4bd10c730cd3d2c62b1eed45db;hp=38da9fe17f562d63eae87ccc4ebfb12866aeb4c6;hpb=7f53ba0ad6eebec56c2936b923ac3ae728f41074;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx old mode 100644 new mode 100755 index 38da9fe17..05eaf2661 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D +// Copyright (C) 2007-2019 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 @@ -16,11 +16,11 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Anthony Geay (CEA/DEN) +// Author : Anthony Geay (EDF R&D) -#include "MEDCouplingUMesh.hxx" +#include "MEDCouplingUMesh.txx" +#include "MEDCouplingCMesh.hxx" #include "MEDCoupling1GTUMesh.hxx" -#include "MEDCouplingMemArray.txx" #include "MEDCouplingFieldDouble.hxx" #include "MEDCouplingSkyLineArray.hxx" #include "CellModel.hxx" @@ -41,6 +41,8 @@ #include "InterpKernelGeo2DEdgeLin.hxx" #include "InterpKernelGeo2DEdgeArcCircle.hxx" #include "InterpKernelGeo2DQuadraticPolygon.hxx" +#include "OrientationInverter.hxx" +#include "MEDCouplingUMesh_internal.hxx" #include #include @@ -54,8 +56,8 @@ using namespace MEDCoupling; double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14; /// @cond INTERNAL -const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED }; -const int MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,36,4}; +const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_PENTA18, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED }; +const mcIdType MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,32,-1,25,42,36,4}; /// @endcond MEDCouplingUMesh *MEDCouplingUMesh::New() @@ -75,7 +77,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared * between \a this and the new mesh. * \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to - * delete this mesh using decrRef() as it is no more needed. + * delete this mesh using decrRef() as it is no more needed. */ MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const { @@ -88,7 +90,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const * \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 MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to - * delete this mesh using decrRef() as it is no more needed. + * delete this mesh using decrRef() as it is no more needed. */ MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const { @@ -98,7 +100,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const /*! * This method behaves mostly like MEDCouplingUMesh::deepCopy 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::deepCopy */ @@ -106,7 +108,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const { checkConnectivityFullyDefined(); MCAuto ret=clone(false); - MCAuto c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy()); + MCAuto c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy()); ret->setConnectivity(c,ci); return ret.retn(); } @@ -174,7 +176,7 @@ void MEDCouplingUMesh::checkConsistencyLight() const MEDCouplingPointSet::checkConsistencyLight(); for(std::set::const_iterator iter=_types.begin();iter!=_types.end();iter++) { - if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim) + if(ToIdType(INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension())!=_mesh_dim) { std::ostringstream message; message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter); @@ -225,22 +227,22 @@ void MEDCouplingUMesh::checkConsistency(double eps) const if(_mesh_dim==-1) return ; int meshDim=getMeshDimension(); - int nbOfNodes=getNumberOfNodes(); - int nbOfCells=getNumberOfCells(); - const int *ptr=_nodal_connec->getConstPointer(); - const int *ptrI=_nodal_connec_index->getConstPointer(); - for(int i=0;igetConstPointer(); + const mcIdType *ptrI=_nodal_connec_index->getConstPointer(); + for(mcIdType i=0;i=0) { if(nodeId>=nbOfNodes) @@ -299,9 +301,10 @@ void MEDCouplingUMesh::setMeshDimension(int meshDim) } /*! - * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted, - * the less will the library need to reallocate memory. 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. + * Allocates memory to store an estimation of the given number of cells. + * The closer the estimation to the number of cells effectively inserted, the less need the library requires + * to reallocate memory. If the number of cells to be inserted is not known simply assign 0 to this parameter. + * If a nodal connectivity previously 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. * @@ -310,7 +313,7 @@ void MEDCouplingUMesh::setMeshDimension(int meshDim) * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example". * \endif */ -void MEDCouplingUMesh::allocateCells(int nbOfCells) +void MEDCouplingUMesh::allocateCells(mcIdType nbOfCells) { if(nbOfCells<0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !"); @@ -322,10 +325,10 @@ void MEDCouplingUMesh::allocateCells(int nbOfCells) { _nodal_connec->decrRef(); } - _nodal_connec_index=DataArrayInt::New(); + _nodal_connec_index=DataArrayIdType::New(); _nodal_connec_index->reserve(nbOfCells+1); _nodal_connec_index->pushBackSilent(0); - _nodal_connec=DataArrayInt::New(); + _nodal_connec=DataArrayIdType::New(); _nodal_connec->reserve(2*nbOfCells); _types.clear(); declareAsNew(); @@ -337,28 +340,28 @@ void MEDCouplingUMesh::allocateCells(int nbOfCells) * \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. - * + * * \if ENABLE_EXAMPLES * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".
* \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example". * \endif */ -void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) +void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, mcIdType size, const mcIdType *nodalConnOfCell) { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type); if(_nodal_connec_index==0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !"); - if((int)cm.getDimension()==_mesh_dim) + if(ToIdType(cm.getDimension())==_mesh_dim) { if(!cm.isDynamic()) - if(size!=(int)cm.getNumberOfNodes()) + if(size!=ToIdType(cm.getNumberOfNodes())) { std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size; oss << " ! Expecting " << cm.getNumberOfNodes() << " !"; throw INTERP_KERNEL::Exception(oss.str()); } - int idx=_nodal_connec_index->back(); - int val=idx+size+1; + mcIdType idx=_nodal_connec_index->back(); + mcIdType val=idx+size+1; _nodal_connec_index->pushBackSilent(val); _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size); _types.insert(type); @@ -375,7 +378,7 @@ void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, in /*! * Compacts data arrays to release unused memory. This method is to be called after * finishing cell insertion using \a this->insertNextCell(). - * + * * \if ENABLE_EXAMPLES * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".
* \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example". @@ -401,7 +404,7 @@ MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator() /*! * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated. - * If \a 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 the 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. */ @@ -429,21 +432,21 @@ std::set MEDCouplingUMesh::getAllGeoTypes() c * 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()); + mcIdType nbOfCells=getNumberOfCells(); if(nbOfCells==0) return ret; if(getNodalConnectivityArrayLen()<1) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !"); - const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()); + const mcIdType *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()); ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]); - for(int i=1;i(other); if(!otherC) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); } /*! @@ -571,133 +574,53 @@ void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double * \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: + * 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. - * + * * \if ENABLE_EXAMPLES * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".
* \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example". * \endif */ -void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const +void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayIdType *revNodal, DataArrayIdType *revNodalIndx) const { checkFullyDefined(); - int nbOfNodes=getNumberOfNodes(); - int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int)); - revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1); + mcIdType nbOfNodes(getNumberOfNodes()); + mcIdType *revNodalIndxPtr=(mcIdType *)malloc((nbOfNodes+1)*sizeof(mcIdType)); + revNodalIndx->useArray(revNodalIndxPtr,true,DeallocType::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(); - int nbOfCells=getNumberOfCells(); - int nbOfEltsInRevNodal=0; - for(int eltId=0;eltIdbegin()),*connIndex(_nodal_connec_index->begin()); + mcIdType nbOfCells(getNumberOfCells()),nbOfEltsInRevNodal(0); + for(mcIdType eltId=0;eltId=0)//for polyhedrons { nbOfEltsInRevNodal++; revNodalIndxPtr[(*iter)+1]++; } } - std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus()); - int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int)); - revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1); + std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus()); + mcIdType *revNodalPtr=(mcIdType *)malloc(nbOfEltsInRevNodal*sizeof(mcIdType)); + revNodal->useArray(revNodalPtr,true,DeallocType::C_DEALLOC,nbOfEltsInRevNodal,1); std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1); - for(int eltId=0;eltId=0)//for polyhedrons - *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to(),-1))=eltId; - } -} - -/// @cond INTERNAL - -int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2) -{ - return id; -} - -int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2) -{ - if(!compute) - return id+1; - else - { - if(cm.getOrientationStatus(nb,conn1,conn2)) - return id+1; - else - return -(id+1); + *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to(),-1))=eltId; } } -class MinusOneSonsGenerator -{ -public: - MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { } - unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); } - unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); } - static const int DELTA=1; -private: - const INTERP_KERNEL::CellModel& _cm; -}; - -class MinusOneSonsGeneratorBiQuadratic -{ -public: - MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { } - unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); } - unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); } - static const int DELTA=1; -private: - const INTERP_KERNEL::CellModel& _cm; -}; - -class MinusTwoSonsGenerator -{ -public: - MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { } - unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); } - unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); } - static const int DELTA=2; -private: - const INTERP_KERNEL::CellModel& _cm; -}; - -class MicroEdgesGenerator2D -{ -public: - MicroEdgesGenerator2D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { } - unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); } - unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); } - static const int DELTA=1; -private: - const INTERP_KERNEL::CellModel& _cm; -}; - -class MicroEdgesGenerator3D -{ -public: - MicroEdgesGenerator3D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { } - unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); } - unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); } - static const int DELTA=2; -private: - const INTERP_KERNEL::CellModel& _cm; -}; - -/// @endcond - /*! * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays @@ -705,7 +628,7 @@ private: * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) 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 (\ref numbering-indirect) describe the reverse descending connectivity, - * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh. + * 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, @@ -735,14 +658,14 @@ private: * \throw If the nodal connectivity of cells is node defined. * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a * revDescIndx == NULL. - * + * * \if ENABLE_EXAMPLES * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".
* \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example". * \endif * \sa buildDescendingConnectivity2() */ -MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const +MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *revDesc, DataArrayIdType *revDescIndx) const { return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer); } @@ -754,7 +677,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *de * 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 +MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *revDesc, DataArrayIdType *revDescIndx) const { checkFullyDefined(); if(getMeshDimension()!=3) @@ -764,11 +687,11 @@ MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataAr /*! * This method computes the micro edges constituting each cell in \a this. Micro edge is an edge for non quadratic cells. Micro edge is an half edge for quadratic cells. - * This method works for both meshes with mesh dimenstion equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...) + * This method works for both meshes with mesh dimension equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...) * * \sa explode3DMeshTo1D, buildDescendingConnectiviy */ -MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const +MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *revDesc, DataArrayIdType *revDescIndx) const { checkFullyDefined(); switch(getMeshDimension()) @@ -795,7 +718,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc * 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 (\ref numbering-indirect) describe the reverse descending connectivity, - * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh. + * 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, @@ -826,14 +749,14 @@ MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc * \throw If the nodal connectivity of cells is node defined. * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a * revDescIndx == NULL. - * + * * \if ENABLE_EXAMPLES * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".
* \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example". * \endif * \sa buildDescendingConnectivity() */ -MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const +MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *revDesc, DataArrayIdType *revDescIndx) const { return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer); } @@ -854,17 +777,41 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *d * \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 (\ref numbering-indirect). */ -void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const +void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayIdType *&neighbors, DataArrayIdType *&neighborsIndx) const { - MCAuto desc=DataArrayInt::New(); - MCAuto descIndx=DataArrayInt::New(); - MCAuto revDesc=DataArrayInt::New(); - MCAuto revDescIndx=DataArrayInt::New(); + MCAuto desc=DataArrayIdType::New(); + MCAuto descIndx=DataArrayIdType::New(); + MCAuto revDesc=DataArrayIdType::New(); + MCAuto revDescIndx=DataArrayIdType::New(); MCAuto meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx); meshDM1=0; ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx); } +void MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne(const DataArrayIdType *nodeNeigh, const DataArrayIdType *nodeNeighI, MCAuto& cellNeigh, MCAuto& cellNeighIndex) const +{ + if(!nodeNeigh || !nodeNeighI) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : null pointer !"); + checkConsistencyLight(); + nodeNeigh->checkAllocated(); nodeNeighI->checkAllocated(); + nodeNeigh->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh"); + nodeNeighI->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh index"); + nodeNeighI->checkNbOfTuples(1+getNumberOfNodes(),"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : invalid length"); + mcIdType nbCells=getNumberOfCells(); + const mcIdType *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()),*ne(nodeNeigh->begin()),*nei(nodeNeighI->begin()); + cellNeigh=DataArrayIdType::New(); cellNeigh->alloc(0,1); cellNeighIndex=DataArrayIdType::New(); cellNeighIndex->alloc(1,1); cellNeighIndex->setIJ(0,0,0); + for(mcIdType i=0;i s; + for(const mcIdType *it=c+ci[i]+1;it!=c+ci[i+1];it++) + if(*it>=0) + s.insert(ne+nei[*it],ne+nei[*it+1]); + s.erase(i); + cellNeigh->insertAtTheEnd(s.begin(),s.end()); + cellNeighIndex->pushBackSilent(cellNeigh->getNumberOfTuples()); + } +} + /*! * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm * of MEDCouplingUMesh::computeNeighborsOfCells. @@ -885,27 +832,27 @@ void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArr * 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::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx, - DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) +void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayIdType *desc, const DataArrayIdType *descIndx, const DataArrayIdType *revDesc, const DataArrayIdType *revDescIndx, + DataArrayIdType *&neighbors, DataArrayIdType *&neighborsIndx) { if(!desc || !descIndx || !revDesc || !revDescIndx) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !"); - const int *descPtr=desc->getConstPointer(); - const int *descIPtr=descIndx->getConstPointer(); - const int *revDescPtr=revDesc->getConstPointer(); - const int *revDescIPtr=revDescIndx->getConstPointer(); + const mcIdType *descPtr=desc->begin(); + const mcIdType *descIPtr=descIndx->begin(); + const mcIdType *revDescPtr=revDesc->begin(); + const mcIdType *revDescIPtr=revDescIndx->begin(); // - int nbCells=descIndx->getNumberOfTuples()-1; - MCAuto out0=DataArrayInt::New(); - MCAuto out1=DataArrayInt::New(); out1->alloc(nbCells+1,1); - int *out1Ptr=out1->getPointer(); + mcIdType nbCells=descIndx->getNumberOfTuples()-1; + MCAuto out0=DataArrayIdType::New(); + MCAuto out1=DataArrayIdType::New(); out1->alloc(nbCells+1,1); + mcIdType *out1Ptr=out1->getPointer(); *out1Ptr++=0; out0->reserve(desc->getNumberOfTuples()); - for(int i=0;i s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]); + std::set s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]); s.erase(i); out0->insertAtTheEnd(s.begin(),s.end()); } @@ -915,6 +862,35 @@ void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, cons neighborsIndx=out1.retn(); } +/*! + * Explodes \a this into edges whatever its dimension. + */ +MCAuto MEDCouplingUMesh::explodeIntoEdges(MCAuto& desc, MCAuto& descIndex, MCAuto& revDesc, MCAuto& revDescIndx) const +{ + checkFullyDefined(); + int mdim(getMeshDimension()); + desc=DataArrayIdType::New(); descIndex=DataArrayIdType::New(); revDesc=DataArrayIdType::New(); revDescIndx=DataArrayIdType::New(); + MCAuto mesh1D; + switch(mdim) + { + case 3: + { + mesh1D=explode3DMeshTo1D(desc,descIndex,revDesc,revDescIndx); + break; + } + case 2: + { + mesh1D=buildDescendingConnectivity(desc,descIndex,revDesc,revDescIndx); + break; + } + default: + { + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2] !"); + } + } + return mesh1D; +} + /*! * \b 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 calls @@ -929,13 +905,15 @@ void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, cons * The number of tuples is equal to the last values in \b neighborsIndx. * \param [out] neighborsIdx 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. + * + * \sa MEDCouplingUMesh::computeEnlargedNeighborsOfNodes */ -void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const +void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayIdType *&neighbors, DataArrayIdType *&neighborsIdx) const { checkFullyDefined(); - int mdim(getMeshDimension()),nbNodes(getNumberOfNodes()); - MCAuto desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New()); - MCAuto mesh1D; + mcIdType mdim(getMeshDimension()),nbNodes(getNumberOfNodes()); + MCAuto desc(DataArrayIdType::New()),descIndx(DataArrayIdType::New()),revDesc(DataArrayIdType::New()),revDescIndx(DataArrayIdType::New()); + MCConstAuto mesh1D; switch(mdim) { case 3: @@ -950,8 +928,7 @@ void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArr } case 1: { - mesh1D=const_cast(this); - mesh1D->incrRef(); + mesh1D.takeRef(this); break; } default: @@ -959,149 +936,65 @@ void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArr throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !"); } } - desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0; + desc=DataArrayIdType::New(); descIndx=DataArrayIdType::New(); revDesc=0; revDescIndx=0; mesh1D->getReverseNodalConnectivity(desc,descIndx); - MCAuto ret0(DataArrayInt::New()); + MCAuto ret0(DataArrayIdType::New()); ret0->alloc(desc->getNumberOfTuples(),1); - int *r0Pt(ret0->getPointer()); - const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin()); - for(int i=0;igetPointer()); + const mcIdType *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin()); + for(mcIdType i=0;i -MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const +void MEDCouplingUMesh::computeEnlargedNeighborsOfNodes(MCAuto &neighbors, MCAuto& neighborsIdx) 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(); - MCAuto revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero(); - int *revNodalIndxPtr=revNodalIndx->getPointer(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connIndex=_nodal_connec_index->getConstPointer(); - std::string name="Mesh constituent of "; name+=getName(); - MCAuto ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA); - ret->setCoords(getCoords()); - ret->allocateCells(2*nbOfCells); - descIndx->alloc(nbOfCells+1,1); - MCAuto revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells); - int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0; - for(int eltId=0;eltId tmp=new int[posP1-pos]; - for(unsigned i=0;i=0) - revNodalIndxPtr[tmp[k]+1]++; - ret->insertNextCell(cmsId,nbOfNodesSon,tmp); - revDesc2->pushBackSilent(eltId); - } - descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons; - } - int nbOfCellsM1=ret->getNumberOfCells(); - std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus()); - MCAuto revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1); - std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1); - int *revNodalPtr=revNodal->getPointer(); - const int *connM1=ret->getNodalConnectivity()->getConstPointer(); - const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer(); - for(int eltId=0;eltId=0)//for polyhedrons - *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to(),-1))=eltId; - } - // - DataArrayInt *commonCells=0,*commonCellsI=0; - FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI); - MCAuto commonCellsTmp(commonCells),commonCellsITmp(commonCellsI); - const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer()); - int newNbOfCellsM1=-1; - MCAuto o2nM1=DataArrayInt::ConvertIndexArrayToO2N(nbOfCellsM1,commonCells->begin(), - commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1); - std::vector isImpacted(nbOfCellsM1,false); - for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++) - for(int work2=work[0];work2!=work[1];work2++) - isImpacted[commonCellsPtr[work2]]=true; - const int *o2nM1Ptr=o2nM1->getConstPointer(); - MCAuto n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1); - const int *n2oM1Ptr=n2oM1->getConstPointer(); - MCAuto ret2=static_cast(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true)); - ret2->copyTinyInfoFrom(this); - desc->alloc(descIndx->back(),1); - int *descPtr=desc->getPointer(); - const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1); - for(int i=0;ireserve(newNbOfCellsM1); - revDescIndx->alloc(newNbOfCellsM1+1,1); - int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0; - const int *revDesc2Ptr=revDesc2->getConstPointer(); - for(int i=0;ipushBackSilent(revDesc2Ptr[oldCellIdM1]); - revDescIndxPtr[0]=revDescIndxPtr[-1]+1; - } - else - { - for(int j=commonCellsIPtr[0];jpushBackSilent(revDesc2Ptr[commonCellsPtr[j]]); - revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0]; - commonCellsIPtr++; - } - } - // - return ret2.retn(); + checkFullyDefined(); + mcIdType nbOfNodes(getNumberOfNodes()); + const mcIdType *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin()); + mcIdType nbOfCells=getNumberOfCells(); + std::vector< std::set > st0(nbOfNodes); + for(mcIdType eltId=0;eltId s(strtNdlConnOfCurCell,endNdlConnOfCurCell); s.erase(-1); //for polyhedrons + for(std::set::const_iterator iter2=s.begin();iter2!=s.end();iter2++) + st0[*iter2].insert(s.begin(),s.end()); + } + neighborsIdx=DataArrayIdType::New(); neighborsIdx->alloc(nbOfNodes+1,1); neighborsIdx->setIJ(0,0,0); + { + mcIdType *neighIdx(neighborsIdx->getPointer()); + for(std::vector< std::set >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++) + { + if ((*it).empty()) + neighIdx[1]=neighIdx[0]; + else + neighIdx[1]=neighIdx[0]+ToIdType((*it).size())-1; + } + } + neighbors=DataArrayIdType::New(); neighbors->alloc(neighborsIdx->back(),1); + { + const mcIdType *neighIdx(neighborsIdx->begin()); + mcIdType *neigh(neighbors->getPointer()),nodeId(0); + for(std::vector< std::set >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++,nodeId++) + { + std::set s(*it); s.erase(nodeId); + std::copy(s.begin(),s.end(),neigh+*neighIdx); + } + } } -struct MEDCouplingAccVisit -{ - MEDCouplingAccVisit():_new_nb_of_nodes(0) { } - int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; } - int _new_nb_of_nodes; -}; - -/// @endcond - /*! * 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 @@ -1125,18 +1018,18 @@ struct MEDCouplingAccVisit * \ref py_mcumesh_convertToPolyTypes "Here is a Python example". * \endif */ -void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd) +void MEDCouplingUMesh::convertToPolyTypes(const mcIdType *cellIdsToConvertBg, const mcIdType *cellIdsToConvertEnd) { checkFullyDefined(); int dim=getMeshDimension(); if(dim<2 || dim>3) throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !"); - int nbOfCells(getNumberOfCells()); + mcIdType nbOfCells=getNumberOfCells(); if(dim==2) { - const int *connIndex=_nodal_connec_index->getConstPointer(); - int *conn=_nodal_connec->getPointer(); - for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++) + const mcIdType *connIndex=_nodal_connec_index->begin(); + mcIdType *conn=_nodal_connec->getPointer(); + for(const mcIdType *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++) { if(*iter>=0 && *itergetPointer()); - const int *connOld(_nodal_connec->getConstPointer()); - MCAuto connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0); + mcIdType *connIndex(_nodal_connec_index->getPointer()); + const mcIdType *connOld(_nodal_connec->getConstPointer()); + MCAuto connNew(DataArrayIdType::New()),connNewI(DataArrayIdType::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0); std::vector toBeDone(nbOfCells,false); - for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++) + for(const mcIdType *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++) { if(*iter>=0 && *iterpushBackValsSilent(tmp,tmp+newLgth); - connNewI->pushBackSilent(connNewI->back()+(int)newLgth); + connNewI->pushBackSilent(connNewI->back()+ToIdType(newLgth)); delete [] tmp; } else @@ -1216,11 +1109,11 @@ void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const i */ void MEDCouplingUMesh::convertAllToPoly() { - int nbOfCells=getNumberOfCells(); - std::vector cellIds(nbOfCells); - for(int i=0;i cellIds(nbOfCells); + for(mcIdType i=0;i newCi=DataArrayInt::New(); + mcIdType nbOfCells=getNumberOfCells(); + MCAuto newCi=DataArrayIdType::New(); newCi->alloc(nbOfCells+1,1); - int *newci=newCi->getPointer(); - const int *ci=_nodal_connec_index->getConstPointer(); - const int *c=_nodal_connec->getConstPointer(); + mcIdType *newci=newCi->getPointer(); + const mcIdType *ci=_nodal_connec_index->getConstPointer(); + const mcIdType *c=_nodal_connec->getConstPointer(); newci[0]=0; - for(int i=0;i newC=DataArrayInt::New(); + MCAuto newC=DataArrayIdType::New(); newC->alloc(newci[nbOfCells],1); - int *newc=newC->getPointer(); - for(int i=0;igetPointer(); + for(mcIdType i=0;igetPointer(); - int *index=_nodal_connec_index->getPointer(); - int posOfCurCell=0; - int newPos=0; - int lgthOfCurCell; + mcIdType initMeshLgth=getNodalConnectivityArrayLen(); + mcIdType *conn=_nodal_connec->getPointer(); + mcIdType *index=_nodal_connec_index->getPointer(); + mcIdType posOfCurCell=0; + mcIdType newPos=0; + mcIdType lgthOfCurCell; bool ret=false; - for(int i=0;i tmp=new int[lgthOfCurCell-1]; - std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp); + INTERP_KERNEL::AutoPtr tmp=new mcIdType[lgthOfCurCell-1]; + std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(mcIdType *)tmp); newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth); break; } case 3: { - int nbOfFaces,lgthOfPolyhConn; - INTERP_KERNEL::AutoPtr zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn); + mcIdType nbOfFaces,lgthOfPolyhConn; + INTERP_KERNEL::AutoPtr zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn); newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth); break; } @@ -1401,9 +1294,9 @@ bool MEDCouplingUMesh::unPolyze() /*! * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3. * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged. - * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. + * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. * - * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal + * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal * precision. */ void MEDCouplingUMesh::simplifyPolyhedra(double eps) @@ -1414,19 +1307,21 @@ void MEDCouplingUMesh::simplifyPolyhedra(double eps) MCAuto coords=getCoords()->deepCopy(); coords->recenterForMaxPrecision(eps); // - int nbOfCells=getNumberOfCells(); - const int *conn=_nodal_connec->getConstPointer(); - const int *index=_nodal_connec_index->getConstPointer(); - MCAuto connINew=DataArrayInt::New(); + mcIdType nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->getConstPointer(); + const mcIdType *index=_nodal_connec_index->getConstPointer(); + MCAuto connINew=DataArrayIdType::New(); connINew->alloc(nbOfCells+1,1); - int *connINewPtr=connINew->getPointer(); *connINewPtr++=0; - MCAuto connNew=DataArrayInt::New(); connNew->alloc(0,1); + mcIdType *connINewPtr=connINew->getPointer(); *connINewPtr++=0; + MCAuto connNew=DataArrayIdType::New(); connNew->alloc(0,1); + MCAuto E_Fi(DataArrayIdType::New()), E_F(DataArrayIdType::New()), F_Ei(DataArrayIdType::New()), F_E(DataArrayIdType::New()); + MCAuto m_faces(buildDescendingConnectivity(E_F, E_Fi, F_E, F_Ei)); bool changed=false; - for(int i=0;igetConstPointer(); - const int *conn=_nodal_connec->getConstPointer(); - const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end()); - int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1; + const mcIdType *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end())); + mcIdType maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1); std::vector retS(maxElt,false); - for(int i=0;i=0) - retS[conn[j]]=true; - int sz=0; - for(int i=0;ialloc(sz,1); - int *retPtr=ret->getPointer(); - for(int i=0;i& nodeIdsInUse) const { - int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells()); - const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer()); - for(int i=0;igetConstPointer()),*conn(_nodal_connec->getConstPointer()); + for(mcIdType i=0;i=0) { if(conn[j]& nodeIdsInUse) const } } +/// @cond INTERNAL + +struct MEDCouplingAccVisit +{ + MEDCouplingAccVisit():_new_nb_of_nodes(0) { } + mcIdType operator()(mcIdType val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; } + mcIdType _new_nb_of_nodes; +}; + +/// @endcond + /*! * Finds nodes not used in any cell and returns an array giving a new id to every node * by excluding the unused nodes, for which the array holds -1. The result array is - * a mapping in "Old to New" mode. + * a mapping in "Old to New" mode. * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity. - * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a + * \return DataArrayIdType * - a new instance of DataArrayIdType. Its length is \a * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1 * if the node is unused or a new id else. The caller is to delete this - * array using decrRef() as it is no more needed. + * 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. @@ -1512,19 +1403,19 @@ void MEDCouplingUMesh::computeNodeIdsAlg(std::vector& nodeIdsInUse) const * \endif * \sa computeFetchedNodeIds, computeNodeIdsAlg() */ -DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const +DataArrayIdType *MEDCouplingUMesh::getNodeIdsInUse(mcIdType& nbrOfNodesInUse) const { nbrOfNodesInUse=-1; - int nbOfNodes(getNumberOfNodes()); - MCAuto ret=DataArrayInt::New(); + mcIdType nbOfNodes(getNumberOfNodes()); + MCAuto ret=DataArrayIdType::New(); ret->alloc(nbOfNodes,1); - int *traducer=ret->getPointer(); + mcIdType *traducer=ret->getPointer(); std::fill(traducer,traducer+nbOfNodes,-1); - int nbOfCells=getNumberOfCells(); - const int *connIndex=_nodal_connec_index->getConstPointer(); - const int *conn=_nodal_connec->getConstPointer(); - for(int i=0;igetConstPointer(); + const mcIdType *conn=_nodal_connec->getConstPointer(); + for(mcIdType i=0;i=0) { if(conn[j] ret=DataArrayInt::New(); + mcIdType nbOfCells=getNumberOfCells(); + MCAuto ret=DataArrayIdType::New(); ret->alloc(nbOfCells,1); - int *retPtr=ret->getPointer(); - const int *conn=getNodalConnectivity()->getConstPointer(); - const int *connI=getNodalConnectivityIndex()->getConstPointer(); - for(int i=0;igetPointer(); + const mcIdType *conn=getNodalConnectivity()->getConstPointer(); + const mcIdType *connI=getNodalConnectivityIndex()->getConstPointer(); + for(mcIdType i=0;i ret=DataArrayInt::New(); + mcIdType nbOfCells=getNumberOfCells(); + MCAuto ret=DataArrayIdType::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(); + mcIdType *retPtr=ret->getPointer(); + const mcIdType *conn=getNodalConnectivity()->getConstPointer(); + const mcIdType *connI=getNodalConnectivityIndex()->getConstPointer(); + for(mcIdType i=0;i s(conn+connI[i]+1,conn+connI[i+1]); + if(conn[connI[i]]!=ToIdType(INTERP_KERNEL::NORM_POLYHED)) + *retPtr=ToIdType(s.size()); else { s.erase(-1); - *retPtr=(int)s.size(); + *retPtr=ToIdType(s.size()); } } return ret.retn(); @@ -1601,19 +1492,19 @@ DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const /*! * 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. - * + * * \return a newly allocated array */ -DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const +DataArrayIdType *MEDCouplingUMesh::computeNbOfFacesPerCell() const { checkConnectivityFullyDefined(); - int nbOfCells=getNumberOfCells(); - MCAuto ret=DataArrayInt::New(); + mcIdType nbOfCells=getNumberOfCells(); + MCAuto ret=DataArrayIdType::New(); ret->alloc(nbOfCells,1); - int *retPtr=ret->getPointer(); - const int *conn=getNodalConnectivity()->getConstPointer(); - const int *connI=getNodalConnectivityIndex()->getConstPointer(); - for(int i=0;igetPointer(); + const mcIdType *conn=getNodalConnectivity()->getConstPointer(); + const mcIdType *connI=getNodalConnectivityIndex()->getConstPointer(); + for(mcIdType i=0;igetNumberOfNodes() before call of this method. The caller is to - * delete this array using decrRef() as it is no more needed. + * 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. @@ -1638,7 +1529,7 @@ DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example". * \endif */ -DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() +DataArrayIdType *MEDCouplingUMesh::zipCoordsTraducer() { return MEDCouplingPointSet::zipCoordsTraducer(); } @@ -1647,7 +1538,7 @@ DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy. * 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) +int MEDCouplingUMesh::AreCellsEqual(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2, int compType) { switch(compType) { @@ -1668,7 +1559,7 @@ int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1 /*! * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0. */ -int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2) +int MEDCouplingUMesh::AreCellsEqualPolicy0(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2) { if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2]) return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0; @@ -1678,9 +1569,9 @@ int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, in /*! * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1. */ -int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2) +int MEDCouplingUMesh::AreCellsEqualPolicy1(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2) { - int sz=connI[cell1+1]-connI[cell1]; + mcIdType sz=connI[cell1+1]-connI[cell1]; if(sz==connI[cell2+1]-connI[cell2]) { if(conn[connI[cell1]]==conn[connI[cell2]]) @@ -1691,11 +1582,11 @@ int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, in { if(dim!=1) { - int sz1=2*(sz-1); - INTERP_KERNEL::AutoPtr tmp=new int[sz1]; - int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp); + mcIdType sz1=2*(sz-1); + INTERP_KERNEL::AutoPtr tmp=new mcIdType[sz1]; + mcIdType *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(mcIdType *)tmp); std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work); - work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]); + work=std::search((mcIdType *)tmp,(mcIdType *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]); return work!=tmp+sz1?1:0; } else @@ -1711,14 +1602,14 @@ int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, in /*! * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2. */ -int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2) +int MEDCouplingUMesh::AreCellsEqualPolicy2(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2) { if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2]) { if(conn[connI[cell1]]==conn[connI[cell2]]) { - std::set s1(conn+connI[cell1]+1,conn+connI[cell1+1]); - std::set s2(conn+connI[cell2]+1,conn+connI[cell2+1]); + std::set s1(conn+connI[cell1]+1,conn+connI[cell1+1]); + std::set s2(conn+connI[cell2]+1,conn+connI[cell2+1]); return s1==s2?1:0; } } @@ -1728,12 +1619,12 @@ int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, in /*! * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account ! */ -int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2) +int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2) { if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2]) { - std::set s1(conn+connI[cell1]+1,conn+connI[cell1+1]); - std::set s2(conn+connI[cell2]+1,conn+connI[cell2+1]); + std::set s1(conn+connI[cell1]+1,conn+connI[cell1+1]); + std::set s2(conn+connI[cell2]+1,conn+connI[cell2+1]); return s1==s2?1:0; } return 0; @@ -1742,9 +1633,9 @@ int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *con /*! * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7. */ -int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2) +int MEDCouplingUMesh::AreCellsEqualPolicy7(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2) { - int sz=connI[cell1+1]-connI[cell1]; + mcIdType sz=connI[cell1+1]-connI[cell1]; if(sz==connI[cell2+1]-connI[cell2]) { if(conn[connI[cell1]]==conn[connI[cell2]]) @@ -1755,17 +1646,17 @@ int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, in { if(dim!=1) { - int sz1=2*(sz-1); - INTERP_KERNEL::AutoPtr tmp=new int[sz1]; - int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp); + mcIdType sz1=2*(sz-1); + INTERP_KERNEL::AutoPtr tmp=new mcIdType[sz1]; + mcIdType *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(mcIdType *)tmp); std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work); - work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]); + work=std::search((mcIdType *)tmp,(mcIdType *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]); if(work!=tmp+sz1) return 1; else { - std::reverse_iterator it1((int *)tmp+sz1); - std::reverse_iterator it2((int *)tmp); + std::reverse_iterator it1((mcIdType *)tmp+sz1); + std::reverse_iterator it2((mcIdType *)tmp); if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2) return 2; else @@ -1780,8 +1671,8 @@ int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, in return 1; if(!cm.isQuadratic()) { - std::reverse_iterator it1(conn+connI[cell1+1]); - std::reverse_iterator it2(conn+connI[cell1]+1); + std::reverse_iterator it1(conn+connI[cell1+1]); + std::reverse_iterator it2(conn+connI[cell1]+1); if(std::equal(it1,it2,conn+connI[cell2]+1)) return 2; return 0; @@ -1801,39 +1692,6 @@ int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, in return 0; } -/*! - * 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 MEDCouplingPointSet::zipConnectivityTraducer method. - * If in 'candidates' pool -1 value is considered as an empty value. - * WARNING this method returns only ONE set of result ! - */ -bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result) -{ - if(candidates.size()<1) - return false; - bool ret=false; - std::vector::const_iterator iter=candidates.begin(); - int start=(*iter++); - for(;iter!=candidates.end();iter++) - { - int status=AreCellsEqual(conn,connI,start,*iter,compType); - if(status!=0) - { - if(!ret) - { - result->pushBackSilent(start); - ret=true; - } - if(status==1) - result->pushBackSilent(*iter); - else - result->pushBackSilent(status==2?(*iter+1):-(*iter+1)); - } - } - return ret; -} /*! * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified @@ -1849,36 +1707,36 @@ bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector& candidates, i * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned. * \param [out] commonCellsArr common cells ids (\ref numbering-indirect) * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect) - * \return the correspondance array old to new in a newly allocated array. - * + * \return the correspondence array old to new in a newly allocated array. + * */ -void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const +void MEDCouplingUMesh::findCommonCells(int compType, mcIdType startCellId, DataArrayIdType *& commonCellsArr, DataArrayIdType *& commonCellsIArr) const { - MCAuto revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New(); + MCAuto revNodal=DataArrayIdType::New(),revNodalI=DataArrayIdType::New(); getReverseNodalConnectivity(revNodal,revNodalI); FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr); } -void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI, - DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) +void MEDCouplingUMesh::FindCommonCellsAlg(int compType, mcIdType startCellId, const DataArrayIdType *nodal, const DataArrayIdType *nodalI, const DataArrayIdType *revNodal, const DataArrayIdType *revNodalI, + DataArrayIdType *& commonCellsArr, DataArrayIdType *& commonCellsIArr) { - MCAuto commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1); - int nbOfCells=nodalI->getNumberOfTuples()-1; + MCAuto commonCells=DataArrayIdType::New(),commonCellsI=DataArrayIdType::New(); commonCells->alloc(0,1); + mcIdType nbOfCells=nodalI->getNumberOfTuples()-1; commonCellsI->reserve(1); commonCellsI->pushBackSilent(0); - const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer(); - const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer(); + const mcIdType *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer(); + const mcIdType *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer(); std::vector isFetched(nbOfCells,false); if(startCellId==0) { - for(int i=0;i(),-1)); - std::vector v,v2; + const mcIdType *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to(),-1)); + std::vector v,v2; if(connOfNode!=connPtr+connIPtr[i+1]) { - const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i); + const mcIdType *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i); v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]); connOfNode++; } @@ -1886,17 +1744,17 @@ void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const D if(*connOfNode>=0) { v=v2; - const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i); - std::vector::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin()); + const mcIdType *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i); + std::vector::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin()); v2.resize(std::distance(v2.begin(),it)); } if(v2.size()>1) { if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells)) { - int pos=commonCellsI->back(); + mcIdType pos=commonCellsI->back(); commonCellsI->pushBackSilent(commonCells->getNumberOfTuples()); - for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++) + for(const mcIdType *it=commonCells->begin()+pos;it!=commonCells->end();it++) isFetched[*it]=true; } } @@ -1905,12 +1763,12 @@ void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const D } else { - for(int i=startCellId;i(),-1)); - std::vector v,v2; + const mcIdType *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to(),-1)); + std::vector v,v2; if(connOfNode!=connPtr+connIPtr[i+1]) { v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]); @@ -1920,16 +1778,16 @@ void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const D if(*connOfNode>=0) { v=v2; - std::vector::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin()); + std::vector::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin()); v2.resize(std::distance(v2.begin(),it)); } if(v2.size()>1) { if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells)) { - int pos=commonCellsI->back(); + mcIdType pos=commonCellsI->back(); commonCellsI->pushBackSilent(commonCells->getNumberOfTuples()); - for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++) + for(const mcIdType *it=commonCells->begin()+pos;it!=commonCells->end();it++) isFetched[*it]=true; } } @@ -1946,11 +1804,11 @@ void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const D * than \a this->getNumberOfCells() in the returned array means that there is no * corresponding cell in \a this mesh. * It is expected that \a this and \a other meshes share the same node coordinates - * array, if it is not so an exception is thrown. + * array, if it is not so an exception is thrown. * \param [in] other - the mesh to compare with. * \param [in] compType - specifies a cell comparison technique. For meaning of its * valid values [0,1,2], see zipConnectivityTraducer(). - * \param [out] arr - a new instance of DataArrayInt returning correspondence + * \param [out] arr - a new instance of DataArrayIdType returning correspondence * between cells of the two meshes. It contains \a other->getNumberOfCells() * values. The caller is to delete this array using * decrRef() as it is no more needed. @@ -1964,10 +1822,10 @@ void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const D * \sa checkDeepEquivalOnSameNodesWith() * \sa checkGeoEquivalWith() */ -bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const +bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayIdType *& arr) const { MCAuto mesh=MergeUMeshesOnSameCoords(this,other); - int nbOfCells=getNumberOfCells(); + mcIdType nbOfCells=getNumberOfCells(); static const int possibleCompType[]={0,1,2}; if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int)) { @@ -1976,10 +1834,10 @@ bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int com oss << " !"; throw INTERP_KERNEL::Exception(oss.str()); } - MCAuto o2n=mesh->zipConnectivityTraducer(compType,nbOfCells); + MCAuto o2n=mesh->zipConnectivityTraducer(compType,nbOfCells); arr=o2n->subArray(nbOfCells); arr->setName(other->getName()); - int tmp; + mcIdType tmp; if(other->getNumberOfCells()==0) return true; return arr->getMaxValue(tmp)getNumberOfCells()'. * \return If \a other is fully included in 'this 'true is returned. If not false is returned. */ -bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const +bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayIdType *& arr) const { MCAuto mesh=MergeUMeshesOnSameCoords(this,other); - DataArrayInt *commonCells=0,*commonCellsI=0; - int thisNbCells=getNumberOfCells(); + DataArrayIdType *commonCells=0,*commonCellsI=0; + mcIdType thisNbCells=getNumberOfCells(); mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI); - MCAuto commonCellsTmp(commonCells),commonCellsITmp(commonCellsI); - const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer(); - int otherNbCells=other->getNumberOfCells(); - MCAuto arr2=DataArrayInt::New(); + MCAuto commonCellsTmp(commonCells),commonCellsITmp(commonCellsI); + const mcIdType *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer(); + mcIdType otherNbCells=other->getNumberOfCells(); + MCAuto arr2=DataArrayIdType::New(); arr2->alloc(otherNbCells,1); arr2->fillWithZero(); - int *arr2Ptr=arr2->getPointer(); - int nbOfCommon=commonCellsI->getNumberOfTuples()-1; - for(int i=0;igetPointer(); + mcIdType nbOfCommon=commonCellsI->getNumberOfTuples()-1; + for(mcIdType i=0;i0?1:-1; - int val=std::abs(commonCellsPtr[j])-1; + mcIdType sig=commonCellsPtr[j]>0?1:-1; + mcIdType val=std::abs(commonCellsPtr[j])-1; if(val>=thisNbCells) arr2Ptr[val-thisNbCells]=sig*(start+1); } @@ -2046,24 +1904,24 @@ MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplin /*! * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords). * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input - * cellIds is not given explicitely but by a range python like. - * + * cellIds is not given explicitly but by a range python like. + * * \param start * \param end * \param step * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called. * \return a newly allocated - * + * * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order. * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary. */ -MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const +MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(mcIdType start, mcIdType end, mcIdType step, bool keepCoords) const { if(getMeshDimension()!=-1) return static_cast(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords)); else { - int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh "); + mcIdType newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh "); if(newNbOfCells!=1) throw INTERP_KERNEL::Exception("-1D mesh has only one cell !"); if(start!=0) @@ -2086,7 +1944,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, i * array of \a this mesh, else "free" nodes are removed from the result mesh * by calling zipCoords(). * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is - * to delete this mesh using decrRef() as it is no more needed. + * 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 cell id in the array \a begin is not valid. @@ -2096,7 +1954,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, i * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example". * \endif */ -MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const +MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const mcIdType *begin, const mcIdType *end, bool keepCoords) const { if(getMeshDimension()!=-1) return static_cast(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords)); @@ -2123,7 +1981,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const in * \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) +void MEDCouplingUMesh::setPartOfMySelf(const mcIdType *cellIdsBg, const mcIdType *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) { checkConnectivityFullyDefined(); otherOnSameCoordsThanThis.checkConnectivityFullyDefined(); @@ -2135,17 +1993,17 @@ void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsE oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !"; throw INTERP_KERNEL::Exception(oss.str()); } - int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd); + mcIdType nbOfCellsToModify( ToIdType((std::distance(cellIdsBg,cellIdsEnd)))); if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells()) { std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !"; throw INTERP_KERNEL::Exception(oss.str()); } - int nbOfCells=getNumberOfCells(); - bool easyAssign=true; - const int *connI=_nodal_connec_index->getConstPointer(); - const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer(); - for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++) + mcIdType nbOfCells(getNumberOfCells()); + bool easyAssign(true); + const mcIdType *connI(_nodal_connec_index->begin()); + const mcIdType *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->begin(); + for(const mcIdType *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++) { if(*it>=0 && *it arrOutAuto(arrOut),arrIOutAuto(arrIOut); + MCAuto arrOutAuto(arrOut),arrIOutAuto(arrIOut); setConnectivity(arrOut,arrIOut,true); } } -void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) +void MEDCouplingUMesh::setPartOfMySelfSlice(mcIdType start, mcIdType end, mcIdType step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) { checkConnectivityFullyDefined(); otherOnSameCoordsThanThis.checkConnectivityFullyDefined(); @@ -2184,18 +2042,18 @@ void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !"; throw INTERP_KERNEL::Exception(oss.str()); } - int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : "); + mcIdType nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : "); if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells()) { std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !"; throw INTERP_KERNEL::Exception(oss.str()); } - int nbOfCells=getNumberOfCells(); + mcIdType nbOfCells=getNumberOfCells(); bool easyAssign=true; - const int *connI=_nodal_connec_index->getConstPointer(); - const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer(); - int it=start; - for(int i=0;igetConstPointer(); + const mcIdType *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer(); + mcIdType it=start; + for(mcIdType i=0;i=0 && it arrOutAuto(arrOut),arrIOutAuto(arrIOut); + MCAuto arrOutAuto(arrOut),arrIOutAuto(arrIOut); setConnectivity(arrOut,arrIOut,true); } -} - -/*! - * 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 \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 [ \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 -{ - MCAuto cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1); - checkConnectivityFullyDefined(); - int tmp=-1; - int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1; - std::vector fastFinder(sz,false); - for(const int *work=begin;work!=end;work++) - if(*work>=0 && *workgetConstPointer(); - const int *connIndex=getNodalConnectivityIndex()->getConstPointer(); - for(int i=0;i=0) - { - ref++; - if(fastFinder[*work2]) - nbOfHit++; - } - if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn)) - cellIdsKept->pushBackSilent(i); - } - cellIdsKeptArr=cellIdsKept.retn(); } + /*! * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a * this->getMeshDimension(), that bound some cells of \a this mesh. @@ -2269,14 +2088,14 @@ void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int * 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. + * 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 added, else cells whose any node is in the * array \a begin are added. * \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is - * to delete this mesh using decrRef() as it is no more needed. + * 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. @@ -2286,10 +2105,10 @@ void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example". * \endif */ -MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const +MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const mcIdType *begin, const mcIdType *end, bool fullyIn) const { - MCAuto desc,descIndx,revDesc,revDescIndx; - desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New(); + MCAuto desc,descIndx,revDesc,revDescIndx; + desc=DataArrayIdType::New(); descIndx=DataArrayIdType::New(); revDesc=DataArrayIdType::New(); revDescIndx=DataArrayIdType::New(); MCAuto subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx); desc=0; descIndx=0; revDesc=0; revDescIndx=0; return static_cast(subMesh->buildPartOfMySelfNode(begin,end,fullyIn)); @@ -2302,7 +2121,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, * array of \a this mesh, else "free" nodes are removed from the result mesh * by calling zipCoords(). * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is - * to delete this mesh using decrRef() as it is no more needed. + * 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. * @@ -2313,19 +2132,19 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, */ MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const { - DataArrayInt *desc=DataArrayInt::New(); - DataArrayInt *descIndx=DataArrayInt::New(); - DataArrayInt *revDesc=DataArrayInt::New(); - DataArrayInt *revDescIndx=DataArrayInt::New(); + DataArrayIdType *desc=DataArrayIdType::New(); + DataArrayIdType *descIndx=DataArrayIdType::New(); + DataArrayIdType *revDesc=DataArrayIdType::New(); + DataArrayIdType *revDescIndx=DataArrayIdType::New(); // MCAuto meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx); revDesc->decrRef(); desc->decrRef(); descIndx->decrRef(); - int nbOfCells=meshDM1->getNumberOfCells(); - const int *revDescIndxC=revDescIndx->getConstPointer(); - std::vector boundaryCells; - for(int i=0;igetNumberOfCells(); + const mcIdType *revDescIndxC=revDescIndx->getConstPointer(); + std::vector boundaryCells; + for(mcIdType i=0;idecrRef(); @@ -2334,35 +2153,35 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const } /*! - * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary. + * This method returns a newly created DataArrayIdType instance containing ids of cells located in boundary. * A cell is detected to be on boundary if it contains one or more than one face having only one father. - * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. + * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. */ -DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const +DataArrayIdType *MEDCouplingUMesh::findCellIdsOnBoundary() const { checkFullyDefined(); - MCAuto desc=DataArrayInt::New(); - MCAuto descIndx=DataArrayInt::New(); - MCAuto revDesc=DataArrayInt::New(); - MCAuto revDescIndx=DataArrayInt::New(); + MCAuto desc=DataArrayIdType::New(); + MCAuto descIndx=DataArrayIdType::New(); + MCAuto revDesc=DataArrayIdType::New(); + MCAuto revDescIndx=DataArrayIdType::New(); // buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef(); - desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0; + desc=(DataArrayIdType*)0; descIndx=(DataArrayIdType*)0; // - MCAuto tmp=revDescIndx->deltaShiftIndex(); - MCAuto faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0; - const int *revDescPtr=revDesc->getConstPointer(); - const int *revDescIndxPtr=revDescIndx->getConstPointer(); - int nbOfCells=getNumberOfCells(); + MCAuto tmp=revDescIndx->deltaShiftIndex(); + MCAuto faceIds=tmp->findIdsEqual(1); tmp=(DataArrayIdType*)0; + const mcIdType *revDescPtr=revDesc->getConstPointer(); + const mcIdType *revDescIndxPtr=revDescIndx->getConstPointer(); + mcIdType nbOfCells=getNumberOfCells(); std::vector ret1(nbOfCells,false); - int sz=0; - for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++) + mcIdType sz=0; + for(const mcIdType *pt=faceIds->begin();pt!=faceIds->end();pt++) if(!ret1[revDescPtr[revDescIndxPtr[*pt]]]) { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; } // - DataArrayInt *ret2=DataArrayInt::New(); + DataArrayIdType *ret2=DataArrayIdType::New(); ret2->alloc(sz,1); - int *ret2Ptr=ret2->getPointer(); + mcIdType *ret2Ptr=ret2->getPointer(); sz=0; for(std::vector::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++) if(*it) @@ -2389,7 +2208,7 @@ DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end()); */ -void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const +void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayIdType *&cellIdsRk0, DataArrayIdType *&cellIdsRk1) const { if(getCoords()!=otherDimM1OnSameCoords.getCoords()) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !"); @@ -2397,21 +2216,21 @@ void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSa otherDimM1OnSameCoords.checkConnectivityFullyDefined(); if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !"); - MCAuto fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds(); - MCAuto s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false); + MCAuto fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds(); + MCAuto s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false); MCAuto thisPart=static_cast(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true)); - MCAuto descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New(); + MCAuto descThisPart=DataArrayIdType::New(),descIThisPart=DataArrayIdType::New(),revDescThisPart=DataArrayIdType::New(),revDescIThisPart=DataArrayIdType::New(); MCAuto thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart); - const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer(); - DataArrayInt *idsOtherInConsti=0; + const mcIdType *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer(); + DataArrayIdType *idsOtherInConsti=0; bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti); - MCAuto idsOtherInConstiAuto(idsOtherInConsti); + MCAuto idsOtherInConstiAuto(idsOtherInConsti); if(!b) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !"); - std::set s1; - for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++) + std::set s1; + for(const mcIdType *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++) s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]); - MCAuto s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer()); + MCAuto s1arr_renum1=DataArrayIdType::New(); s1arr_renum1->alloc(s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer()); s1arr_renum1->sort(); cellIdsRk0=s0arr.retn(); //cellIdsRk1=s_renum1.retn(); @@ -2421,26 +2240,26 @@ void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSa /*! * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this. - * + * * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh. */ MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const { - MCAuto desc=DataArrayInt::New(); - MCAuto descIndx=DataArrayInt::New(); - MCAuto revDesc=DataArrayInt::New(); - MCAuto revDescIndx=DataArrayInt::New(); + MCAuto desc=DataArrayIdType::New(); + MCAuto descIndx=DataArrayIdType::New(); + MCAuto revDesc=DataArrayIdType::New(); + MCAuto revDescIndx=DataArrayIdType::New(); // MCAuto meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx); revDesc=0; desc=0; descIndx=0; - MCAuto revDescIndx2=revDescIndx->deltaShiftIndex(); - MCAuto part=revDescIndx2->findIdsEqual(1); + MCAuto revDescIndx2=revDescIndx->deltaShiftIndex(); + MCAuto part=revDescIndx2->findIdsEqual(1); return static_cast(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true)); } /*! * Finds nodes lying on the boundary of \a this mesh. - * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found + * \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of found * nodes. The caller is to delete this array using decrRef() as it is no * more needed. * \throw If the coordinates array is not set. @@ -2451,7 +2270,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const * \ref py_mcumesh_findBoundaryNodes "Here is a Python example". * \endif */ -DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const +DataArrayIdType *MEDCouplingUMesh::findBoundaryNodes() const { MCAuto skin=computeSkin(); return skin->computeFetchedNodeIds(); @@ -2467,21 +2286,21 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const * 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. * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords. - * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated. + * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considered as needed to be duplicated. * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate. * * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input * parameter is altered during the call. * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above. * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed. - * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum. + * \param [out] cellIdsNotModified cell ids mcIdType \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum. * * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons). */ -void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate, - DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const +void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayIdType *& nodeIdsToDuplicate, + DataArrayIdType *& cellIdsNeededToBeRenum, DataArrayIdType *& cellIdsNotModified) const { - typedef MCAuto DAInt; + typedef MCAuto DAInt; typedef MCAuto MCUMesh; checkFullyDefined(); @@ -2492,7 +2311,7 @@ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1On throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !"); // Checking star-shaped M1 group: - DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New(); + DAInt dt0=DataArrayIdType::New(),dit0=DataArrayIdType::New(),rdt0=DataArrayIdType::New(),rdit0=DataArrayIdType::New(); MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); DAInt dsi = rdit0->deltaShiftIndex(); DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3); @@ -2505,7 +2324,7 @@ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1On MCUMesh meshM2Part = static_cast(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true)); DAInt xtrem = meshM2Part->computeFetchedNodeIds(); // Remove from the list points on the boundary of the M0 mesh (those need duplication!) - dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New(); + dt0=DataArrayIdType::New(),dit0=DataArrayIdType::New(),rdt0=DataArrayIdType::New(),rdit0=DataArrayIdType::New(); MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0; dsi = rdit0->deltaShiftIndex(); DAInt boundSegs = dsi->findIdsEqual(1); // boundary segs/faces of the M0 mesh @@ -2515,10 +2334,10 @@ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1On DAInt notDup = 0; if (getMeshDimension() == 3) { - DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New(); + DAInt dnu1=DataArrayIdType::New(), dnu2=DataArrayIdType::New(), dnu3=DataArrayIdType::New(), dnu4=DataArrayIdType::New(); MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4); dnu1=0;dnu2=0;dnu3=0;dnu4=0; - DataArrayInt * corresp=0; + DataArrayIdType * corresp=0; meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp); DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells()); corresp->decrRef(); @@ -2542,23 +2361,23 @@ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1On // MCUMesh m0Part2=static_cast(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true)); - int nCells2 = m0Part2->getNumberOfCells(); - DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New(); + mcIdType nCells2 = m0Part2->getNumberOfCells(); + DAInt desc00=DataArrayIdType::New(),descI00=DataArrayIdType::New(),revDesc00=DataArrayIdType::New(),revDescI00=DataArrayIdType::New(); MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00); // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of) - DataArrayInt *tmp00=0,*tmp11=0; + DataArrayIdType *tmp00=0,*tmp11=0; MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11); DAInt neighInit00(tmp00); DAInt neighIInit00(tmp11); // Neighbor information of the mesh WITH the crack (some neighbors are removed): - DataArrayInt *idsTmp=0; - bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp); + DataArrayIdType *idsTmp=0; + m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp); DAInt ids(idsTmp); // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack): - MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00); - DataArrayInt *tmp0=0,*tmp1=0; + DataArrayIdType::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00); + DataArrayIdType *tmp0=0,*tmp1=0; // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore. ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1); @@ -2566,11 +2385,11 @@ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1On DAInt neighI00(tmp1); // For each initial connex part of the sub-mesh (or said differently for each independent crack): - int seed = 0, nIter = 0; - int nIterMax = nCells2+1; // Safety net for the loop - DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2); + mcIdType seed = 0, nIter = 0; + mcIdType nIterMax = nCells2+1; // Safety net for the loop + DAInt hitCells = DataArrayIdType::New(); hitCells->alloc(nCells2); hitCells->fillWithValue(-1); - DAInt cellsToModifyConn0_torenum = DataArrayInt::New(); + DAInt cellsToModifyConn0_torenum = DataArrayIdType::New(); cellsToModifyConn0_torenum->alloc(0,1); while (nIter < nIterMax) { @@ -2578,14 +2397,14 @@ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1On if (!t->getNumberOfTuples()) break; // Connex zone without the crack (to compute the next seed really) - int dnu; + mcIdType dnu; DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu); - int cnt = 0; - for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++) + mcIdType cnt(0); + for (mcIdType * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++) hitCells->setIJ(*ptr,0,1); // Connex zone WITH the crack (to identify cells lying on either part of the crack) DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu); - cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0); + cellsToModifyConn0_torenum = DataArrayIdType::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0); // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2); DAInt nonHitCells = hitCells->findIdsEqual(-1); @@ -2610,20 +2429,20 @@ 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 + * More explicitly the renumber array in nodes is not explicitly 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, * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2... - * + * * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method. - * + * * \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 */ -void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) +void MEDCouplingUMesh::duplicateNodes(const mcIdType *nodeIdsToDuplicateBg, const mcIdType *nodeIdsToDuplicateEnd) { - int nbOfNodes=getNumberOfNodes(); + mcIdType nbOfNodes=getNumberOfNodes(); duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd); duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes); } @@ -2636,16 +2455,16 @@ void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int * * \sa renumberNodesInConn */ -void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset) +void MEDCouplingUMesh::renumberNodesWithOffsetInConn(mcIdType offset) { checkConnectivityFullyDefined(); - int *conn(getNodalConnectivity()->getPointer()); - const int *connIndex(getNodalConnectivityIndex()->getConstPointer()); - int nbOfCells(getNumberOfCells()); - for(int i=0;igetPointer()); + const mcIdType *connIndex(getNodalConnectivityIndex()->getConstPointer()); + mcIdType nbOfCells=getNumberOfCells(); + for(mcIdType i=0;i=0)//avoid polyhedron separator { node+=offset; @@ -2656,36 +2475,23 @@ void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset) } /*! - * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead + * Same than renumberNodesInConn(const mcIdType *) except that here the format of old-to-new traducer is using map instead * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction * of a big mesh. */ -void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap& newNodeNumbersO2N) +void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap& newNodeNumbersO2N) { - checkConnectivityFullyDefined(); - int *conn(getNodalConnectivity()->getPointer()); - const int *connIndex(getNodalConnectivityIndex()->getConstPointer()); - int nbOfCells(getNumberOfCells()); - for(int i=0;i=0)//avoid polyhedron separator - { - INTERP_KERNEL::HashMap::const_iterator it(newNodeNumbersO2N.find(node)); - if(it!=newNodeNumbersO2N.end()) - { - node=(*it).second; - } - else - { - std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !"; - throw INTERP_KERNEL::Exception(oss.str()); - } - } - } - _nodal_connec->declareAsNew(); - updateTime(); + this->renumberNodesInConnT< INTERP_KERNEL::HashMap >(newNodeNumbersO2N); +} + +/*! + * Same than renumberNodesInConn(const mcIdType *) except that here the format of old-to-new traducer is using map instead + * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction + * of a big mesh. + */ +void MEDCouplingUMesh::renumberNodesInConn(const std::map& newNodeNumbersO2N) +{ + this->renumberNodesInConnT< std::map >(newNodeNumbersO2N); } /*! @@ -2694,7 +2500,7 @@ void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap * This method is a generalization of shiftNodeNumbersInConn(). * \warning This method performs no check of validity of new ids. **Use it with care !** * \param [in] newNodeNumbersO2N - a permutation array, of length \a - * this->getNumberOfNodes(), in "Old to New" mode. + * this->getNumberOfNodes(), in "Old to New" mode. * See \ref numbering for more info on renumbering modes. * \throw If the nodal connectivity of cells is not defined. * @@ -2703,16 +2509,16 @@ void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap * \ref py_mcumesh_renumberNodesInConn "Here is a Python example". * \endif */ -void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N) +void MEDCouplingUMesh::renumberNodesInConn(const mcIdType *newNodeNumbersO2N) { checkConnectivityFullyDefined(); - int *conn=getNodalConnectivity()->getPointer(); - const int *connIndex=getNodalConnectivityIndex()->getConstPointer(); - int nbOfCells(getNumberOfCells()); - for(int i=0;igetPointer(); + const mcIdType *connIndex=getNodalConnectivityIndex()->getConstPointer(); + mcIdType nbOfCells=getNumberOfCells(); + for(mcIdType i=0;i=0)//avoid polyhedron separator { node=newNodeNumbersO2N[node]; @@ -2726,19 +2532,19 @@ void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N) * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords. * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care ! * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method". - * + * * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this. */ -void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) +void MEDCouplingUMesh::shiftNodeNumbersInConn(mcIdType delta) { checkConnectivityFullyDefined(); - int *conn=getNodalConnectivity()->getPointer(); - const int *connIndex=getNodalConnectivityIndex()->getConstPointer(); - int nbOfCells=getNumberOfCells(); - for(int i=0;igetPointer(); + const mcIdType *connIndex=getNodalConnectivityIndex()->getConstPointer(); + mcIdType nbOfCells=getNumberOfCells(); + for(mcIdType i=0;i=0)//avoid polyhedron separator { node+=delta; @@ -2751,36 +2557,36 @@ void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) /*! * 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 + * More explicitly the renumber array in nodes is not explicitly 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, * node id nodeIdsToDuplicateBg[2] will have id offset+2... - * + * * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method. * As an another consequense after the call of this method \b this can be transiently non cohrent. - * + * * \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 [ \a nodeIdsToDuplicateBg, \a 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) +void MEDCouplingUMesh::duplicateNodesInConn(const mcIdType *nodeIdsToDuplicateBg, const mcIdType *nodeIdsToDuplicateEnd, mcIdType offset) { checkConnectivityFullyDefined(); - std::map m; - int val=offset; - for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++) + std::map m; + mcIdType val=offset; + for(const mcIdType *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++) m[*work]=val; - int *conn=getNodalConnectivity()->getPointer(); - const int *connIndex=getNodalConnectivityIndex()->getConstPointer(); - int nbOfCells=getNumberOfCells(); - for(int i=0;igetPointer(); + const mcIdType *connIndex=getNodalConnectivityIndex()->getConstPointer(); + mcIdType nbOfCells=getNumberOfCells(); + for(mcIdType i=0;i=0)//avoid polyhedron separator { - std::map::iterator it=m.find(node); + std::map::iterator it=m.find(node); if(it!=m.end()) node=(*it).second; } @@ -2801,38 +2607,38 @@ void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, con * 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() * \param check */ -void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) +void MEDCouplingUMesh::renumberCells(const mcIdType *old2NewBg, bool check) { checkConnectivityFullyDefined(); - int nbCells=getNumberOfCells(); - const int *array=old2NewBg; + mcIdType nbCells=getNumberOfCells(); + const mcIdType *array=old2NewBg; if(check) - array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells); + array=DataArrayIdType::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells); // - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - MCAuto o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1); - MCAuto n2o=o2n->invertArrayO2N2N2O(nbCells); - const int *n2oPtr=n2o->begin(); - MCAuto newConn=DataArrayInt::New(); + const mcIdType *conn=_nodal_connec->getConstPointer(); + const mcIdType *connI=_nodal_connec_index->getConstPointer(); + MCAuto o2n=DataArrayIdType::New(); o2n->useArray(array,false,DeallocType::C_DEALLOC,nbCells,1); + MCAuto n2o=o2n->invertArrayO2N2N2O(nbCells); + const mcIdType *n2oPtr=n2o->begin(); + MCAuto newConn=DataArrayIdType::New(); newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents()); newConn->copyStringInfoFrom(*_nodal_connec); - MCAuto newConnI=DataArrayInt::New(); + MCAuto newConnI=DataArrayIdType::New(); newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents()); newConnI->copyStringInfoFrom(*_nodal_connec_index); // - int *newC=newConn->getPointer(); - int *newCI=newConnI->getPointer(); - int loc=0; + mcIdType *newC=newConn->getPointer(); + mcIdType *newCI=newConnI->getPointer(); + mcIdType loc=0; newCI[0]=loc; - for(int i=0;i(array)); + free(const_cast(array)); } /*! * Finds cells whose bounding boxes intersect a given bounding box. * \param [in] bbox - an array defining the bounding box via coordinates of its * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin, - * zMax (if in 3D). + * zMax (if in 3D). * \param [in] eps - a factor used to increase size of the bounding box of cell * before comparing it with \a bbox. This factor is multiplied by the maximal * extent of the bounding box of cell to produce an addition to this bounding box. - * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found + * \return DataArrayIdType * - a new instance of DataArrayIdType holding ids for found * cells. The caller is to delete this array using decrRef() as it is no more - * needed. + * needed. * \throw If the coordinates array is not set. * \throw If the nodal connectivity of cells is not defined. * @@ -2862,9 +2668,9 @@ void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example". * \endif */ -DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const +DataArrayIdType *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const { - MCAuto elems=DataArrayInt::New(); elems->alloc(0,1); + MCAuto elems=DataArrayIdType::New(); elems->alloc(0,1); if(getMeshDimension()==-1) { elems->pushBackSilent(0); @@ -2872,11 +2678,11 @@ DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double } int dim=getSpaceDimension(); INTERP_KERNEL::AutoPtr elem_bb=new double[2*dim]; - const int* conn = getNodalConnectivity()->getConstPointer(); - const int* conn_index= getNodalConnectivityIndex()->getConstPointer(); + const mcIdType* conn = getNodalConnectivity()->getConstPointer(); + const mcIdType* conn_index= getNodalConnectivityIndex()->getConstPointer(); const double* coords = getCoords()->getConstPointer(); - int nbOfCells=getNumberOfCells(); - for ( int ielem=0; ielem::max(); } - for (int inode=conn_index[ielem]+1; inode=0)//avoid polyhedron separator { for (int idim=0; idim elems=DataArrayInt::New(); elems->alloc(0,1); + MCAuto elems=DataArrayIdType::New(); elems->alloc(0,1); if(getMeshDimension()==-1) { elems->pushBackSilent(0); @@ -2923,11 +2729,11 @@ DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::Direc } int dim=getSpaceDimension(); INTERP_KERNEL::AutoPtr elem_bb=new double[2*dim]; - const int* conn = getNodalConnectivity()->getConstPointer(); - const int* conn_index= getNodalConnectivityIndex()->getConstPointer(); + const mcIdType* conn = getNodalConnectivity()->getConstPointer(); + const mcIdType* conn_index= getNodalConnectivityIndex()->getConstPointer(); const double* coords = getCoords()->getConstPointer(); - int nbOfCells=getNumberOfCells(); - for ( int ielem=0; ielem::max(); } - for (int inode=conn_index[ielem]+1; inode=0)//avoid polyhedron separator { for (int idim=0; idimgetNumberOfCells() ). */ -INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const +INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(mcIdType cellId) const { - const int *ptI=_nodal_connec_index->getConstPointer(); - const int *pt=_nodal_connec->getConstPointer(); - if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1) + const mcIdType *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin()); + if(cellId<_nodal_connec_index->getNbOfElems()-1) return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]]; else { @@ -2987,20 +2792,20 @@ INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) co * \param [in] type the geometric type * \return cell ids in this having geometric type \a type. */ -DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const +DataArrayIdType *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const { - MCAuto ret=DataArrayInt::New(); + MCAuto ret=DataArrayIdType::New(); ret->alloc(0,1); checkConnectivityFullyDefined(); - int nbCells=getNumberOfCells(); + mcIdType nbCells=getNumberOfCells(); int mdim=getMeshDimension(); const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type); - if(mdim!=(int)cm.getDimension()) + if(mdim!=ToIdType(cm.getDimension())) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !"); - const int *ptI=_nodal_connec_index->getConstPointer(); - const int *pt=_nodal_connec->getConstPointer(); - for(int i=0;igetConstPointer(); + const mcIdType *pt=_nodal_connec->getConstPointer(); + for(mcIdType i=0;ipushBackSilent(i); @@ -3011,13 +2816,11 @@ DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellT /*! * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type. */ -int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const +mcIdType MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const { - const int *ptI=_nodal_connec_index->getConstPointer(); - const int *pt=_nodal_connec->getConstPointer(); - int nbOfCells=getNumberOfCells(); - int ret=0; - for(int i=0;ibegin()),*pt(_nodal_connec->begin()); + mcIdType nbOfCells(getNumberOfCells()),ret(0); + for(mcIdType i=0;igetNumberOfCells() ). */ -void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector& conn) const +void MEDCouplingUMesh::getNodeIdsOfCell(mcIdType cellId, std::vector& conn) const { - const int *ptI=_nodal_connec_index->getConstPointer(); - const int *pt=_nodal_connec->getConstPointer(); - for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++) + const mcIdType *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin()); + for(const mcIdType *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++) if(*w>=0) conn.push_back(*w); } @@ -3128,26 +2930,26 @@ std::string MEDCouplingUMesh::reprConnectivityOfThis() const } /*! - * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with. + * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsibility to deal with. * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates) * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with * some algos). - * + * * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown. * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created * with number of tuples set to 0, if not the array is taken as this in the returned instance. */ -MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const +MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(std::size_t spaceDim) const { int mdim=getMeshDimension(); if(mdim<0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !"); MCAuto ret=MEDCouplingUMesh::New(getName(),mdim); - MCAuto tmp1,tmp2; + MCAuto tmp1,tmp2; bool needToCpyCT=true; if(!_nodal_connec) { - tmp1=DataArrayInt::New(); tmp1->alloc(0,1); + tmp1=DataArrayIdType::New(); tmp1->alloc(0,1); needToCpyCT=false; } else @@ -3157,7 +2959,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const } if(!_nodal_connec_index) { - tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0); + tmp2=DataArrayIdType::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0); needToCpyCT=false; } else @@ -3178,53 +2980,34 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const return ret.retn(); } -void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const -{ - if(_nodal_connec!=0 && _nodal_connec_index!=0) - { - int nbOfCells=getNumberOfCells(); - const int *c=_nodal_connec->getConstPointer(); - const int *ci=_nodal_connec_index->getConstPointer(); - for(int i=0;i(stream," ")); - stream << "\n"; - } - } - else - stream << "Connectivity not defined !\n"; -} - -int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const +mcIdType MEDCouplingUMesh::getNumberOfNodesInCell(mcIdType cellId) const { - const int *ptI=_nodal_connec_index->getConstPointer(); - const int *pt=_nodal_connec->getConstPointer(); + const mcIdType *ptI=_nodal_connec_index->getConstPointer(); + const mcIdType *pt=_nodal_connec->getConstPointer(); if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED) return ptI[cellId+1]-ptI[cellId]-1; else - return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to(),-1)); + return ToIdType(std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to(),-1))); } /*! * Returns types of cells of the specified part of \a this mesh. - * This method avoids computing sub-mesh explicitely to get its types. + * This method avoids computing sub-mesh explicitly to get its types. * \param [in] begin - an array of cell ids of interest. * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element. * \return std::set - a set of enumeration items - * describing the cell types. + * describing the cell types. * \throw If the coordinates array is not set. * \throw If the nodal connectivity of cells is not defined. * \sa getAllGeoTypes() */ -std::set MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const +std::set MEDCouplingUMesh::getTypesOfPart(const mcIdType *begin, const mcIdType *end) const { checkFullyDefined(); std::set ret; - const int *conn=_nodal_connec->getConstPointer(); - const int *connIndex=_nodal_connec_index->getConstPointer(); - for(const int *w=begin;w!=end;w++) + const mcIdType *conn=_nodal_connec->getConstPointer(); + const mcIdType *connIndex=_nodal_connec_index->getConstPointer(); + for(const mcIdType *w=begin;w!=end;w++) ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]); return ret; } @@ -3232,18 +3015,18 @@ std::set MEDCouplingUMesh::getTypesOfPart(con /*! * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format. * Optionally updates - * a set of types of cells constituting \a this mesh. + * a set of types of cells constituting \a this mesh. * This method is for advanced users having prepared their connectivity before. For * more info on using this method see \ref MEDCouplingUMeshAdvBuild. - * \param [in] conn - the nodal connectivity array. + * \param [in] conn - the nodal connectivity array. * \param [in] connIndex - the nodal connectivity index array. * \param [in] isComputingTypes - if \c true, the set of types constituting \a this * mesh is updated. */ -void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes) +void MEDCouplingUMesh::setConnectivity(DataArrayIdType *conn, DataArrayIdType *connIndex, bool isComputingTypes) { - DataArrayInt::SetArrayIn(conn,_nodal_connec); - DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index); + DataArrayIdType::SetArrayIn(conn,_nodal_connec); + DataArrayIdType::SetArrayIn(connIndex,_nodal_connec_index); if(isComputingTypes) computeTypes(); declareAsNew(); @@ -3253,14 +3036,14 @@ void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connInd * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other. * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied. */ -MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim), +MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy):MEDCouplingPointSet(other,deepCpy),_mesh_dim(other._mesh_dim), _nodal_connec(0),_nodal_connec_index(0), _types(other._types) { if(other._nodal_connec) - _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy); + _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCpy); if(other._nodal_connec_index) - _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy); + _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCpy); } MEDCouplingUMesh::~MEDCouplingUMesh() @@ -3280,31 +3063,14 @@ void MEDCouplingUMesh::computeTypes() ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index); } -/*! - * This method checks that all arrays are set. If yes nothing done if no an exception is thrown. - */ -void MEDCouplingUMesh::checkFullyDefined() const -{ - if(!_nodal_connec_index || !_nodal_connec || !_coords) - throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh."); -} - -/*! - * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown. - */ -void MEDCouplingUMesh::checkConnectivityFullyDefined() const -{ - if(!_nodal_connec_index || !_nodal_connec) - throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh."); -} /*! - * Returns a number of cells constituting \a this mesh. - * \return int - the number of cells in \a this mesh. + * Returns a number of cells constituting \a this mesh. + * \return mcIdType - the number of cells in \a this mesh. * \throw If the nodal connectivity of cells is not defined. */ -int MEDCouplingUMesh::getNumberOfCells() const -{ +mcIdType MEDCouplingUMesh::getNumberOfCells() const +{ if(_nodal_connec_index) return _nodal_connec_index->getNumberOfTuples()-1; else @@ -3331,9 +3097,9 @@ int MEDCouplingUMesh::getMeshDimension() const * Returns a length of the nodal connectivity array. * This method is for test reason. Normally the integer returned is not useable by * user. For more info see \ref MEDCouplingUMeshNodalConnectivity. - * \return int - the length of the nodal connectivity array. + * \return mcIdType - the length of the nodal connectivity array. */ -int MEDCouplingUMesh::getNodalConnectivityArrayLen() const +mcIdType MEDCouplingUMesh::getNodalConnectivityArrayLen() const { return _nodal_connec->getNbOfElems(); } @@ -3341,10 +3107,10 @@ int MEDCouplingUMesh::getNodalConnectivityArrayLen() const /*! * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process. */ -void MEDCouplingUMesh::getTinySerializationInformation(std::vector& tinyInfoD, std::vector& tinyInfo, std::vector& littleStrings) const +void MEDCouplingUMesh::getTinySerializationInformation(std::vector& tinyInfoD, std::vector& tinyInfo, std::vector& littleStrings) const { MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings); - tinyInfo.push_back(getMeshDimension()); + tinyInfo.push_back(ToIdType(getMeshDimension())); tinyInfo.push_back(getNumberOfCells()); if(_nodal_connec) tinyInfo.push_back(getNodalConnectivityArrayLen()); @@ -3355,7 +3121,7 @@ void MEDCouplingUMesh::getTinySerializationInformation(std::vector& tiny /*! * First step of unserialization process. */ -bool MEDCouplingUMesh::isEmptyMesh(const std::vector& tinyInfo) const +bool MEDCouplingUMesh::isEmptyMesh(const std::vector& tinyInfo) const { return tinyInfo[6]<=0; } @@ -3367,7 +3133,7 @@ bool MEDCouplingUMesh::isEmptyMesh(const std::vector& tinyInfo) const * \param a2 * \param littleStrings */ -void MEDCouplingUMesh::resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) const +void MEDCouplingUMesh::resizeForUnserialization(const std::vector& tinyInfo, DataArrayIdType *a1, DataArrayDouble *a2, std::vector& littleStrings) const { MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings); if(tinyInfo[5]!=-1) @@ -3377,16 +3143,16 @@ void MEDCouplingUMesh::resizeForUnserialization(const std::vector& tinyInfo /*! * Third and final step of serialization process. */ -void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const +void MEDCouplingUMesh::serialize(DataArrayIdType *&a1, DataArrayDouble *&a2) const { MEDCouplingPointSet::serialize(a1,a2); if(getMeshDimension()>-1) { - a1=DataArrayInt::New(); + a1=DataArrayIdType::New(); a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1); - int *ptA1=a1->getPointer(); - const int *conn=getNodalConnectivity()->getConstPointer(); - const int *index=getNodalConnectivityIndex()->getConstPointer(); + mcIdType *ptA1=a1->getPointer(); + const mcIdType *conn=getNodalConnectivity()->getConstPointer(); + const mcIdType *index=getNodalConnectivityIndex()->getConstPointer(); ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1); std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1); } @@ -3398,114 +3164,25 @@ void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const * Second and final unserialization process. * \param tinyInfo must be equal to the result given by getTinySerializationInformation method. */ -void MEDCouplingUMesh::unserialization(const std::vector& tinyInfoD, const std::vector& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector& littleStrings) +void MEDCouplingUMesh::unserialization(const std::vector& tinyInfoD, const std::vector& tinyInfo, const DataArrayIdType *a1, DataArrayDouble *a2, const std::vector& littleStrings) { MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings); - setMeshDimension(tinyInfo[5]); + setMeshDimension(FromIdType(tinyInfo[5])); if(tinyInfo[7]!=-1) { // Connectivity - const int *recvBuffer=a1->getConstPointer(); - MCAuto myConnecIndex=DataArrayInt::New(); + const mcIdType *recvBuffer=a1->getConstPointer(); + MCAuto myConnecIndex=DataArrayIdType::New(); myConnecIndex->alloc(tinyInfo[6]+1,1); std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer()); - MCAuto myConnec=DataArrayInt::New(); + MCAuto myConnec=DataArrayIdType::New(); myConnec->alloc(tinyInfo[7],1); std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer()); setConnectivity(myConnec, myConnecIndex); } } -/*! - * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelfSlice. - * CellIds are given using range specified by a start an end and step. - */ -MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice(int start, int end, int step) const -{ - checkFullyDefined(); - int ncell=getNumberOfCells(); - MCAuto ret=MEDCouplingUMesh::New(); - ret->_mesh_dim=_mesh_dim; - ret->setCoords(_coords); - int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : "); - MCAuto newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1); - int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0; - int work=start; - const int *conn=_nodal_connec->getConstPointer(); - const int *connIndex=_nodal_connec_index->getConstPointer(); - for(int i=0;i=0 && work newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1); - int *newConnPtr=newConn->getPointer(); - std::set types; - work=start; - for(int i=0;isetConnectivity(newConn,newConnI,false); - ret->_types=types; - ret->copyTinyInfoFrom(this); - return ret.retn(); -} -/*! - * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf. - * 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 -{ - checkConnectivityFullyDefined(); - int ncell=getNumberOfCells(); - MCAuto ret=MEDCouplingUMesh::New(); - ret->_mesh_dim=_mesh_dim; - ret->setCoords(_coords); - std::size_t nbOfElemsRet=std::distance(begin,end); - int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int)); - connIndexRet[0]=0; - const int *conn=_nodal_connec->getConstPointer(); - const int *connIndex=_nodal_connec_index->getConstPointer(); - int newNbring=0; - for(const int *work=begin;work!=end;work++,newNbring++) - { - if(*work>=0 && *work types; - for(const int *work=begin;work!=end;work++) - { - types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]); - connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork); - } - MCAuto connRetArr=DataArrayInt::New(); - connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1); - MCAuto connIndexRetArr=DataArrayInt::New(); - connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1); - ret->setConnectivity(connRetArr,connIndexRetArr,false); - ret->_types=types; - ret->copyTinyInfoFrom(this); - return ret.retn(); -} /*! * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this @@ -3523,7 +3200,7 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const { std::string name="MeasureOfMesh_"; name+=getName(); - int nbelem=getNumberOfCells(); + mcIdType nbelem=getNumberOfCells(); MCAuto field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); field->setName(name); MCAuto array=DataArrayDouble::New(); @@ -3534,17 +3211,17 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const field->synchronizeTimeWithMesh(); if(getMeshDimension()!=-1) { - int ipt; + mcIdType ipt; INTERP_KERNEL::NormalizedCellType type; int dim_space=getSpaceDimension(); const double *coords=getCoords()->getConstPointer(); - const int *connec=getNodalConnectivity()->getConstPointer(); - const int *connec_index=getNodalConnectivityIndex()->getConstPointer(); - for(int iel=0;ielgetConstPointer(); + const mcIdType *connec_index=getNodalConnectivityIndex()->getConstPointer(); + for(mcIdType iel=0;iel(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space); + area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space); } if(isAbs) std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun(fabs)); @@ -3569,35 +3246,35 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element. * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to * delete this array using decrRef() as it is no more needed. - * + * * \if ENABLE_EXAMPLES * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".
* \ref py_mcumesh_getPartMeasureField "Here is a Python example". * \endif * \sa getMeasureField() */ -DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const +DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const mcIdType *begin, const mcIdType *end) const { std::string name="PartMeasureOfMesh_"; name+=getName(); - int nbelem=(int)std::distance(begin,end); + std::size_t nbelem=std::distance(begin,end); MCAuto array=DataArrayDouble::New(); array->setName(name); array->alloc(nbelem,1); double *area_vol=array->getPointer(); if(getMeshDimension()!=-1) { - int ipt; + mcIdType ipt; INTERP_KERNEL::NormalizedCellType type; int dim_space=getSpaceDimension(); const double *coords=getCoords()->getConstPointer(); - const int *connec=getNodalConnectivity()->getConstPointer(); - const int *connec_index=getNodalConnectivityIndex()->getConstPointer(); - for(const int *iel=begin;iel!=end;iel++) + const mcIdType *connec=getNodalConnectivity()->getConstPointer(); + const mcIdType *connec_index=getNodalConnectivityIndex()->getConstPointer(); + for(const mcIdType *iel=begin;iel!=end;iel++) { ipt=connec_index[*iel]; type=(INTERP_KERNEL::NormalizedCellType)connec[ipt]; - *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space); + *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space); } if(isAbs) std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun(fabs)); @@ -3629,22 +3306,28 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) cons MCAuto tmp=getMeasureField(isAbs); std::string name="MeasureOnNodeOfMesh_"; name+=getName(); - int nbNodes=getNumberOfNodes(); + mcIdType nbNodes=getNumberOfNodes(); + MCAuto nnpc; + { + MCAuto tmp(computeNbOfNodesPerCell()); + nnpc=tmp->convertToDblArr(); + } + std::for_each(nnpc->rwBegin(),nnpc->rwEnd(),[](double& v) { v=1./v; }); + const double *nnpcPtr(nnpc->begin()); MCAuto ret=MEDCouplingFieldDouble::New(ON_NODES); - double cst=1./((double)getMeshDimension()+1.); MCAuto array=DataArrayDouble::New(); array->alloc(nbNodes,1); double *valsToFill=array->getPointer(); std::fill(valsToFill,valsToFill+nbNodes,0.); const double *values=tmp->getArray()->getConstPointer(); - MCAuto da=DataArrayInt::New(); - MCAuto daInd=DataArrayInt::New(); + MCAuto da=DataArrayIdType::New(); + MCAuto daInd=DataArrayIdType::New(); getReverseNodalConnectivity(da,daInd); - const int *daPtr=da->getConstPointer(); - const int *daIPtr=daInd->getConstPointer(); - for(int i=0;igetConstPointer(); + const mcIdType *daIPtr=daInd->getConstPointer(); + for(mcIdType i=0;isetMesh(this); ret->setArray(array); return ret.retn(); @@ -3655,10 +3338,10 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) cons * mesh. The returned normal vectors to each cell have a norm2 equal to 1. * The computed vectors have this->getMeshDimension()+1 components * and are normalized. - *
\a this can be either - * - a 2D mesh in 2D or 3D space or + *
\a this can be either + * - a 2D mesh in 2D or 3D space or * - an 1D mesh in 2D space. - * + * * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on * cells and one time. The caller is to delete this field using decrRef() as * it is no more needed. @@ -3673,12 +3356,12 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !"); MCAuto ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); MCAuto array=DataArrayDouble::New(); - int nbOfCells=getNumberOfCells(); + mcIdType nbOfCells=getNumberOfCells(); int nbComp=getMeshDimension()+1; array->alloc(nbOfCells,nbComp); double *vals=array->getPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const int *conn=_nodal_connec->getConstPointer(); + const mcIdType *connI=_nodal_connec_index->getConstPointer(); + const mcIdType *conn=_nodal_connec->getConstPointer(); const double *coords=_coords->getConstPointer(); if(getMeshDimension()==2) { @@ -3686,9 +3369,9 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const { MCAuto loc=computeCellCenterOfMass(); const double *locPtr=loc->getConstPointer(); - for(int i=0;i(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals); double n=INTERP_KERNEL::norm<3>(vals); std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies(),1./n)); @@ -3698,16 +3381,16 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const { MCAuto isAbs=getMeasureField(false); const double *isAbsPtr=isAbs->getArray()->begin(); - for(int i=0;i0.?1.:-1.; } } } else//meshdimension==1 { double tmp[2]; - for(int i=0;i()); double n=INTERP_KERNEL::norm<2>(tmp); std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies(),1./n)); @@ -3725,10 +3408,10 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of * \a this mesh. The computed vectors have this->getMeshDimension()+1 components * and are normalized. - *
\a this can be either - * - a 2D mesh in 2D or 3D space or + *
\a this can be either + * - a 2D mesh in 2D or 3D space or * - an 1D mesh in 2D space. - * + * * This method avoids building explicitly a part of \a this mesh to perform the work. * \param [in] begin - an array of cell ids of interest. * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element. @@ -3746,7 +3429,7 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example". * \endif */ -MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const +MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const mcIdType *begin, const mcIdType *end) const { if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2)) throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !"); @@ -3754,10 +3437,10 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *be MCAuto array=DataArrayDouble::New(); std::size_t nbelems=std::distance(begin,end); int nbComp=getMeshDimension()+1; - array->alloc((int)nbelems,nbComp); + array->alloc(nbelems,nbComp); double *vals=array->getPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const int *conn=_nodal_connec->getConstPointer(); + const mcIdType *connI=_nodal_connec_index->getConstPointer(); + const mcIdType *conn=_nodal_connec->getConstPointer(); const double *coords=_coords->getConstPointer(); if(getMeshDimension()==2) { @@ -3765,9 +3448,9 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *be { MCAuto loc=getPartBarycenterAndOwner(begin,end); const double *locPtr=loc->getConstPointer(); - for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3) + for(const mcIdType *i=begin;i!=end;i++,vals+=3,locPtr+=3) { - int offset=connI[*i]; + mcIdType offset=connI[*i]; INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals); double n=INTERP_KERNEL::norm<3>(vals); std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies(),1./n)); @@ -3782,9 +3465,9 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *be else//meshdimension==1 { double tmp[2]; - for(const int *i=begin;i!=end;i++) + for(const mcIdType *i=begin;i!=end;i++) { - int offset=connI[*i]; + mcIdType offset=connI[*i]; std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus()); double n=INTERP_KERNEL::norm<2>(tmp); std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies(),1./n)); @@ -3818,14 +3501,14 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !"); MCAuto ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); MCAuto array=DataArrayDouble::New(); - int nbOfCells=getNumberOfCells(); + mcIdType nbOfCells=getNumberOfCells(); int spaceDim=getSpaceDimension(); array->alloc(nbOfCells,spaceDim); double *pt=array->getPointer(); const double *coo=getCoords()->getConstPointer(); - std::vector conn; + std::vector conn; conn.reserve(2); - for(int i=0;igetMeshDimension() != 3 or \a this->getSpaceDimension() != 3. @@ -3860,38 +3543,38 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const * \throw If the plane does not intersect any 3D cell of \a this mesh. * \throw If \a this includes quadratic cells. */ -MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const +MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayIdType *&cellIds) const { checkFullyDefined(); if(getMeshDimension()!=3 || getSpaceDimension()!=3) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!"); - MCAuto candidates=getCellIdsCrossingPlane(origin,vec,eps); + MCAuto candidates=getCellIdsCrossingPlane(origin,vec,eps); if(candidates->empty()) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !"); - std::vector nodes; - DataArrayInt *cellIds1D=0; + std::vector nodes; + DataArrayIdType *cellIds1D=0; MCAuto subMesh=static_cast(buildPartOfMySelf(candidates->begin(),candidates->end(),false)); subMesh->findNodesOnPlane(origin,vec,eps,nodes); - MCAuto desc1=DataArrayInt::New(),desc2=DataArrayInt::New(); - MCAuto descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New(); - MCAuto revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New(); - MCAuto revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New(); + MCAuto desc1=DataArrayIdType::New(),desc2=DataArrayIdType::New(); + MCAuto descIndx1=DataArrayIdType::New(),descIndx2=DataArrayIdType::New(); + MCAuto revDesc1=DataArrayIdType::New(),revDesc2=DataArrayIdType::New(); + MCAuto revDescIndx1=DataArrayIdType::New(),revDescIndx2=DataArrayIdType::New(); MCAuto mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3 revDesc2=0; revDescIndx2=0; MCAuto mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3 revDesc1=0; revDescIndx1=0; mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D); - MCAuto cellIds1DTmp(cellIds1D); + MCAuto cellIds1DTmp(cellIds1D); // - std::vector cut3DCurve(mDesc1->getNumberOfCells(),-2); - for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++) + std::vector cut3DCurve(mDesc1->getNumberOfCells(),-2); + for(const mcIdType *it=cellIds1D->begin();it!=cellIds1D->end();it++) cut3DCurve[*it]=-1; mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve); - std::vector< std::pair > cut3DSurf(mDesc2->getNumberOfCells()); + std::vector< std::pair > cut3DSurf(mDesc2->getNumberOfCells()); AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(), mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(), desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf); - MCAuto conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); + MCAuto conn(DataArrayIdType::New()),connI(DataArrayIdType::New()),cellIds2(DataArrayIdType::New()); connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1); subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2); if(cellIds2->empty()) @@ -3905,20 +3588,20 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const dou /*! * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In -addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes +addition to the mesh, returns a new DataArrayIdType, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes from. If a result segment is shared by two 2D cells, then the segment in included twice in the result mesh. * \param [in] origin - 3 components of a point defining location of the plane. * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude * must be greater than 1e-6. * \param [in] eps - half-thickness of the plane. - * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces + * \param [out] cellIds - a new instance of DataArrayIdType holding ids of faces * producing correspondent segments. The caller is to delete this array * using decrRef() as it is no more needed. * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D * mesh in 3D space. This mesh does not share the node coordinates array with * \a this mesh. The caller is to delete this mesh using decrRef() as it is - * no more needed. + * no more needed. * \throw If the coordinates array is not set. * \throw If the nodal connectivity of cells is not defined. * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3. @@ -3926,57 +3609,54 @@ the result mesh. * \throw If the plane does not intersect any 2D cell of \a this mesh. * \throw If \a this includes quadratic cells. */ -MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const +MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayIdType *&cellIds) const { checkFullyDefined(); if(getMeshDimension()!=2 || getSpaceDimension()!=3) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !"); - MCAuto candidates=getCellIdsCrossingPlane(origin,vec,eps); + MCAuto candidates(getCellIdsCrossingPlane(origin,vec,eps)); if(candidates->empty()) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !"); - std::vector nodes; - DataArrayInt *cellIds1D=0; - MCAuto subMesh=static_cast(buildPartOfMySelf(candidates->begin(),candidates->end(),false)); + std::vector nodes; + DataArrayIdType *cellIds1D(0); + MCAuto subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false)); subMesh->findNodesOnPlane(origin,vec,eps,nodes); - MCAuto desc1=DataArrayInt::New(); - MCAuto descIndx1=DataArrayInt::New(); - MCAuto revDesc1=DataArrayInt::New(); - MCAuto revDescIndx1=DataArrayInt::New(); - MCAuto mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3 + MCAuto desc1(DataArrayIdType::New()),descIndx1(DataArrayIdType::New()),revDesc1(DataArrayIdType::New()),revDescIndx1(DataArrayIdType::New()); + MCAuto mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D); - MCAuto cellIds1DTmp(cellIds1D); + MCAuto cellIds1DTmp(cellIds1D); // - std::vector cut3DCurve(mDesc1->getNumberOfCells(),-2); - for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++) + std::vector cut3DCurve(mDesc1->getNumberOfCells(),-2); + for(const mcIdType *it=cellIds1D->begin();it!=cellIds1D->end();it++) cut3DCurve[*it]=-1; mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve); - int ncellsSub=subMesh->getNumberOfCells(); - std::vector< std::pair > cut3DSurf(ncellsSub); + mcIdType ncellsSub=subMesh->getNumberOfCells(); + std::vector< std::pair > cut3DSurf(ncellsSub); AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(), mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(), desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf); - MCAuto conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0); + MCAuto conn(DataArrayIdType::New()),connI(DataArrayIdType::New()),cellIds2(DataArrayIdType::New()); connI->pushBackSilent(0); conn->alloc(0,1); - const int *nodal=subMesh->getNodalConnectivity()->getConstPointer(); - const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer(); - for(int i=0;igetNodalConnectivity()->getConstPointer(); + const mcIdType *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer(); + for(mcIdType i=0;ipushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second); + conn->pushBackSilent(ToIdType(INTERP_KERNEL::NORM_SEG2)); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second); connI->pushBackSilent(conn->getNumberOfTuples()); cellIds2->pushBackSilent(i); } else { - int cellId3DSurf=cut3DSurf[i].second; - int offset=nodalI[cellId3DSurf]+1; - int nbOfEdges=nodalI[cellId3DSurf+1]-offset; - for(int j=0;jpushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]); + conn->pushBackSilent(ToIdType(INTERP_KERNEL::NORM_SEG2)); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]); connI->pushBackSilent(conn->getNumberOfTuples()); cellIds2->pushBackSilent(cellId3DSurf); } @@ -3992,13 +3672,128 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const return ret.retn(); } +MCAuto MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const +{ + checkFullyDefined(); + if(getMeshDimension()!=3 || getSpaceDimension()!=3) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!"); + if(getNumberOfCells()!=1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !"); + // + std::vector nodes; + findNodesOnPlane(origin,vec,eps,nodes); + MCAuto desc1(DataArrayIdType::New()),desc2(DataArrayIdType::New()),descIndx1(DataArrayIdType::New()),descIndx2(DataArrayIdType::New()),revDesc1(DataArrayIdType::New()),revDesc2(DataArrayIdType::New()),revDescIndx1(DataArrayIdType::New()),revDescIndx2(DataArrayIdType::New()); + MCAuto mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3 + revDesc2=0; revDescIndx2=0; + MCAuto mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3 + revDesc1=0; revDescIndx1=0; + DataArrayIdType *cellIds1D(0); + mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D); + MCAuto cellIds1DTmp(cellIds1D); + std::vector cut3DCurve(mDesc1->getNumberOfCells(),-2); + for(const mcIdType *it=cellIds1D->begin();it!=cellIds1D->end();it++) + cut3DCurve[*it]=-1; + bool sameNbNodes; + { + mcIdType oldNbNodes(mDesc1->getNumberOfNodes()); + mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve); + sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes); + } + std::vector< std::pair > cut3DSurf(mDesc2->getNumberOfCells()); + AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(), + mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(), + desc1->begin(),descIndx1->begin(),cut3DSurf); + MCAuto conn(DataArrayIdType::New()),connI(DataArrayIdType::New()); + connI->pushBackSilent(0); conn->alloc(0,1); + { + MCAuto cellIds2(DataArrayIdType::New()); cellIds2->alloc(0,1); + assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2); + if(cellIds2->empty()) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !"); + } + std::vector > res; + buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res); + std::size_t sz(res.size()); + if(ToIdType(res.size())==mDesc1->getNumberOfCells() && sameNbNodes) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !"); + for(std::size_t i=0;ipushBackSilent(ToIdType(INTERP_KERNEL::NORM_POLYGON)); + conn->insertAtTheEnd(res[i].begin(),res[i].end()); + connI->pushBackSilent(conn->getNumberOfTuples()); + } + MCAuto ret(MEDCouplingUMesh::New("",2)); + ret->setCoords(mDesc1->getCoords()); + ret->setConnectivity(conn,connI,true); + mcIdType nbCellsRet(ret->getNumberOfCells()); + // + MCAuto vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer()); + MCAuto ortho(ret->buildOrthogonalField()); + MCAuto ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1)); + MCAuto dott(DataArrayDouble::Dot(ortho2,vec2)); + MCAuto ccm(ret->computeCellCenterOfMass()); + MCAuto occm; + { + MCAuto pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer()); + occm=DataArrayDouble::Substract(ccm,pt); + } + vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3); + vec2->setPartOfValuesSimple1(vec[0],0,nbCellsRet,1,0,1,1); vec2->setPartOfValuesSimple1(vec[1],0,nbCellsRet,1,1,2,1); vec2->setPartOfValuesSimple1(vec[2],0,nbCellsRet,1,2,3,1); + MCAuto dott2(DataArrayDouble::Dot(occm,vec2)); + // + const mcIdType *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin()); + MCAuto ret2(MEDCouplingUMesh::New("Clip3D",3)); + ret2->setCoords(mDesc1->getCoords()); + MCAuto conn2(DataArrayIdType::New()),conn2I(DataArrayIdType::New()); + conn2I->pushBackSilent(0); conn2->alloc(0,1); + std::vector cell0(1,ToIdType(INTERP_KERNEL::NORM_POLYHED)); + std::vector cell1(1,ToIdType(INTERP_KERNEL::NORM_POLYHED)); + if(dott->getIJ(0,0)>0) + { + cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]); + std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end())); + } + else + { + cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]); + std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end())); + } + for(mcIdType i=1;igetIJ(i,0)<0) + { + if(ciPtr[i+1]-ciPtr[i]>=4) + { + cell0.push_back(-1); + cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]); + } + } + else + { + if(ciPtr[i+1]-ciPtr[i]>=4) + { + cell1.push_back(-1); + cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]); + } + } + } + conn2->insertAtTheEnd(cell0.begin(),cell0.end()); + conn2I->pushBackSilent(conn2->getNumberOfTuples()); + conn2->insertAtTheEnd(cell1.begin(),cell1.end()); + conn2I->pushBackSilent(conn2->getNumberOfTuples()); + ret2->setConnectivity(conn2,conn2I,true); + ret2->checkConsistencyLight(); + ret2->orientCorrectlyPolyhedrons(); + return ret2; +} + /*! * Finds cells whose bounding boxes intersect a given plane. * \param [in] origin - 3 components of a point defining location of the plane. * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude * must be greater than 1e-6. * \param [in] eps - half-thickness of the plane. - * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found + * \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of the 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. @@ -4007,7 +3802,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const * \throw If magnitude of \a vec is less than 1e-6. * \sa buildSlice3D() */ -DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const +DataArrayIdType *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const { checkFullyDefined(); if(getSpaceDimension()!=3) @@ -4018,14 +3813,14 @@ DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, co double vec2[3]; vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1) double angle=acos(vec[2]/normm); - MCAuto cellIds; + MCAuto cellIds; double bbox[6]; if(angle>eps) { MCAuto coo=_coords->deepCopy(); double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2])); if(normm2/normm>1e-6) - MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer()); + DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer()); MCAuto mw=clone(false);//false -> shallow copy mw->setCoords(coo); mw->getBoundingBox(bbox); @@ -4046,19 +3841,18 @@ DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, co * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too. * No consideration of coordinate is done by this method. * A 1D mesh is said contiguous if : a cell i with nodal connectivity (k,p) the cell i+1 the nodal connectivity should be (p,m) - * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull. + * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be useful. */ bool MEDCouplingUMesh::isContiguous1D() const { if(getMeshDimension()!=1) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !"); - int nbCells=getNumberOfCells(); + mcIdType nbCells=getNumberOfCells(); if(nbCells<1) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !"); - const int *connI=_nodal_connec_index->getConstPointer(); - const int *conn=_nodal_connec->getConstPointer(); - int ref=conn[connI[0]+2]; - for(int i=1;ibegin()),*conn(_nodal_connec->begin()); + mcIdType ref=conn[connI[0]+2]; + for(mcIdType i=1;i f=buildDirectionVectorField(); const double *fPtr=f->getArray()->getConstPointer(); double tmp[3]; - for(int i=0;igetConstPointer(); - for(int i=0;i()); std::transform(tmp,tmp+3,v,tmp,std::multiplies()); @@ -4107,7 +3901,7 @@ void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, } /*! - * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. + * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. * \a this is expected to be a mesh so that its space dimension is equal to its * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment. * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates). @@ -4127,7 +3921,7 @@ void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, * dimension - 1. * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints */ -double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const +double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, mcIdType& cellId) const { int meshDim=getMeshDimension(),spaceDim=getSpaceDimension(); if(meshDim!=spaceDim-1) @@ -4135,23 +3929,23 @@ double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd if(meshDim!=2 && meshDim!=1) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !"); checkFullyDefined(); - if((int)std::distance(ptBg,ptEnd)!=spaceDim) + if(ToIdType(std::distance(ptBg,ptEnd))!=spaceDim) { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str()); } - DataArrayInt *ret1=0; - MCAuto pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim); + DataArrayIdType *ret1=0; + MCAuto pts=DataArrayDouble::New(); pts->useArray(ptBg,false,DeallocType::C_DEALLOC,1,spaceDim); MCAuto ret0=distanceToPoints(pts,ret1); - MCAuto ret1Safe(ret1); + MCAuto ret1Safe(ret1); cellId=*ret1Safe->begin(); return *ret0->begin(); } /*! * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point) - * to \a this and the first \a cellId in \a this corresponding to the returned distance. + * to \a this and the first \a cellId in \a this corresponding to the returned distance. * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance). * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this. - * + * * \a this is expected to be a mesh so that its space dimension is equal to its * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment. * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates). @@ -4166,7 +3960,7 @@ double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd * \throw if mesh dimension of \a this is not equal to space dimension - 1. * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint */ -DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const +DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayIdType *& cellIds) const { if(!pts) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !"); @@ -4176,20 +3970,20 @@ DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !"); if(meshDim!=2 && meshDim!=1) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !"); - if(pts->getNumberOfComponents()!=spaceDim) + if(ToIdType(pts->getNumberOfComponents())!=spaceDim) { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !"; throw INTERP_KERNEL::Exception(oss.str()); } checkFullyDefined(); - int nbCells=getNumberOfCells(); + mcIdType nbCells=getNumberOfCells(); if(nbCells==0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !"); - int nbOfPts=pts->getNumberOfTuples(); + mcIdType nbOfPts=pts->getNumberOfTuples(); MCAuto ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1); - MCAuto ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1); - const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin(); - double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin(); + MCAuto ret1=DataArrayIdType::New(); ret1->alloc(nbOfPts,1); + const mcIdType *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin(); + double *ret0Ptr=ret0->getPointer(); mcIdType *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin(); MCAuto bboxArr(getBoundingBoxForBBTree()); const double *bbox(bboxArr->begin()); switch(spaceDim) @@ -4197,10 +3991,10 @@ DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, case 3: { BBTreeDst<3> myTree(bbox,0,0,nbCells); - for(int i=0;i::max(); - std::vector elems; + std::vector elems; myTree.getMinDistanceOfMax(ptsPtr,x); myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems); DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr); @@ -4210,10 +4004,10 @@ DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, case 2: { BBTreeDst<2> myTree(bbox,0,0,nbCells); - for(int i=0;i::max(); - std::vector elems; + std::vector elems; myTree.getMinDistanceOfMax(ptsPtr,x); myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems); DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr); @@ -4229,97 +4023,26 @@ DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, /// @cond INTERNAL -/*! - * \param [in] pt the start pointer (included) of the coordinates of the point - * \param [in] cellIdsBg the start pointer (included) of cellIds - * \param [in] cellIdsEnd the end pointer (excluded) of cellIds - * \param [in] nc nodal connectivity - * \param [in] ncI nodal connectivity index - * \param [in,out] ret0 the min distance between \a this and the external input point - * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned. - * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints - */ -void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) -{ - cellId=-1; - ret0=std::numeric_limits::max(); - for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++) - { - switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]]) - { - case INTERP_KERNEL::NORM_TRI3: - { - double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]); - if(tmp::max(); - for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++) - { - switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]]) - { - case INTERP_KERNEL::NORM_SEG2: - { - std::size_t uselessEntry=0; - double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry); - tmp=sqrt(tmp); - if(tmpgetMeshDimension() != \a this->getSpaceDimension(). */ -int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const +mcIdType MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const { - std::vector elts; + std::vector elts; getCellsContainingPoint(pos,eps,elts); if(elts.empty()) return -1; @@ -4332,7 +4055,7 @@ int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) cons * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method. * \warning This method is suitable if the caller intends to evaluate only one * point, for more points getCellsContainingPoints() is recommended as it is - * faster. + * faster. * \param [in] pos - array of coordinates of the ball central point. * \param [in] eps - ball radius. * \param [out] elts - vector returning ids of the found cells. It is cleared @@ -4345,236 +4068,52 @@ int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) cons * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example". * \endif */ -void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector& elts) const +void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector& elts) const { - MCAuto eltsUg,eltsIndexUg; + MCAuto eltsUg,eltsIndexUg; getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg); elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end()); } -/// @cond INTERNAL - -namespace MEDCoupling +void MEDCouplingUMesh::getCellsContainingPointsZeAlg(const double *pos, mcIdType nbOfPoints, double eps, + MCAuto& elts, MCAuto& eltsIndex, + std::function sensibilityTo2DQuadraticLinearCellsFunc) const { - template - class DummyClsMCUG - { - public: - static const int MY_SPACEDIM=SPACEDIMM; - static const int MY_MESHDIM=8; - typedef int MyConnType; - static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE; - // begin - // useless, but for windows compilation ... - const double* getCoordinatesPtr() const { return 0; } - const int* getConnectivityPtr() const { return 0; } - const int* getConnectivityIndexPtr() const { return 0; } - INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; } - // end - }; - - INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MCAuto,int>& m) - { - INTERP_KERNEL::Edge *ret(0); - MCAuto n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1])); - m[n0]=bg[0]; m[n1]=bg[1]; - switch(typ) + int spaceDim(getSpaceDimension()),mDim(getMeshDimension()); + if(spaceDim==3) { - case INTERP_KERNEL::NORM_SEG2: - { - ret=new INTERP_KERNEL::EdgeLin(n0,n1); - break; - } - case INTERP_KERNEL::NORM_SEG3: + if(mDim==3) { - INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2]; - INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1)); - INTERP_KERNEL::SegSegIntersector inters(*e1,*e2); - // is the SEG3 degenerated, and thus can be reduced to a SEG2? - bool colinearity(inters.areColinears()); - delete e1; delete e2; - if(colinearity) - { ret=new INTERP_KERNEL::EdgeLin(n0,n1); } - else - { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); } - break; + const double *coords=_coords->getConstPointer(); + getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc); } - default: - throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !"); + else + throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !"); } - return ret; - } - - INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map >& mapp2, const int *bg) - { - INTERP_KERNEL::Edge *ret=0; - switch(typ) + else if(spaceDim==2) { - case INTERP_KERNEL::NORM_SEG2: - { - ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first); - break; - } - case INTERP_KERNEL::NORM_SEG3: + if(mDim==2) { - INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first); - INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first); - INTERP_KERNEL::SegSegIntersector inters(*e1,*e2); - // is the SEG3 degenerated, and thus can be reduced to a SEG2? - bool colinearity=inters.areColinears(); - delete e1; delete e2; - if(colinearity) - ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first); - else - ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first); - mapp2[bg[2]].second=false; - break; + const double *coords=_coords->getConstPointer(); + getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc); } - default: - throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !"); + else + throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !"); } - return ret; - } - - /*! - * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from - * the global mesh 'mDesc'. - * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2. - * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'. - */ - INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector& candidates, - std::map& mapp) - { - mapp.clear(); - std::map > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3. - const double *coo=mDesc->getCoords()->getConstPointer(); - const int *c=mDesc->getNodalConnectivity()->getConstPointer(); - const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer(); - std::set s; - for(std::vector::const_iterator it=candidates.begin();it!=candidates.end();it++) - s.insert(c+cI[*it]+1,c+cI[(*it)+1]); - for(std::set::const_iterator it2=s.begin();it2!=s.end();it2++) - { - INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]); - mapp2[*it2]=std::pair(n,true); - } - INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon; - for(std::vector::const_iterator it=candidates.begin();it!=candidates.end();it++) - { - INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]]; - ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1)); - } - for(std::map >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++) - { - if((*it2).second.second) - mapp[(*it2).second.first]=(*it2).first; - ((*it2).second.first)->decrRef(); - } - return ret; - } - - INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector& addCoo) - { - if(nodeId>=offset2) - { - int locId=nodeId-offset2; - return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]); - } - if(nodeId>=offset1) - { - int locId=nodeId-offset1; - return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]); - } - return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]); - } - - /** - * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI). - */ - void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector& addCoo, - const int *desc1Bg, const int *desc1End, const std::vector >& intesctEdges1, - /*output*/std::map& mapp, std::map& mappRev) - { - for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++) - { - int eltId1=abs(*desc1)-1; - for(std::vector::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++) - { - std::map::const_iterator it=mappRev.find(*it1); - if(it==mappRev.end()) - { - INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo); - mapp[node]=*it1; - mappRev[*it1]=node; - } - } - } - } -} - -/// @endcond - -template -void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints, - double eps, MCAuto& elts, MCAuto& eltsIndex) const -{ - elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1); - int *eltsIndexPtr(eltsIndex->getPointer()); - MCAuto bboxArr(getBoundingBoxForBBTree(eps)); - const double *bbox(bboxArr->begin()); - int nbOfCells=getNumberOfCells(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - double bb[2*SPACEDIM]; - BBTree myTree(&bbox[0],0,0,nbOfCells,-eps); - for(int i=0;i candidates; - myTree.getIntersectingElems(bb,candidates); - for(std::vector::const_iterator iter=candidates.begin();iter!=candidates.end();iter++) + else if(spaceDim==1) + { + if(mDim==1) { - int sz(connI[(*iter)+1]-connI[*iter]-1); - INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]); - bool status(false); - if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG) - status=INTERP_KERNEL::PointLocatorAlgos >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps); - else - { - if(SPACEDIM!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !"); - INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps; - INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps; - std::vector nodes(sz); - INTERP_KERNEL::QuadraticPolygon *pol(0); - for(int j=0;jnormalizeMe(b,c); n->applySimilarity(b,c,a); - status=pol->isInOrOut2(n); - delete pol; n->decrRef(); - } - if(status) - { - eltsIndexPtr[i+1]++; - elts->pushBackSilent(*iter); - } + const double *coords=_coords->getConstPointer(); + getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc); } + else + throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !"); } + else + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !"); } + /*! * Finds cells in contact with several balls (i.e. points with precision). * This method is an extension of getCellContainingPoint() and @@ -4583,7 +4122,7 @@ void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const d * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method. * \param [in] pos - an array of coordinates of points in full interlace mode : * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a - * this->getSpaceDimension() * \a nbOfPoints + * this->getSpaceDimension() * \a nbOfPoints * \param [in] nbOfPoints - number of points to locate within \a this mesh. * \param [in] eps - radius of balls (i.e. the precision). * \param [out] elts - vector returning ids of found cells. @@ -4604,47 +4143,24 @@ void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const d * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example". * \endif */ -void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps, - MCAuto& elts, MCAuto& eltsIndex) const +void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, mcIdType nbOfPoints, double eps, + MCAuto& elts, MCAuto& eltsIndex) const { - int spaceDim=getSpaceDimension(); - int mDim=getMeshDimension(); - if(spaceDim==3) - { - if(mDim==3) - { - const double *coords=_coords->getConstPointer(); - getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex); - } - /*else if(mDim==2) - { + auto yesImSensibleTo2DQuadraticLinearCellsFunc([](INTERP_KERNEL::NormalizedCellType ct, int mdim) { return INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic() && mdim == 2; } ); + this->getCellsContainingPointsZeAlg(pos,nbOfPoints,eps,elts,eltsIndex,yesImSensibleTo2DQuadraticLinearCellsFunc); +} - }*/ - else - throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !"); - } - else if(spaceDim==2) - { - if(mDim==2) - { - const double *coords=_coords->getConstPointer(); - getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex); - } - else - throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !"); - } - else if(spaceDim==1) - { - if(mDim==1) - { - const double *coords=_coords->getConstPointer(); - getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex); - } - else - throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !"); - } - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !"); +/*! + * Behaves like MEDCouplingMesh::getCellsContainingPoints for cells in \a this that are linear. + * For quadratic cells in \a this, this method behaves by just considering linear part of cells. + * This method is here only for backward compatibility (interpolation GaussPoints to GaussPoints). + * + * \sa MEDCouplingUMesh::getCellsContainingPoints, MEDCouplingRemapper::prepareNotInterpKernelOnlyGaussGauss + */ +void MEDCouplingUMesh::getCellsContainingPointsLinearPartOnlyOnNonDynType(const double *pos, mcIdType nbOfPoints, double eps, MCAuto& elts, MCAuto& eltsIndex) const +{ + auto noImNotSensibleTo2DQuadraticLinearCellsFunc([](INTERP_KERNEL::NormalizedCellType,mcIdType) { return false; } ); + this->getCellsContainingPointsZeAlg(pos,nbOfPoints,eps,elts,eltsIndex,noImNotSensibleTo2DQuadraticLinearCellsFunc); } /*! @@ -4657,7 +4173,7 @@ void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoint * \throw If \a this->getMeshDimension() != 2. * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3. */ -void MEDCouplingUMesh::checkButterflyCells(std::vector& cells, double eps) const +void MEDCouplingUMesh::checkButterflyCells(std::vector& cells, double eps) const { const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!"; if(getMeshDimension()!=2) @@ -4665,14 +4181,14 @@ void MEDCouplingUMesh::checkButterflyCells(std::vector& cells, double eps) int spaceDim=getSpaceDimension(); if(spaceDim!=2 && spaceDim!=3) throw INTERP_KERNEL::Exception(msg); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - int nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->getConstPointer(); + const mcIdType *connI=_nodal_connec_index->getConstPointer(); + mcIdType nbOfCells=getNumberOfCells(); std::vector cell2DinS2; - for(int i=0;i& cells, double eps) * * This method expects that space dimension is equal to 2 and mesh dimension is equal to 2 too. If it is not the case an INTERP_KERNEL::Exception will be thrown. * This method works only for linear 2D cells. If there is any of non linear cells (INTERP_KERNEL::NORM_QUAD8 for example) an INTERP_KERNEL::Exception will be thrown too. - * + * * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell. * This convex envelop is computed using Jarvis march algorithm. * The coordinates and the number of cells of \b this remain unchanged on invocation of this method. @@ -4698,26 +4214,26 @@ void MEDCouplingUMesh::checkButterflyCells(std::vector& cells, double eps) * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned. * \sa MEDCouplingUMesh::colinearize2D */ -DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() +DataArrayIdType *MEDCouplingUMesh::convexEnvelop2D() { if(getMeshDimension()!=2 || getSpaceDimension()!=2) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !"); checkFullyDefined(); const double *coords=getCoords()->getConstPointer(); - int nbOfCells=getNumberOfCells(); - MCAuto nodalConnecIndexOut=DataArrayInt::New(); + mcIdType nbOfCells=getNumberOfCells(); + MCAuto nodalConnecIndexOut=DataArrayIdType::New(); nodalConnecIndexOut->alloc(nbOfCells+1,1); - MCAuto nodalConnecOut(DataArrayInt::New()); - int *workIndexOut=nodalConnecIndexOut->getPointer(); + MCAuto nodalConnecOut(DataArrayIdType::New()); + mcIdType *workIndexOut=nodalConnecIndexOut->getPointer(); *workIndexOut=0; - const int *nodalConnecIn=_nodal_connec->getConstPointer(); - const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer(); + const mcIdType *nodalConnecIn=_nodal_connec->getConstPointer(); + const mcIdType *nodalConnecIndexIn=_nodal_connec_index->getConstPointer(); std::set types; - MCAuto isChanged(DataArrayInt::New()); + MCAuto isChanged(DataArrayIdType::New()); isChanged->alloc(0,1); - for(int i=0;igetNumberOfTuples(); + mcIdType pos=nodalConnecOut->getNumberOfTuples(); if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut)) isChanged->pushBackSilent(i); types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0)); @@ -4741,7 +4257,7 @@ DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() * the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done * along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the * arc. - * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this. + * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this. */ MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy) { @@ -4763,7 +4279,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *me else throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !"); } - int oldNbOfNodes(getNumberOfNodes()); + mcIdType oldNbOfNodes(getNumberOfNodes()); MCAuto newCoords; switch(policy) { @@ -4786,350 +4302,60 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *me return ret.retn(); } + /*! - * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3). - * If it is not the case an exception will be thrown. - * This method is non const because the coordinate of \a this can be appended with some new points issued from - * intersection of plane defined by ('origin','vec'). - * This method has one in/out parameter : 'cut3DCurve'. - * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()') - * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously. - * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec'). - * This method will throw an exception if \a this contains a non linear segment. + * Checks if \a this mesh is constituted by only quadratic cells. + * \return bool - \c true if there are only quadratic cells in \a this mesh. + * \throw If the coordinates array is not set. + * \throw If the nodal connectivity of cells is not defined. */ -void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector& cut3DCurve) +bool MEDCouplingUMesh::isFullyQuadratic() const { checkFullyDefined(); - if(getMeshDimension()!=1 || getSpaceDimension()!=3) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !"); - int ncells=getNumberOfCells(); - int nnodes=getNumberOfNodes(); - double vec2[3],vec3[3],vec4[3]; - double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]); - if(normm<1e-6) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !"); - vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm; - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coo=_coords->getConstPointer(); - std::vector addCoo; - for(int i=0;ieps)//if colin<=eps -> current SEG2 is colinear to the input plane - { - const double *st2=coo+3*st; - vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2]; - double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])); - if(pos>eps && pos<1-eps) - { - int nNode=((int)addCoo.size())/3; - vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2]; - addCoo.insert(addCoo.end(),vec4,vec4+3); - cut3DCurve[i]=nnodes+nNode; - } - } - } - } - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !"); - } - if(!addCoo.empty()) + bool ret=true; + mcIdType nbOfCells=getNumberOfCells(); + for(mcIdType i=0;i coo2=DataArrayDouble::New(); - coo2->alloc(newNbOfNodes,3); - double *tmp=coo2->getPointer(); - tmp=std::copy(_coords->begin(),_coords->end(),tmp); - std::copy(addCoo.begin(),addCoo.end(),tmp); - DataArrayDouble::SetArrayIn(coo2,_coords); + INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i); + const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type); + ret=cm.isQuadratic(); } + return ret; } /*! - * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method. - * \param mesh1D is the input 1D mesh used for translation computation. - * \return newCoords new coords filled by this method. + * Checks if \a this mesh includes any quadratic cell. + * \return bool - \c true if there is at least one quadratic cells in \a this mesh. + * \throw If the coordinates array is not set. + * \throw If the nodal connectivity of cells is not defined. */ -DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const +bool MEDCouplingUMesh::isPresenceOfQuadratic() const { - int oldNbOfNodes=getNumberOfNodes(); - int nbOf1DCells=mesh1D->getNumberOfCells(); - int spaceDim=getSpaceDimension(); - DataArrayDouble *ret=DataArrayDouble::New(); - std::vector isQuads; - int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1; - ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim); - double *retPtr=ret->getPointer(); - const double *coords=getCoords()->getConstPointer(); - double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr); - std::vector v; - std::vector c; - double vec[3]; - v.reserve(3); - c.reserve(6); - for(int i=0;igetNodeIdsOfCell(i,v); - c.resize(0); - mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c); - mesh1D->getCoordinatesOfNode(v[0],c); - std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus()); - for(int j=0;j()); - if(isQuad) - { - c.resize(0); - mesh1D->getCoordinatesOfNode(v[1],c); - mesh1D->getCoordinatesOfNode(v[0],c); - std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus()); - for(int j=0;j()); - } + checkFullyDefined(); + bool ret=false; + mcIdType nbOfCells=getNumberOfCells(); + for(mcIdType i=0;icopyStringInfoFrom(*getCoords()); return ret; } /*! - * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method. - * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation. - * \return newCoords new coords filled by this method. - */ -DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const -{ - if(mesh1D->getSpaceDimension()==2) - return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad); - if(mesh1D->getSpaceDimension()==3) - return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad); - throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !"); -} - -/*! - * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method. - * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation. - * \return newCoords new coords filled by this method. + * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a + * this mesh, it remains unchanged. + * \throw If the coordinates array is not set. + * \throw If the nodal connectivity of cells is not defined. */ -DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const -{ - if(isQuad) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !"); - int oldNbOfNodes=getNumberOfNodes(); - int nbOf1DCells=mesh1D->getNumberOfCells(); - if(nbOf1DCells<2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !"); - MCAuto ret=DataArrayDouble::New(); - int nbOfLevsInVec=nbOf1DCells+1; - ret->alloc(oldNbOfNodes*nbOfLevsInVec,2); - double *retPtr=ret->getPointer(); - retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr); - MCAuto tmp=MEDCouplingUMesh::New(); - MCAuto tmp2=getCoords()->deepCopy(); - tmp->setCoords(tmp2); - const double *coo1D=mesh1D->getCoords()->getConstPointer(); - const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer(); - const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer(); - for(int i=1;itranslate(vec); - double tmp3[2],radius,alpha,alpha0; - const double *p0=i+1rotate(end,0,angle); - retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr); - } - return ret.retn(); -} - -/*! - * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method. - * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation. - * \return newCoords new coords filled by this method. - */ -DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const -{ - if(isQuad) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !"); - int oldNbOfNodes=getNumberOfNodes(); - int nbOf1DCells=mesh1D->getNumberOfCells(); - if(nbOf1DCells<2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !"); - MCAuto ret=DataArrayDouble::New(); - int nbOfLevsInVec=nbOf1DCells+1; - ret->alloc(oldNbOfNodes*nbOfLevsInVec,3); - double *retPtr=ret->getPointer(); - retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr); - MCAuto tmp=MEDCouplingUMesh::New(); - MCAuto tmp2=getCoords()->deepCopy(); - tmp->setCoords(tmp2); - const double *coo1D=mesh1D->getCoords()->getConstPointer(); - const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer(); - const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer(); - for(int i=1;itranslate(vec); - double tmp3[2],radius,alpha,alpha0; - const double *p0=i+11.e-7) - { - vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm; - double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]); - double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2}; - double s2=norm2; - double c2=cos(asin(s2)); - double m[3][3]={ - {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2}, - {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2}, - {-vec2[1]*s2, vec2[0]*s2, c2} - }; - double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]}; - double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]}; - double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]}; - INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0); - double cosangle=i+1rotate(end,vecPlane,angle); - } - retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr); - } - return ret.retn(); -} - -/*! - * This method is private because not easy to use for end user. This method is const contrary to - * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain - * the coords sorted slice by slice. - * \param isQuad specifies presence of quadratic cells. - */ -MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const -{ - int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1); - int nbOf2DCells(getNumberOfCells()); - int nbOf3DCells(nbOf2DCells*nbOf1DCells); - MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1)); - const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin()); - MCAuto newConn(DataArrayInt::New()),newConnI(DataArrayInt::New()); - newConnI->alloc(nbOf3DCells+1,1); - int *newConnIPtr(newConnI->getPointer()); - *newConnIPtr++=0; - std::vector newc; - for(int j=0;jalloc((int)(newc.size())*nbOf1DCells,1); - int *newConnPtr(newConn->getPointer()); - int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev); - newConnIPtr=newConnI->getPointer(); - for(int iz=0;iz(),newConnIPtr[iz*nbOf2DCells])); - const int *posOfTypeOfCell(newConnIPtr); - for(std::vector::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++) - { - int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98 - if(icell!=*posOfTypeOfCell) - { - if(*iter!=-1) - *newConnPtr=(*iter)+iz*deltaPerLev; - else - *newConnPtr=-1; - } - else - { - *newConnPtr=*iter; - posOfTypeOfCell++; - } - } - } - ret->setConnectivity(newConn,newConnI,true); - ret->setCoords(getCoords()); - return ret; -} - -/*! - * Checks if \a this mesh is constituted by only quadratic cells. - * \return bool - \c true if there are only quadratic cells in \a this mesh. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - */ -bool MEDCouplingUMesh::isFullyQuadratic() const -{ - checkFullyDefined(); - bool ret=true; - int nbOfCells=getNumberOfCells(); - for(int i=0;igetConstPointer(); - for(int i=0;ibegin(); + for(mcIdType i=0;i newConn=DataArrayInt::New(); - MCAuto newConnI=DataArrayInt::New(); - const int *icptr=_nodal_connec->getConstPointer(); + MCAuto newConn(DataArrayIdType::New()),newConnI(DataArrayIdType::New()); + const mcIdType *icptr(_nodal_connec->begin()); newConn->alloc(getNodalConnectivityArrayLen()-delta,1); newConnI->alloc(nbOfCells+1,1); - int *ocptr=newConn->getPointer(); - int *ociptr=newConnI->getPointer(); + mcIdType *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer()); *ociptr=0; _types.clear(); - for(int i=0;i types; checkFullyDefined(); - MCAuto ret,connSafe,connISafe; + MCAuto ret,connSafe,connISafe; MCAuto coordsSafe; int meshDim=getMeshDimension(); switch(conversionType) @@ -5285,16 +4509,6 @@ void MEDCouplingUMesh::tessellate2D(double eps) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !"); } } -/*! - * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges. - * \warning This method can lead to a huge amount of nodes if \a eps is very low. - * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of - * a sub-divided edge. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * \throw If \a this->getMeshDimension() != 1. - * \throw If \a this->getSpaceDimension() != 2. - */ #if 0 /*! @@ -5317,8 +4531,8 @@ void MEDCouplingUMesh::tessellate2D(double eps) * * \sa buildDescendingConnectivity2 */ -void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit, - const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI) +void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayIdType *nodeIdsToAdd, const DataArrayIdType *nodeIdsIndexToAdd, const DataArrayIdType *edgeIdsToBeSplit, + const MEDCouplingUMesh *mesh1Desc, const DataArrayIdType *desc, const DataArrayIdType *descI, const DataArrayIdType *revDesc, const DataArrayIdType *revDescI) { if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !"); @@ -5327,255 +4541,13 @@ void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !"); if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !"); - //DataArrayInt *out0(0),*outi0(0); + //DataArrayIdType *out0(0),*outi0(0); //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0); - //MCAuto out0s(out0),outi0s(outi0); + //MCAuto out0s(out0),outi0s(outi0); //out0s=out0s->buildUnique(); out0s->sort(true); } #endif -/*! - * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method. - * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells. - * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic. - */ -DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set& types) const -{ - MCAuto bary=computeCellCenterOfMass(); - MCAuto newConn=DataArrayInt::New(); newConn->alloc(0,1); - MCAuto newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0); - MCAuto ret=DataArrayInt::New(); ret->alloc(0,1); - int nbOfCells=getNumberOfCells(); - int nbOfNodes=getNumberOfNodes(); - const int *cPtr=_nodal_connec->getConstPointer(); - const int *icPtr=_nodal_connec_index->getConstPointer(); - int lastVal=0,offset=nbOfNodes; - for(int i=0;ipushBackSilent((int)INTERP_KERNEL::NORM_SEG3); - newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3); - newConn->pushBackSilent(offset++); - lastVal+=4; - newConnI->pushBackSilent(lastVal); - ret->pushBackSilent(i); - } - else - { - types.insert(type); - lastVal+=(icPtr[1]-icPtr[0]); - newConnI->pushBackSilent(lastVal); - newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]); - } - } - MCAuto tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end()); - coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn(); - return ret.retn(); -} - -DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set& types) const -{ - MCAuto newConn=DataArrayInt::New(); newConn->alloc(0,1); - MCAuto newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0); - MCAuto ret=DataArrayInt::New(); ret->alloc(0,1); - // - const int *descPtr(desc->begin()),*descIPtr(descI->begin()); - DataArrayInt *conn1D=0,*conn1DI=0; - std::set types1D; - DataArrayDouble *coordsTmp=0; - MCAuto ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0; - MCAuto coordsTmpSafe(coordsTmp); - MCAuto conn1DSafe(conn1D),conn1DISafe(conn1DI); - const int *c1DPtr=conn1D->begin(); - const int *c1DIPtr=conn1DI->begin(); - int nbOfCells=getNumberOfCells(); - const int *cPtr=_nodal_connec->getConstPointer(); - const int *icPtr=_nodal_connec_index->getConstPointer(); - int lastVal=0; - for(int i=0;ipushBackSilent(typ2); - newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]); - for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++) - newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]); - lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]); - newConnI->pushBackSilent(lastVal); - ret->pushBackSilent(i); - } - else - { - types.insert(typ); - lastVal+=(icPtr[1]-icPtr[0]); - newConnI->pushBackSilent(lastVal); - newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]); - } - } - conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn(); - return ret.retn(); -} - -/*! - * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method. - * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells. - * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic. - */ -DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set& types) const -{ - MCAuto desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New()); - MCAuto m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0; - return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types); -} - -DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set& types) const -{ - MCAuto desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New()); - MCAuto m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0; - // - MCAuto newConn=DataArrayInt::New(); newConn->alloc(0,1); - MCAuto newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0); - MCAuto ret=DataArrayInt::New(); ret->alloc(0,1); - // - MCAuto bary=computeCellCenterOfMass(); - const int *descPtr(desc->begin()),*descIPtr(descI->begin()); - DataArrayInt *conn1D=0,*conn1DI=0; - std::set types1D; - DataArrayDouble *coordsTmp=0; - MCAuto ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0; - MCAuto coordsTmpSafe(coordsTmp); - MCAuto conn1DSafe(conn1D),conn1DISafe(conn1DI); - const int *c1DPtr=conn1D->begin(); - const int *c1DIPtr=conn1DI->begin(); - int nbOfCells=getNumberOfCells(); - const int *cPtr=_nodal_connec->getConstPointer(); - const int *icPtr=_nodal_connec_index->getConstPointer(); - int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples(); - for(int i=0;ipushBackSilent(typ2); - newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]); - for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++) - newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]); - newConn->pushBackSilent(offset+ret->getNumberOfTuples()); - lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1; - newConnI->pushBackSilent(lastVal); - ret->pushBackSilent(i); - } - else - { - types.insert(typ); - lastVal+=(icPtr[1]-icPtr[0]); - newConnI->pushBackSilent(lastVal); - newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]); - } - } - MCAuto tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end()); - coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn(); - return ret.retn(); -} - -/*! - * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method. - * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells. - * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic. - */ -DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set& types) const -{ - MCAuto desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New()); - MCAuto m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0; - return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types); -} - -DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set& types) const -{ - MCAuto desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New()); - MCAuto m2D=buildDescendingConnectivityGen(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0; - MCAuto desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New()); - MCAuto m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0; - // - MCAuto newConn=DataArrayInt::New(); newConn->alloc(0,1); - MCAuto newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0); - MCAuto ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1); - // - MCAuto bary=computeCellCenterOfMass(); - const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin()); - DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0; - std::set types1D,types2D; - DataArrayDouble *coordsTmp=0,*coordsTmp2=0; - MCAuto ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1); - MCAuto conn1DSafe(conn1D),conn1DISafe(conn1DI); - MCAuto coordsTmpSafe(coordsTmp); - MCAuto ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1); - MCAuto coordsTmp2Safe(coordsTmp2); - MCAuto conn2DSafe(conn2D),conn2DISafe(conn2DI); - const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin(); - int nbOfCells=getNumberOfCells(); - const int *cPtr=_nodal_connec->getConstPointer(); - const int *icPtr=_nodal_connec_index->getConstPointer(); - int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples(); - for(int i=0;ipushBackSilent(typ2); - newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]); - for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++) - newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]); - for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++) - { - int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1]; - int tmpPos=newConn->getNumberOfTuples(); - newConn->pushBackSilent(nodeId2); - ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos); - } - newConn->pushBackSilent(offset+ret->getNumberOfTuples()); - lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1; - newConnI->pushBackSilent(lastVal); - ret->pushBackSilent(i); - } - else - { - types.insert(typ); - lastVal+=(icPtr[1]-icPtr[0]); - newConnI->pushBackSilent(lastVal); - newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]); - } - } - MCAuto diffRet2D=ret2D->getDifferentValues(); - MCAuto o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples()); - coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end()); - MCAuto tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end()); - std::vector v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp; - int *c=newConn->getPointer(); - const int *cI(newConnI->begin()); - for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++) - c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset; - offset=coordsTmp2Safe->getNumberOfTuples(); - for(const int *elt=ret->begin();elt!=ret->end();elt++) - c[cI[(*elt)+1]-1]+=offset; - coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn(); - return ret.retn(); -} /*! * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D). @@ -5592,18 +4564,18 @@ DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *& * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image). * * - * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell, + * \return DataArrayIdType * - a new instance of DataArrayIdType 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. * * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2. * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6 - * and \a this->getMeshDimension() != 3. + * 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, MEDCoupling1SGTUMesh::sortHexa8EachOther */ -DataArrayInt *MEDCouplingUMesh::simplexize(int policy) +DataArrayIdType *MEDCouplingUMesh::simplexize(int policy) { switch(policy) { @@ -5611,9 +4583,9 @@ DataArrayInt *MEDCouplingUMesh::simplexize(int policy) return simplexizePol0(); case 1: return simplexizePol1(); - case (int) INTERP_KERNEL::PLANAR_FACE_5: + case INTERP_KERNEL::PLANAR_FACE_5: return simplexizePlanarFace5(); - case (int) INTERP_KERNEL::PLANAR_FACE_6: + case INTERP_KERNEL::PLANAR_FACE_6: return simplexizePlanarFace6(); default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n - 0 or 1 (only available for meshdim=2) \n - PLANAR_FACE_5, PLANAR_FACE_6 (only for meshdim=3)"); @@ -5640,10 +4612,10 @@ bool MEDCouplingUMesh::areOnlySimplexCells() const int mdim=getMeshDimension(); if(mdim<1 || mdim>3) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !"); - int nbCells=getNumberOfCells(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - for(int i=0;ibegin(); + const mcIdType *connI=_nodal_connec_index->begin(); + for(mcIdType i=0;igetMeshDimension() <= 1. + * \throw If the coordinates array is not set. + * \throw If the nodal connectivity of cells is not defined. */ -DataArrayInt *MEDCouplingUMesh::simplexizePol0() +void MEDCouplingUMesh::convertDegeneratedCells() { - checkConnectivityFullyDefined(); - if(getMeshDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !"); - int nbOfCells=getNumberOfCells(); - MCAuto ret=DataArrayInt::New(); - int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4); - ret->alloc(nbOfCells+nbOfCutCells,1); - if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); } - int *retPt=ret->getPointer(); - MCAuto newConn=DataArrayInt::New(); - MCAuto newConnI=DataArrayInt::New(); - newConnI->alloc(nbOfCells+nbOfCutCells+1,1); - newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1); - int *pt=newConn->getPointer(); - int *ptI=newConnI->getPointer(); - ptI[0]=0; - const int *oldc=_nodal_connec->getConstPointer(); - const int *ci=_nodal_connec_index->getConstPointer(); - for(int i=0;igetPointer(); + mcIdType *index=_nodal_connec_index->getPointer(); + mcIdType posOfCurCell=0; + mcIdType newPos=0; + mcIdType lgthOfCurCell; + for(mcIdType i=0;idecrRef(); - _nodal_connec=newConn.retn(); - _nodal_connec_index->decrRef(); - _nodal_connec_index=newConnI.retn(); + if(newPos!=initMeshLgth) + _nodal_connec->reAlloc(newPos); computeTypes(); - updateTime(); - return ret.retn(); } /*! - * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize. + * Same as MEDCouplingUMesh::convertDegeneratedCells() plus deletion of the flat cells. + * A cell is flat in the following cases: + * - for a linear cell, all points in the connectivity are equal + * - for a quadratic cell, either the above, or a quadratic polygon with two (linear) points and two + * identical quadratic points + * \return a new instance of DataArrayIdType holding ids of removed cells. The caller is to delete + * this array using decrRef() as it is no more needed. */ -DataArrayInt *MEDCouplingUMesh::simplexizePol1() +DataArrayIdType *MEDCouplingUMesh::convertDegeneratedCellsAndRemoveFlatOnes() { - checkConnectivityFullyDefined(); - if(getMeshDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !"); - int nbOfCells=getNumberOfCells(); - MCAuto ret=DataArrayInt::New(); - int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4); - ret->alloc(nbOfCells+nbOfCutCells,1); - if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); } - int *retPt=ret->getPointer(); - MCAuto newConn=DataArrayInt::New(); - MCAuto newConnI=DataArrayInt::New(); - newConnI->alloc(nbOfCells+nbOfCutCells+1,1); - newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1); - int *pt=newConn->getPointer(); - int *ptI=newConnI->getPointer(); - ptI[0]=0; - const int *oldc=_nodal_connec->getConstPointer(); - const int *ci=_nodal_connec_index->getConstPointer(); - for(int i=0;i ret(DataArrayIdType::New()); ret->alloc(0,1); + if(nbOfCells<1) + return ret.retn(); + mcIdType initMeshLgth=getNodalConnectivityArrayLen(); + mcIdType *conn=_nodal_connec->getPointer(); + mcIdType *index=_nodal_connec_index->getPointer(); + mcIdType posOfCurCell=0; + mcIdType newPos=0; + mcIdType lgthOfCurCell, nbDelCells(0); + for(mcIdType i=0;ipushBackSilent(i); } - else + else //if the cell is to be deleted, simply stay at the same place { - pt=std::copy(oldc+ci[0],oldc+ci[1],pt); - ptI[1]=ptI[0]+ci[1]-ci[0]; - ptI++; - *retPt++=i; + conn[newPos]=newType; + newPos+=newLgth+1; } + posOfCurCell=index[i+1]; + index[i+1-nbDelCells]=newPos; } - _nodal_connec->decrRef(); - _nodal_connec=newConn.retn(); - _nodal_connec_index->decrRef(); - _nodal_connec_index=newConnI.retn(); + if(newPos!=initMeshLgth) + _nodal_connec->reAlloc(newPos); + const mcIdType nCellDel=ret->getNumberOfTuples(); + if (nCellDel) + _nodal_connec_index->reAlloc(nbOfCells-nCellDel+1); computeTypes(); - updateTime(); return ret.retn(); } /*! - * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize. + * This method remove null 1D cells from \a this. A 1D cell is considered null if start node is equal to end node. + * Only connectivity is considered here. */ -DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() +bool MEDCouplingUMesh::removeDegenerated1DCells() { checkConnectivityFullyDefined(); - if(getMeshDimension()!=3) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !"); - int nbOfCells=getNumberOfCells(); - MCAuto ret=DataArrayInt::New(); - int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8); - ret->alloc(nbOfCells+4*nbOfCutCells,1); - if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); } - int *retPt=ret->getPointer(); - MCAuto newConn=DataArrayInt::New(); - MCAuto newConnI=DataArrayInt::New(); - newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1); - newConn->alloc(getNodalConnectivityArrayLen()+16*nbOfCutCells,1);//21 - int *pt=newConn->getPointer(); - int *ptI=newConnI->getPointer(); - ptI[0]=0; - const int *oldc=_nodal_connec->getConstPointer(); - const int *ci=_nodal_connec_index->getConstPointer(); - for(int i=0;ibegin()),*conni(getNodalConnectivityIndex()->begin()); + { + for(std::size_t i=0;i do nothing + return false; + MCAuto newConn(DataArrayIdType::New()),newConnI(DataArrayIdType::New()); newConnI->alloc(newSize+1,1); newConn->alloc(newSize2,1); + mcIdType *newConnPtr(newConn->getPointer()),*newConnIPtr(newConnI->getPointer()); newConnIPtr[0]=0; + for(std::size_t i=0;idecrRef(); - _nodal_connec=newConn.retn(); - _nodal_connec_index->decrRef(); - _nodal_connec_index=newConnI.retn(); - computeTypes(); - updateTime(); - return ret.retn(); + setConnectivity(newConn,newConnI,true); + return true; } /*! - * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize. + * Finds incorrectly oriented cells of this 2D mesh in 3D space. + * A cell is considered to be oriented correctly if an angle between its + * normal vector and a given vector is less than \c PI / \c 2. + * \param [in] vec - 3 components of the vector specifying the correct orientation of + * cells. + * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are + * checked. + * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It + * is not cleared before filling in. + * \throw If \a this->getMeshDimension() != 2. + * \throw If \a this->getSpaceDimension() != 3. + * + * \if ENABLE_EXAMPLES + * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".
+ * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example". + * \endif */ -DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() -{ - checkConnectivityFullyDefined(); - if(getMeshDimension()!=3) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !"); - int nbOfCells=getNumberOfCells(); - MCAuto ret=DataArrayInt::New(); - int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8); - ret->alloc(nbOfCells+5*nbOfCutCells,1); - if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); } - int *retPt=ret->getPointer(); - MCAuto newConn=DataArrayInt::New(); - MCAuto newConnI=DataArrayInt::New(); - newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1); - newConn->alloc(getNodalConnectivityArrayLen()+21*nbOfCutCells,1); - int *pt=newConn->getPointer(); - int *ptI=newConnI->getPointer(); - ptI[0]=0; - const int *oldc=_nodal_connec->getConstPointer(); - const int *ci=_nodal_connec_index->getConstPointer(); - for(int i=0;idecrRef(); - _nodal_connec=newConn.retn(); - _nodal_connec_index->decrRef(); - _nodal_connec_index=newConnI.retn(); - computeTypes(); - updateTime(); - return ret.retn(); -} - -/*! - * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces, - * so that the number of cells remains the same. Quadratic faces are converted to - * polygons. This method works only for 2D meshes in - * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8, - * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged. - * \warning This method can lead to a huge amount of nodes if \a eps is very low. - * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of - * a polylinized edge constituting the input polygon. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * \throw If \a this->getMeshDimension() != 2. - * \throw If \a this->getSpaceDimension() != 2. - */ -void MEDCouplingUMesh::tessellate2DInternal(double eps) -{ - checkFullyDefined(); - if(getMeshDimension()!=2 || getSpaceDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!"); - double epsa=fabs(eps); - if(epsa::min()) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !"); - MCAuto desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New()); - MCAuto mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1)); - revDesc1=0; revDescIndx1=0; - mDesc->tessellate2D(eps); - subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer()); - setCoords(mDesc->getCoords()); -} - -/*! - * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges. - * \warning This method can lead to a huge amount of nodes if \a eps is very low. - * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of - * a sub-divided edge. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - * \throw If \a this->getMeshDimension() != 1. - * \throw If \a this->getSpaceDimension() != 2. - */ -void MEDCouplingUMesh::tessellate2DCurveInternal(double eps) -{ - checkFullyDefined(); - if(getMeshDimension()!=1 || getSpaceDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!"); - double epsa=fabs(eps); - if(epsa::min()) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !"); - INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10; - int nbCells=getNumberOfCells(); - int nbNodes=getNumberOfNodes(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coords=_coords->getConstPointer(); - std::vector addCoo; - std::vector newConn;//no direct DataArrayInt because interface with Geometric2D - MCAuto newConnI(DataArrayInt::New()); - newConnI->alloc(nbCells+1,1); - int *newConnIPtr=newConnI->getPointer(); - *newConnIPtr=0; - int tmp1[3]; - INTERP_KERNEL::Node *tmp2[3]; - std::set types; - for(int i=0;itesselate(tmp1,nbNodes,epsa,newConn,addCoo); - types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]); - delete eac; - newConnIPtr[1]=(int)newConn.size(); - } - else - { - types.insert(INTERP_KERNEL::NORM_SEG2); - newConn.push_back(INTERP_KERNEL::NORM_SEG2); - newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3); - newConnIPtr[1]=newConnIPtr[0]+3; - } - } - else - { - types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]); - newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]); - newConnIPtr[1]=newConnIPtr[0]+3; - } - } - if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed - return ; - _types=types; - DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index); - MCAuto newConnArr=DataArrayInt::New(); - newConnArr->alloc((int)newConn.size(),1); - std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer()); - DataArrayInt::SetArrayIn(newConnArr,_nodal_connec); - MCAuto newCoords=DataArrayDouble::New(); - newCoords->alloc(nbNodes+((int)addCoo.size())/2,2); - double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer()); - std::copy(addCoo.begin(),addCoo.end(),work); - DataArrayDouble::SetArrayIn(newCoords,_coords); - updateTime(); -} - -/*! - * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown. - * This method completly ignore coordinates. - * \param nodeSubdived is the nodal connectivity of subdivision of edges - * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges - * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2 - * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2 - */ -void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) -{ - checkFullyDefined(); - if(getMeshDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !"); - int nbOfCells=getNumberOfCells(); - int *connI=_nodal_connec_index->getPointer(); - int newConnLgth=0; - for(int i=0;i0; - int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1; - int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1]; - for(int j=0;j0; - int edgeId=std::abs(desc[offset+j])-1; - if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic()) - { - int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1]; - int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1]; - int ref2=direct?id1:id2; - if(ref==ref2) - { - int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1; - newConnLgth+=nbOfSubNodes-1; - ref=direct?id2:id1; - } - else - { - std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !"; - throw INTERP_KERNEL::Exception(oss.str()); - } - } - else - { - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !"); - } - } - newConnLgth++;//+1 is for cell type - connI[1]=newConnLgth; - } - // - MCAuto newConn=DataArrayInt::New(); - newConn->alloc(newConnLgth,1); - int *work=newConn->getPointer(); - for(int i=0;i0; - int edgeId=std::abs(desc[offset+j])-1; - if(direct) - work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work); - else - { - int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1; - std::reverse_iterator it(nodeSubdived+nodeIndxSubdived[edgeId+1]); - work=std::copy(it,it+nbOfSubNodes-1,work); - } - } - } - DataArrayInt::SetArrayIn(newConn,_nodal_connec); - _types.clear(); - if(nbOfCells>0) - _types.insert(INTERP_KERNEL::NORM_POLYGON); -} - -/*! - * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler - * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in - * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method - * does \b not perform geometrical checks and checks only nodal connectivity of cells, - * so it can be useful to call mergeNodes() before calling this method. - * \throw If \a this->getMeshDimension() <= 1. - * \throw If the coordinates array is not set. - * \throw If the nodal connectivity of cells is not defined. - */ -void MEDCouplingUMesh::convertDegeneratedCells() -{ - checkFullyDefined(); - if(getMeshDimension()<=1) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !"); - int nbOfCells=getNumberOfCells(); - if(nbOfCells<1) - return ; - int initMeshLgth=getNodalConnectivityArrayLen(); - int *conn=_nodal_connec->getPointer(); - int *index=_nodal_connec_index->getPointer(); - int posOfCurCell=0; - int newPos=0; - int lgthOfCurCell; - for(int i=0;ireAlloc(newPos); - computeTypes(); -} - -/*! - * Finds incorrectly oriented cells of this 2D mesh in 3D space. - * A cell is considered to be oriented correctly if an angle between its - * normal vector and a given vector is less than \c PI / \c 2. - * \param [in] vec - 3 components of the vector specifying the correct orientation of - * cells. - * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are - * checked. - * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It - * is not cleared before filling in. - * \throw If \a this->getMeshDimension() != 2. - * \throw If \a this->getSpaceDimension() != 3. - * - * \if ENABLE_EXAMPLES - * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".
- * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example". - * \endif - */ -void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector& cells) const +void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector& cells) const { if(getMeshDimension()!=2 || getSpaceDimension()!=3) throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !"); - int nbOfCells=getNumberOfCells(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coordsPtr=_coords->getConstPointer(); - for(int i=0;ibegin(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coordsPtr=_coords->begin(); + for(mcIdType i=0;igetMeshDimension() != 2. @@ -6156,11 +4830,12 @@ void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) { if(getMeshDimension()!=2 || getSpaceDimension()!=3) throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !"); - int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer()); - const int *connI(_nodal_connec_index->getConstPointer()); - const double *coordsPtr(_coords->getConstPointer()); + mcIdType nbOfCells=getNumberOfCells(); + mcIdType *conn(_nodal_connec->getPointer()); + const mcIdType *connI(_nodal_connec_index->begin()); + const double *coordsPtr(_coords->begin()); bool isModified(false); - for(int i=0;igetPointer()); - const int *connI(_nodal_connec_index->getConstPointer()); + mcIdType nbOfCells=getNumberOfCells(); + mcIdType *conn(_nodal_connec->getPointer()); + const mcIdType *connI(_nodal_connec_index->begin()); if(mdim==2) {//2D - for(int i=0;i& cells) const +void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector& cells) const { if(getMeshDimension()!=3 || getSpaceDimension()!=3) throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !"); - int nbOfCells=getNumberOfCells(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coordsPtr=_coords->getConstPointer(); - for(int i=0;ibegin(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coordsPtr=_coords->begin(); + for(mcIdType i=0;i& cell /*! * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point - * out of the cell. + * out of the cell. * \throw If \a this->getMeshDimension() != 3. * \throw If \a this->getSpaceDimension() != 3. * \throw If the coordinates array is not set. @@ -6264,11 +4940,11 @@ void MEDCouplingUMesh::orientCorrectlyPolyhedrons() { if(getMeshDimension()!=3 || getSpaceDimension()!=3) throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !"); - int nbOfCells=getNumberOfCells(); - int *conn=_nodal_connec->getPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coordsPtr=_coords->getConstPointer(); - for(int i=0;igetPointer(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coordsPtr=_coords->begin(); + for(mcIdType i=0;i gts(getAllGeoTypes()); + mcIdType *conn(_nodal_connec->getPointer()); + const mcIdType *conni(_nodal_connec_index->begin()); + for(std::set::const_iterator gt=gts.begin();gt!=gts.end();gt++) + { + INTERP_KERNEL::AutoCppPtr oi(INTERP_KERNEL::OrientationInverter::BuildInstanceFrom(*gt)); + MCAuto cwt(giveCellsWithType(*gt)); + for(const mcIdType *it=cwt->begin();it!=cwt->end();it++) + oi->operate(conn+conni[*it]+1,conn+conni[*it+1]); + } + updateTime(); +} + /*! * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8, * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention * according to which the first facet of the cell should be oriented to have the normal vector * pointing out of cell. - * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed + * \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of fixed * cells. The caller is to delete this array using decrRef() as it is no more - * needed. + * needed. * \throw If \a this->getMeshDimension() != 3. * \throw If \a this->getSpaceDimension() != 3. * \throw If the coordinates array is not set. @@ -6307,7 +5004,7 @@ void MEDCouplingUMesh::orientCorrectlyPolyhedrons() * \endif * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells */ -DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() +DataArrayIdType *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() { const char msg[]="check3DCellsWellOriented detection works only for 3D cells !"; if(getMeshDimension()!=3) @@ -6316,12 +5013,12 @@ DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() if(spaceDim!=3) throw INTERP_KERNEL::Exception(msg); // - int nbOfCells=getNumberOfCells(); - int *conn=_nodal_connec->getPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coo=getCoords()->getConstPointer(); - MCAuto cells(DataArrayInt::New()); cells->alloc(0,1); - for(int i=0;igetPointer(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coo=getCoords()->begin(); + MCAuto cells(DataArrayIdType::New()); cells->alloc(0,1); + for(mcIdType i=0;igetPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coordsPtr=_coords->getConstPointer(); - MCAuto ret=DataArrayInt::New(); ret->alloc(0,1); - for(int i=0;igetPointer(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coordsPtr=_coords->begin(); + MCAuto ret=DataArrayIdType::New(); ret->alloc(0,1); + for(mcIdType i=0;igetConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coordsPtr=_coords->getConstPointer(); - INTERP_KERNEL::areaVectorOfPolygon(conn+1,connI[1]-connI[0]-1,coordsPtr,vec); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coordsPtr=_coords->begin(); + INTERP_KERNEL::areaVectorOfPolygon(conn+1,connI[1]-connI[0]-1,coordsPtr,vec); std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos); } @@ -6428,13 +5125,13 @@ void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4. * For a cell of other type an exception is thrown. * Space dimension of a 2D mesh can be either 2 or 3. - * The Edge Ratio of a cell \f$t\f$ is: + * The Edge Ratio of a cell \f$t\f$ is: * \f$\frac{|t|_\infty}{|t|_0}\f$, * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and * the smallest edge lengths of \f$t\f$. * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on * cells and one time, lying on \a this mesh. The caller is to delete this - * field using decrRef() as it is no more needed. + * field using decrRef() as it is no more needed. * \throw If the coordinates array is not set. * \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. @@ -6456,16 +5153,16 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !"); MCAuto ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); ret->setMesh(this); - int nbOfCells=getNumberOfCells(); + mcIdType nbOfCells=getNumberOfCells(); MCAuto arr=DataArrayDouble::New(); arr->alloc(nbOfCells,1); double *pt=arr->getPointer(); ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef. - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coo=_coords->getConstPointer(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coo=_coords->begin(); double tmp[12]; - for(int i=0;i ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); ret->setMesh(this); - int nbOfCells=getNumberOfCells(); + mcIdType nbOfCells=getNumberOfCells(); MCAuto arr=DataArrayDouble::New(); arr->alloc(nbOfCells,1); double *pt=arr->getPointer(); ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef. - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coo=_coords->getConstPointer(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coo=_coords->begin(); double tmp[12]; - for(int i=0;i ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); ret->setMesh(this); - int nbOfCells=getNumberOfCells(); + mcIdType nbOfCells=getNumberOfCells(); MCAuto arr=DataArrayDouble::New(); arr->alloc(nbOfCells,1); double *pt=arr->getPointer(); ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef. - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coo=_coords->getConstPointer(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coo=_coords->begin(); double tmp[12]; - for(int i=0;i ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); ret->setMesh(this); - int nbOfCells=getNumberOfCells(); + mcIdType nbOfCells=getNumberOfCells(); MCAuto arr=DataArrayDouble::New(); arr->alloc(nbOfCells,1); double *pt=arr->getPointer(); ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef. - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const double *coo=_coords->getConstPointer(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + const double *coo=_coords->begin(); double tmp[12]; - for(int i=0;isetMesh(this); std::set types; ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index); - int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells()); + int spaceDim(getSpaceDimension()); + mcIdType nbCells(getNumberOfCells()); MCAuto arr(DataArrayDouble::New()); arr->alloc(nbCells,1); for(std::set::const_iterator it=types.begin();it!=types.end();it++) { INTERP_KERNEL::AutoCppPtr dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim)); - MCAuto cellIds(giveCellsWithType(*it)); + MCAuto cellIds(giveCellsWithType(*it)); dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer()); } ret->setArray(arr); @@ -6736,11 +5434,11 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const /*! * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax). - * + * * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12) * For all other cases this input parameter is ignored. * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components. - * + * * \throw If \a this is not fully set (coordinates and connectivity). * \throw If a cell in \a this has no valid nodeId. * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic @@ -6772,32 +5470,33 @@ DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) con /*! * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter. * So meshes having quadratic cells the computed bounding boxes can be invalid ! - * + * * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components. - * + * * \throw If \a this is not fully set (coordinates and connectivity). * \throw If a cell in \a this has no valid nodeId. */ DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const { checkFullyDefined(); - int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes()); + int spaceDim(getSpaceDimension()); + mcIdType nbOfCells(getNumberOfCells()), nbOfNodes(getNumberOfNodes()); MCAuto ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim); double *bbox(ret->getPointer()); - for(int i=0;i::max(); bbox[2*i+1]=-std::numeric_limits::max(); } - const double *coordsPtr(_coords->getConstPointer()); - const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer()); - for(int i=0;ibegin()); + const mcIdType *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin()); + for(mcIdType i=0;i=0 && nodeId ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim); double *bbox(ret->getPointer()); - const double *coords(_coords->getConstPointer()); - const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer()); - for(int i=0;ibegin()); + const mcIdType *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin()); + for(mcIdType i=0;i nodes(sz); INTERP_KERNEL::QuadraticPolygon *pol(0); - for(int j=0;jfillBounds(b); delete pol; - bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); + bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); } return ret.retn(); } @@ -6867,7 +5568,7 @@ DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arc * useful for 2D meshes having quadratic cells * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers * the two extremities of the arc of circle). - * + * * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12) * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components. * \throw If \a this is not fully defined. @@ -6878,23 +5579,24 @@ DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arc DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const { checkFullyDefined(); - int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells()); + int spaceDim(getSpaceDimension()),mDim(getMeshDimension()); + mcIdType nbOfCells=getNumberOfCells(); if(spaceDim!=2 || mDim!=1) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!"); + INTERP_KERNEL::QuadraticPlanarPrecision arcPrec(arcDetEps); MCAuto ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim); double *bbox(ret->getPointer()); - const double *coords(_coords->getConstPointer()); - const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer()); - for(int i=0;ibegin()); + const mcIdType *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin()); + for(mcIdType i=0;i nodes(sz); INTERP_KERNEL::Edge *edge(0); - for(int j=0;j MEDCouplingUMesh::getDistributionOfTypes() const +std::vector MEDCouplingUMesh::getDistributionOfTypes() const { checkConnectivityFullyDefined(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const int *work=connI; - int nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + const mcIdType *work=connI; + mcIdType nbOfCells=getNumberOfCells(); std::size_t n=getAllGeoTypes().size(); - std::vector ret(3*n,-1); //ret[3*k+2]==-1 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++) { @@ -6963,8 +5665,8 @@ std::vector MEDCouplingUMesh::getDistributionOfTypes() const } types.insert(typ); ret[3*i]=typ; - const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ)); - ret[3*i+1]=(int)std::distance(work,work2); + const mcIdType *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ)); + ret[3*i+1]=ToIdType(std::distance(work,work2)); work=work2; } return ret; @@ -6982,12 +5684,12 @@ std::vector MEDCouplingUMesh::getDistributionOfTypes() const * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown. * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match, * an exception is thrown too. - * + * * If all geometric types in \a code are exactly those in \a this null pointer is returned. - * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown - * and a DataArrayInt instance is returned that the user has the responsability to deallocate. + * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown + * and a DataArrayIdType instance is returned that the user has the responsibility to deallocate. */ -DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector& code, const std::vector& idsPerType) const +DataArrayIdType *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector& code, const std::vector& idsPerType) const { if(code.empty()) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !"); @@ -6996,7 +5698,7 @@ DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector< if(sz%3!=0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !"); std::vector types; - int nb=0; + mcIdType nb=0; bool isNoPflUsed=true; for(std::size_t i=0;i ret=DataArrayInt::New(); + MCAuto ret=DataArrayIdType::New(); ret->alloc(nb,1); - int *retPtr=ret->getPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - const int *conn=_nodal_connec->getConstPointer(); - int nbOfCells=getNumberOfCells(); - const int *i=connI; + mcIdType *retPtr=ret->getPointer(); + const mcIdType *connI=_nodal_connec_index->begin(); + const mcIdType *conn=_nodal_connec->begin(); + mcIdType nbOfCells=getNumberOfCells(); + const mcIdType *i=connI; int kk=0; for(std::vector::const_iterator it=types.begin();it!=types.end();it++,kk++) { - i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it))); - int offset=(int)std::distance(connI,i); - const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it))); - int nbOfCellsOfCurType=(int)std::distance(i,j); + i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,ToIdType((*it)))); + mcIdType offset=ToIdType(std::distance(connI,i)); + const mcIdType *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType((*it)))); + mcIdType nbOfCellsOfCurType=ToIdType(std::distance(i,j)); if(code[3*kk+2]==-1) - for(int k=0;k=0 && idInIdsPerType<(int)idsPerType.size()) + mcIdType idInIdsPerType=code[3*kk+2]; + if(idInIdsPerType>=0 && idInIdsPerTypecheckAllocated(); if(zePfl->getNumberOfComponents()==1) { - for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++) + for(const mcIdType *k=zePfl->begin();k!=zePfl->end();k++,retPtr++) { if(*k>=0 && *k& code, std::vector& idsInPflPerType, std::vector& idsPerType) const +void MEDCouplingUMesh::splitProfilePerType(const DataArrayIdType *profile, std::vector& code, std::vector& idsInPflPerType, std::vector& idsPerType, bool smartPflKiller) const { if(!profile) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !"); if(profile->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !"); checkConnectivityFullyDefined(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - int nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + mcIdType nbOfCells=getNumberOfCells(); std::vector types; - std::vector typeRangeVals(1); - for(const int *i=connI;i!=connI+nbOfCells;) + std::vector typeRangeVals(1); + for(const mcIdType *i=connI;i!=connI+nbOfCells;) { INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i]; if(std::find(types.begin(),types.end(),curType)!=types.end()) @@ -7108,33 +5810,33 @@ void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vec throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !"); } types.push_back(curType); - i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType)); - typeRangeVals.push_back((int)std::distance(connI,i)); + i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType(curType))); + typeRangeVals.push_back(ToIdType(std::distance(connI,i))); } // - DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0; + DataArrayIdType *castArr=0,*rankInsideCast=0,*castsPresent=0; profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent); - MCAuto tmp0=castArr; - MCAuto tmp1=rankInsideCast; - MCAuto tmp2=castsPresent; + MCAuto tmp0=castArr; + MCAuto tmp1=rankInsideCast; + MCAuto tmp2=castsPresent; // - int nbOfCastsFinal=castsPresent->getNumberOfTuples(); + mcIdType nbOfCastsFinal=castsPresent->getNumberOfTuples(); code.resize(3*nbOfCastsFinal); - std::vector< MCAuto > idsInPflPerType2; - std::vector< MCAuto > idsPerType2; - for(int i=0;i > idsInPflPerType2; + std::vector< MCAuto > idsPerType2; + for(mcIdType i=0;igetIJ(i,0); - MCAuto tmp3=castArr->findIdsEqual(castId); + mcIdType castId=castsPresent->getIJ(i,0); + MCAuto tmp3=castArr->findIdsEqual(castId); idsInPflPerType2.push_back(tmp3); - code[3*i]=(int)types[castId]; + code[3*i]=ToIdType(types[castId]); code[3*i+1]=tmp3->getNumberOfTuples(); - MCAuto tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples()); - if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId])) + MCAuto tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples()); + if(!smartPflKiller || !tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId])) { tmp4->copyStringInfoFrom(*profile); idsPerType2.push_back(tmp4); - code[3*i+2]=(int)idsPerType2.size()-1; + code[3*i+2]=ToIdType(idsPerType2.size())-1; } else { @@ -7145,7 +5847,7 @@ void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vec idsInPflPerType.resize(sz2); for(std::size_t i=0;iincrRef(); idsInPflPerType[i]=locDa; } @@ -7153,7 +5855,7 @@ void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vec idsPerType.resize(sz); for(std::size_t i=0;iincrRef(); idsPerType[i]=locDa; } @@ -7165,7 +5867,7 @@ void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vec * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1' * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered. */ -MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const +MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *&revDesc, DataArrayIdType *&revDescIndx, DataArrayIdType *& nM1LevMeshIds, DataArrayIdType *&meshnM1Old2New) const { checkFullyDefined(); nM1LevMesh->checkFullyDefined(); @@ -7173,20 +5875,20 @@ MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" ); if(_coords!=nM1LevMesh->getCoords()) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !"); - MCAuto tmp0=DataArrayInt::New(); - MCAuto tmp1=DataArrayInt::New(); + MCAuto tmp0=DataArrayIdType::New(); + MCAuto tmp1=DataArrayIdType::New(); MCAuto ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1); - MCAuto ret0=ret1->sortCellsInMEDFileFrmt(); - desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems()); + MCAuto ret0=ret1->sortCellsInMEDFileFrmt(); + desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems()); MCAuto tmp=MEDCouplingUMesh::New(); tmp->setConnectivity(tmp0,tmp1); - tmp->renumberCells(ret0->getConstPointer(),false); + tmp->renumberCells(ret0->begin(),false); revDesc=tmp->getNodalConnectivity(); revDescIndx=tmp->getNodalConnectivityIndex(); - DataArrayInt *ret=0; + DataArrayIdType *ret=0; if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret)) { - int tmp2; + mcIdType tmp2; ret->getMaxValue(tmp2); ret->decrRef(); std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !"; @@ -7206,15 +5908,15 @@ MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is * necessary for writing the mesh to MED file. Additionally returns a permutation array * in "Old to New" mode. - * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete + * \return DataArrayIdType * - a new instance of DataArrayIdType. The caller is to delete * this array using decrRef() as it is no more needed. * \throw If the nodal connectivity of cells is not defined. */ -DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() +DataArrayIdType *MEDCouplingUMesh::sortCellsInMEDFileFrmt() { checkConnectivityFullyDefined(); - MCAuto ret=getRenumArrForMEDFileFrmt(); - renumberCells(ret->getConstPointer(),false); + MCAuto ret=getRenumArrForMEDFileFrmt(); + renumberCells(ret->begin(),false); return ret.retn(); } @@ -7225,17 +5927,17 @@ DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() bool MEDCouplingUMesh::checkConsecutiveCellTypes() const { checkFullyDefined(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - int nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + mcIdType nbOfCells=getNumberOfCells(); std::set types; - for(const int *i=connI;i!=connI+nbOfCells;) + for(const mcIdType *i=connI;i!=connI+nbOfCells;) { INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i]; if(types.find(curType)!=types.end()) return false; types.insert(curType); - i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType)); + i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType(curType))); } return true; } @@ -7243,7 +5945,7 @@ bool MEDCouplingUMesh::checkConsecutiveCellTypes() const /*! * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here. * The geometric type order is specified by MED file. - * + * * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder */ bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const @@ -7260,30 +5962,30 @@ bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const { checkFullyDefined(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - int nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + mcIdType nbOfCells=getNumberOfCells(); if(nbOfCells==0) return true; - int lastPos=-1; + mcIdType lastPos=-1; std::set sg; - for(const int *i=connI;i!=connI+nbOfCells;) + for(const mcIdType *i=connI;i!=connI+nbOfCells;) { INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i]; const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType); if(isTypeExists!=orderEnd) { - int pos=(int)std::distance(orderBg,isTypeExists); + mcIdType pos=ToIdType(std::distance(orderBg,isTypeExists)); if(pos<=lastPos) return false; lastPos=pos; - i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType)); + i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType(curType))); } else { if(sg.find(curType)==sg.end()) { - i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType)); + i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType(curType))); sg.insert(curType); } else @@ -7294,29 +5996,29 @@ bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::No } /*! - * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component, + * This method returns 2 newly allocated DataArrayIdType instances. The first is an array of size 'this->getNumberOfCells()' with one component, * that tells for each cell the pos of its type in the array on type given in input parameter. The 2nd output parameter is an array with the same - * number of tuples than input type array and with one component. This 2nd output array gives type by type the number of occurence of type in 'this'. + * number of tuples than input type array and with one component. This 2nd output array gives type by type the number of occurrence of type in 'this'. */ -DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const +DataArrayIdType *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayIdType *&nbPerType) const { checkConnectivityFullyDefined(); - int nbOfCells=getNumberOfCells(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - MCAuto tmpa=DataArrayInt::New(); - MCAuto tmpb=DataArrayInt::New(); + mcIdType nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + MCAuto tmpa=DataArrayIdType::New(); + MCAuto tmpb=DataArrayIdType::New(); tmpa->alloc(nbOfCells,1); - tmpb->alloc((int)std::distance(orderBg,orderEnd),1); + tmpb->alloc(std::distance(orderBg,orderEnd),1); tmpb->fillWithZero(); - int *tmp=tmpa->getPointer(); - int *tmp2=tmpb->getPointer(); - for(const int *i=connI;i!=connI+nbOfCells;i++) + mcIdType *tmp=tmpa->getPointer(); + mcIdType *tmp2=tmpb->getPointer(); + for(const mcIdType *i=connI;i!=connI+nbOfCells;i++) { const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]); if(where!=orderEnd) { - int pos=(int)std::distance(orderBg,where); + mcIdType pos=ToIdType(std::distance(orderBg,where)); tmp2[pos]++; tmp[std::distance(connI,i)]=pos; } @@ -7335,25 +6037,25 @@ DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::Norma /*! * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec. * - * \return a new object containing the old to new correspondance. + * \return a new object containing the old to new correspondence. * * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt. */ -DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const +DataArrayIdType *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const { return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER); } /*! - * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this. + * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specified by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this. * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells. * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs. * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same. */ -DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const +DataArrayIdType *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const { - DataArrayInt *nbPerType=0; - MCAuto tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType); + DataArrayIdType *nbPerType=0; + MCAuto tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType); nbPerType->decrRef(); return tmpa->buildPermArrPerLevel(); } @@ -7364,31 +6066,31 @@ DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INT * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as * MEDCouplingUMesh::sortCellsInMEDFileFrmt. * - * \return the array giving the correspondance old to new. + * \return the array giving the correspondence old to new. */ -DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes() +DataArrayIdType *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes() { checkFullyDefined(); computeTypes(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - int nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + mcIdType nbOfCells=getNumberOfCells(); std::vector types; - for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());) + for(const mcIdType *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());) if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end()) { INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i]; types.push_back(curType); for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++); } - DataArrayInt *ret=DataArrayInt::New(); + DataArrayIdType *ret=DataArrayIdType::New(); ret->alloc(nbOfCells,1); - int *retPtr=ret->getPointer(); + mcIdType *retPtr=ret->getPointer(); std::fill(retPtr,retPtr+nbOfCells,-1); - int newCellId=0; + mcIdType newCellId=0; for(std::vector::const_iterator iter=types.begin();iter!=types.end();iter++) { - for(const int *i=connI;i!=connI+nbOfCells;i++) + for(const mcIdType *i=connI;i!=connI+nbOfCells;i++) if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter)) retPtr[std::distance(connI,i)]=newCellId++; } @@ -7404,19 +6106,19 @@ DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes() std::vector MEDCouplingUMesh::splitByType() const { checkConnectivityFullyDefined(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - int nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + mcIdType nbOfCells=getNumberOfCells(); std::vector ret; - for(const int *i=connI;i!=connI+nbOfCells;) + for(const mcIdType *i=connI;i!=connI+nbOfCells;) { INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i]; - int beginCellId=(int)std::distance(connI,i); - i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType)); - int endCellId=(int)std::distance(connI,i); - int sz=endCellId-beginCellId; - int *cells=new int[sz]; - for(int j=0;j((MEDCoupling1GTUMesh*)ret); if(retC) { - MCAuto c=convertNodalConnectivityToStaticGeoTypeMesh(); + MCAuto c=convertNodalConnectivityToStaticGeoTypeMesh(); retC->setNodalConnectivity(c); } else @@ -7454,15 +6156,15 @@ MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const MEDCoupling1DGTUMesh *retD=dynamic_cast((MEDCoupling1GTUMesh*)ret); if(!retD) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !"); - DataArrayInt *c=0,*ci=0; + DataArrayIdType *c=0,*ci=0; convertNodalConnectivityToDynamicGeoTypeMesh(c,ci); - MCAuto cs(c),cis(ci); + MCAuto cs(c),cis(ci); retD->setNodalConnectivity(cs,cis); } return ret.retn(); } -DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const +DataArrayIdType *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const { checkConnectivityFullyDefined(); if(_types.size()!=1) @@ -7475,15 +6177,15 @@ DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() co oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !"; throw INTERP_KERNEL::Exception(oss.str()); } - int nbCells=getNumberOfCells(); - int typi=(int)typ; - int nbNodesPerCell=(int)cm.getNumberOfNodes(); - MCAuto 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(); + mcIdType nbCells=getNumberOfCells(); + mcIdType typi=ToIdType(typ); + mcIdType nbNodesPerCell=ToIdType(cm.getNumberOfNodes()); + MCAuto connOut=DataArrayIdType::New(); connOut->alloc(nbCells*nbNodesPerCell,1); + mcIdType *outPtr=connOut->getPointer(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); nbNodesPerCell++; - for(int i=0;igetNumberOfTuples(); + mcIdType nbCells=getNumberOfCells(), + lgth=_nodal_connec->getNumberOfTuples(); if(lgth c(DataArrayInt::New()),ci(DataArrayInt::New()); + MCAuto c(DataArrayIdType::New()),ci(DataArrayIdType::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()); + mcIdType *cp(c->getPointer()),*cip(ci->getPointer()); + const mcIdType *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)) @@ -7537,22 +6240,22 @@ void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt /*! * 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). - * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting + * This method is particularly useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old * are not used here to avoid the build of big permutation array. * * \param [in] ms meshes with same mesh dimension lying on the same coords and sorted by type following de the same geometric type order than * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method. - * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype + * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayIdType instance whose number of tuples is equal to the number of chunks of same geotype * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh. - * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This + * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayIdType instance having the same size than \b szOfCellGrpOfSameType. This * output array gives for each chunck of same type the corresponding mesh id in \b ms. * \return A newly allocated unstructured mesh that is the result of the aggregation on same coords of all meshes in \b ms. This returned mesh * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method. */ MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector& ms, - DataArrayInt *&szOfCellGrpOfSameType, - DataArrayInt *&idInMsOfCellGrpOfSameType) + DataArrayIdType *&szOfCellGrpOfSameType, + DataArrayIdType *&idInMsOfCellGrpOfSameType) { std::vector ms2; for(std::vector::const_iterator it=ms.begin();it!=ms.end();it++) @@ -7570,8 +6273,8 @@ MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(cons // std::vector m1ssmSingle; std::vector< MCAuto > m1ssmSingleAuto; - int fake=0,rk=0; - MCAuto ret1(DataArrayInt::New()),ret2(DataArrayInt::New()); + mcIdType fake=0,rk=0; + MCAuto ret1(DataArrayIdType::New()),ret2(DataArrayIdType::New()); ret1->alloc(0,1); ret2->alloc(0,1); for(std::vector::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++) { @@ -7591,27 +6294,27 @@ MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(cons } } MCAuto m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle); - MCAuto renum=m1ssmSingle2->sortCellsInMEDFileFrmt(); + MCAuto renum=m1ssmSingle2->sortCellsInMEDFileFrmt(); std::vector m1ssmfinal(m1ssm.size()); - for(std::size_t i=0;igetIJ(i,0)]=m1ssm[i]; MCAuto ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal); - szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer()); - idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer()); + szOfCellGrpOfSameType=ret1->renumber(renum->begin()); + idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin()); return ret0.retn(); } /*! - * This method returns a newly created DataArrayInt instance. + * This method returns a newly created DataArrayIdType instance. * 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 +DataArrayIdType *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const mcIdType *begin, const mcIdType *end) const { checkFullyDefined(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connIndex=_nodal_connec_index->getConstPointer(); - MCAuto ret(DataArrayInt::New()); ret->alloc(0,1); - for(const int *w=begin;w!=end;w++) + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connIndex=_nodal_connec_index->begin(); + MCAuto ret(DataArrayIdType::New()); ret->alloc(0,1); + for(const mcIdType *w=begin;w!=end;w++) if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type) ret->pushBackSilent(*w); return ret.retn(); @@ -7621,28 +6324,28 @@ DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellT * This method makes the assumption that da->getNumberOfTuples()getNumberOfCells(). This method makes the assumption that ids contained in 'da' * are in [0:getNumberOfCells()) */ -DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const +DataArrayIdType *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayIdType *da) const { checkFullyDefined(); - const int *conn=_nodal_connec->getConstPointer(); - const int *connI=_nodal_connec_index->getConstPointer(); - int nbOfCells=getNumberOfCells(); + const mcIdType *conn=_nodal_connec->begin(); + const mcIdType *connI=_nodal_connec_index->begin(); + mcIdType nbOfCells=getNumberOfCells(); std::set types(getAllGeoTypes()); - int *tmp=new int[nbOfCells]; + mcIdType *tmp=new mcIdType[nbOfCells]; for(std::set::const_iterator iter=types.begin();iter!=types.end();iter++) { - int j=0; - for(const int *i=connI;i!=connI+nbOfCells;i++) + mcIdType j=0; + for(const mcIdType *i=connI;i!=connI+nbOfCells;i++) if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter)) tmp[std::distance(connI,i)]=j++; } - DataArrayInt *ret=DataArrayInt::New(); + DataArrayIdType *ret=DataArrayIdType::New(); ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents()); ret->copyStringInfoFrom(*da); - int *retPtr=ret->getPointer(); - const int *daPtr=da->getConstPointer(); - int nbOfElems=da->getNbOfElems(); - for(int k=0;kgetPointer(); + const mcIdType *daPtr=da->begin(); + mcIdType nbOfElems=da->getNbOfElems(); + for(mcIdType k=0;k code=getDistributionOfTypes(); + std::vector code=getDistributionOfTypes(); std::size_t nOfTypesInThis=code.size()/3; - int sz=0,szOfType=0; + mcIdType sz=0,szOfType=0; for(std::size_t i=0;i=szOfType) { std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work; oss << ". It should be in [0," << szOfType << ") !"; throw INTERP_KERNEL::Exception(oss.str()); } - MCAuto idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1); - int *idsPtr=idsTokeep->getPointer(); - int offset=0; + MCAuto idsTokeep=DataArrayIdType::New(); idsTokeep->alloc(sz+std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1); + mcIdType *idsPtr=idsTokeep->getPointer(); + mcIdType offset=0; for(std::size_t i=0;i(),offset)); + idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus(),offset)); offset+=code[3*i+1]; } MCAuto ret=static_cast(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true)); @@ -7696,11 +6399,11 @@ MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::Normalized */ std::vector MEDCouplingUMesh::getQuadraticStatus() const { - int ncell=getNumberOfCells(); + mcIdType ncell=getNumberOfCells(); std::vector ret(ncell); - const int *cI=getNodalConnectivityIndex()->getConstPointer(); - const int *c=getNodalConnectivity()->getConstPointer(); - for(int i=0;ibegin(); + const mcIdType *c=getNodalConnectivity()->begin(); + for(mcIdType i=0;igetNumberOfCells() tuples per \a this->getSpaceDimension() * components. The caller is to delete this array using decrRef() as it is @@ -7731,34 +6436,56 @@ MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) * \throw If the coordinates array is not set. * \throw If the nodal connectivity of cells is not defined. * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell + * \sa MEDCouplingUMesh::computeCellCenterOfMassWithPrecision */ DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const { MCAuto ret=DataArrayDouble::New(); int spaceDim=getSpaceDimension(); - int nbOfCells=getNumberOfCells(); + mcIdType nbOfCells=getNumberOfCells(); ret->alloc(nbOfCells,spaceDim); ret->copyStringInfoFrom(*getCoords()); double *ptToFill=ret->getPointer(); - const int *nodal=_nodal_connec->getConstPointer(); - const int *nodalI=_nodal_connec_index->getConstPointer(); - const double *coor=_coords->getConstPointer(); - for(int i=0;ibegin(); + const mcIdType *nodalI=_nodal_connec_index->begin(); + const double *coor=_coords->begin(); + for(mcIdType i=0;i(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill); + INTERP_KERNEL::computeBarycenter2(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill); ptToFill+=spaceDim; } return ret.retn(); } + +/*! + * See computeCellCenterOfMass(). + * \param eps a precision for the detection of degenerated arc of circles. + * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a + * this->getNumberOfCells() tuples per \a this->getSpaceDimension() + * components. 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. + * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell + * \sa MEDCouplingUMesh::computeCellCenterOfMassWithPrecision + */ +DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMassWithPrecision(double eps) const +{ + INTERP_KERNEL::QuadraticPlanarPrecision prec(eps); + MCAuto ret = computeCellCenterOfMass(); + return ret.retn(); +} + + /*! * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting - * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the - * - * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned + * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the + * + * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components. - * + * * \sa MEDCouplingUMesh::computeCellCenterOfMass * \throw If \a this is not fully defined (coordinates and connectivity) * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() ) @@ -7768,20 +6495,20 @@ DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const checkFullyDefined(); MCAuto ret=DataArrayDouble::New(); int spaceDim=getSpaceDimension(); - int nbOfCells=getNumberOfCells(); - int nbOfNodes=getNumberOfNodes(); + mcIdType nbOfCells=getNumberOfCells(); + mcIdType nbOfNodes=getNumberOfNodes(); ret->alloc(nbOfCells,spaceDim); double *ptToFill=ret->getPointer(); - const int *nodal=_nodal_connec->getConstPointer(); - const int *nodalI=_nodal_connec_index->getConstPointer(); - const double *coor=_coords->getConstPointer(); - for(int i=0;ibegin(); + const mcIdType *nodalI=_nodal_connec_index->begin(); + const double *coor=_coords->begin(); + for(mcIdType i=0;i=0 && *conn()); @@ -7791,7 +6518,7 @@ DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw INTERP_KERNEL::Exception(oss.str()); } } - int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1; + mcIdType nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1; if(nbOfNodesInCell>0) std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies(),1./(double)nbOfNodesInCell)); else @@ -7802,9 +6529,9 @@ DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const } else { - std::set s(nodal+nodalI[i]+1,nodal+nodalI[i+1]); + std::set s(nodal+nodalI[i]+1,nodal+nodalI[i+1]); s.erase(-1); - for(std::set::const_iterator it=s.begin();it!=s.end();it++) + for(std::set::const_iterator it=s.begin();it!=s.end();it++) { if(*it>=0 && *it()); @@ -7829,14 +6556,14 @@ DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const /*! * Returns a new DataArrayDouble holding barycenters of specified cells. The * barycenter is computed by averaging coordinates of cell nodes. The cells to treat - * are specified via an array of cell ids. - * \warning Validity of the specified cell ids is not checked! + * are specified via an array of cell ids. + * \warning Validity of the specified cell ids is not checked! * Valid range is [ 0, \a this->getNumberOfCells() ). * \param [in] begin - an array of cell ids of interest. * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element. * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a * end - \a begin ) tuples per \a this->getSpaceDimension() components. The - * caller is to delete this array using decrRef() as it is no more needed. + * 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. * @@ -7845,21 +6572,21 @@ DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example". * \endif */ -DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const +DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const mcIdType *begin, const mcIdType *end) const { DataArrayDouble *ret=DataArrayDouble::New(); int spaceDim=getSpaceDimension(); - int nbOfTuple=(int)std::distance(begin,end); + std::size_t nbOfTuple=std::distance(begin,end); ret->alloc(nbOfTuple,spaceDim); double *ptToFill=ret->getPointer(); double *tmp=new double[spaceDim]; - const int *nodal=_nodal_connec->getConstPointer(); - const int *nodalI=_nodal_connec_index->getConstPointer(); - const double *coor=_coords->getConstPointer(); - for(const int *w=begin;w!=end;w++) + const mcIdType *nodal=_nodal_connec->begin(); + const mcIdType *nodalI=_nodal_connec_index->begin(); + const double *coor=_coords->begin(); + for(const mcIdType *w=begin;w!=end;w++) { INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]]; - INTERP_KERNEL::computeBarycenter2(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill); + INTERP_KERNEL::computeBarycenter2(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill); ptToFill+=spaceDim; } delete [] tmp; @@ -7872,7 +6599,7 @@ DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, c * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2. * The computation of the plane equation is done using each time the 3 first nodes of 2D cells. * This method is useful to detect 2D cells in 3D space that are not coplanar. - * + * * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this. * \throw If spaceDim!=3 or meshDim!=2. * \throw If connectivity of \a this is invalid. @@ -7881,21 +6608,30 @@ DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, c DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const { MCAuto ret(DataArrayDouble::New()); - int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes()); + mcIdType nbOfCells=getNumberOfCells(); + mcIdType nbOfNodes(getNumberOfNodes()); if(getSpaceDimension()!=3 || getMeshDimension()!=2) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !"); ret->alloc(nbOfCells,4); double *retPtr(ret->getPointer()); - const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin()); + const mcIdType *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin()); const double *coor(_coords->begin()); - for(int i=0;i=3) - { + if(nodalI[1]-nodalI[0]>=4) + { + double aa[3]={coor[nodal[nodalI[0]+1+1]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0], + coor[nodal[nodalI[0]+1+1]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1], + coor[nodal[nodalI[0]+1+1]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]} + ,bb[3]={coor[nodal[nodalI[0]+1+2]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0], + coor[nodal[nodalI[0]+1+2]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1], + coor[nodal[nodalI[0]+1+2]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]}; + double cc[3]={aa[1]*bb[2]-aa[2]*bb[1],aa[2]*bb[0]-aa[0]*bb[2],aa[0]*bb[1]-aa[1]*bb[0]}; + double aa_norm(sqrt(aa[0]*aa[0]+aa[1]*aa[1]+aa[2]*aa[2])),bb_norm(sqrt(bb[0]*bb[0]+bb[1]*bb[1]+bb[2]*bb[2])); for(int j=0;j<3;j++) { - int nodeId(nodal[nodalI[0]+1+j]); + mcIdType nodeId(nodal[nodalI[0]+1+j]); if(nodeId>=0 && nodeId(1e-3*aa_norm*bb_norm)) + { + INTERP_KERNEL::inverseMatrix(matrix,4,matrix2); + retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15]; + } + else + { + if(nodalI[1]-nodalI[0]==4) + { + std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : cell" << i << " : Presence of The 3 colinear points !"; + throw INTERP_KERNEL::Exception(oss.str()); + } + // + double dd[3]={0.,0.,0.}; + for(mcIdType offset=nodalI[0]+1;offset()); + mcIdType nbOfNodesInCell(nodalI[1]-nodalI[0]-1); + std::transform(dd,dd+3,dd,std::bind2nd(std::multiplies(),1./(double)nbOfNodesInCell)); + std::copy(dd,dd+3,matrix+4*2); + INTERP_KERNEL::inverseMatrix(matrix,4,matrix2); + retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15]; + } } else { std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !"; throw INTERP_KERNEL::Exception(oss.str()); } - INTERP_KERNEL::inverseMatrix(matrix,4,matrix2); - retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15]; } return ret.retn(); } /*! * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown. - * + * */ MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) { if(!da) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !"); da->checkAllocated(); - MCAuto ret=MEDCouplingUMesh::New(da->getName(),0); + std::string name(da->getName()); + MCAuto ret(MEDCouplingUMesh::New(name,0)); + if(name.empty()) + ret->setName("Mesh"); ret->setCoords(da); - int nbOfTuples=da->getNumberOfTuples(); - MCAuto c=DataArrayInt::New(); - MCAuto cI=DataArrayInt::New(); + mcIdType nbOfTuples(da->getNumberOfTuples()); + MCAuto c(DataArrayIdType::New()),cI(DataArrayIdType::New()); c->alloc(2*nbOfTuples,1); cI->alloc(nbOfTuples+1,1); - int *cp=c->getPointer(); - int *cip=cI->getPointer(); + mcIdType *cp(c->getPointer()),*cip(cI->getPointer()); *cip++=0; - for(int i=0;isetConnectivity(c,cI,true); return ret.retn(); } + +MCAuto MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da) +{ + if(!da) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !"); + da->checkAllocated(); + std::string name(da->getName()); + MCAuto ret; + { + MCAuto tmp(MEDCouplingCMesh::New()); + MCAuto arr(DataArrayDouble::New()); + arr->alloc(da->getNumberOfTuples()); + tmp->setCoordsAt(0,arr); + ret=tmp->buildUnstructured(); + } + ret->setCoords(da); + if(name.empty()) + ret->setName("Mesh"); + else + ret->setName(name); + return ret; +} + /*! * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension. * Cells and nodes of @@ -7979,7 +6759,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, * \throw If \a a[ *i* ]->getMeshDimension() < 0. * \throw If the meshes in \a a are of different dimension (getMeshDimension()). */ -MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector& a) +MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector& a) { std::size_t sz=a.size(); if(sz==0) @@ -7998,7 +6778,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vectorgetCoords(); if(coo) - spaceDim=coo->getNumberOfComponents(); + spaceDim=int(coo->getNumberOfComponents()); } if(spaceDim==-3) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !"); @@ -8010,70 +6790,11 @@ MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector& a) -{ - if(a.empty()) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !"); - std::vector::const_iterator it=a.begin(); - int meshDim=(*it)->getMeshDimension(); - int nbOfCells=(*it)->getNumberOfCells(); - int meshLgth=(*it++)->getNodalConnectivityArrayLen(); - for(;it!=a.end();it++) - { - if(meshDim!=(*it)->getMeshDimension()) - throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !"); - nbOfCells+=(*it)->getNumberOfCells(); - meshLgth+=(*it)->getNodalConnectivityArrayLen(); - } - std::vector aps(a.size()); - std::copy(a.begin(),a.end(),aps.begin()); - MCAuto pts=MergeNodesArray(aps); - MCAuto ret=MEDCouplingUMesh::New("merge",meshDim); - ret->setCoords(pts); - MCAuto c=DataArrayInt::New(); - c->alloc(meshLgth,1); - int *cPtr=c->getPointer(); - MCAuto cI=DataArrayInt::New(); - cI->alloc(nbOfCells+1,1); - int *cIPtr=cI->getPointer(); - *cIPtr++=0; - int offset=0; - int offset2=0; - for(it=a.begin();it!=a.end();it++) - { - int curNbOfCell=(*it)->getNumberOfCells(); - const int *curCI=(*it)->_nodal_connec_index->getConstPointer(); - const int *curC=(*it)->_nodal_connec->getConstPointer(); - cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus(),offset)); - for(int j=0;jgetNumberOfNodes(); - } - // - ret->setConnectivity(c,cI,true); - return ret.retn(); -} - -/// @endcond - /*! * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same * dimension and sharing the node coordinates array. * All cells of the first mesh precede all cells of the second mesh - * within the result mesh. + * within the result mesh. * \param [in] mesh1 - the first mesh. * \param [in] mesh2 - the second mesh. * \return MEDCouplingUMesh * - the result mesh. It is a new instance of @@ -8119,8 +6840,8 @@ MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vectorgetCoords(); int meshDim=meshes.front()->getMeshDimension(); std::vector::const_iterator iter=meshes.begin(); - int meshLgth=0; - int meshIndexLgth=0; + mcIdType meshLgth=0; + mcIdType meshIndexLgth=0; for(;iter!=meshes.end();iter++) { if(coords!=(*iter)->getCoords()) @@ -8130,22 +6851,22 @@ MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vectorgetNodalConnectivityArrayLen(); meshIndexLgth+=(*iter)->getNumberOfCells(); } - MCAuto nodal=DataArrayInt::New(); + MCAuto nodal=DataArrayIdType::New(); nodal->alloc(meshLgth,1); - int *nodalPtr=nodal->getPointer(); - MCAuto nodalIndex=DataArrayInt::New(); + mcIdType *nodalPtr=nodal->getPointer(); + MCAuto nodalIndex=DataArrayIdType::New(); nodalIndex->alloc(meshIndexLgth+1,1); - int *nodalIndexPtr=nodalIndex->getPointer(); - int offset=0; + mcIdType *nodalIndexPtr=nodalIndex->getPointer(); + mcIdType offset=0; for(iter=meshes.begin();iter!=meshes.end();iter++) { - const int *nod=(*iter)->getNodalConnectivity()->getConstPointer(); - const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer(); - int nbOfCells=(*iter)->getNumberOfCells(); - int meshLgth2=(*iter)->getNodalConnectivityArrayLen(); + const mcIdType *nod=(*iter)->getNodalConnectivity()->begin(); + const mcIdType *index=(*iter)->getNodalConnectivityIndex()->begin(); + mcIdType nbOfCells=(*iter)->getNumberOfCells(); + mcIdType meshLgth2=(*iter)->getNodalConnectivityArrayLen(); nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr); if(iter!=meshes.begin()) - nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus(),offset)); + nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus(),offset)); else nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr); offset+=meshLgth2; @@ -8167,7 +6888,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector& meshes, int compType, std::vector& corr) +MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector& meshes, int compType, std::vector& corr) { //All checks are delegated to MergeUMeshesOnSameCoords MCAuto ret=MergeUMeshesOnSameCoords(meshes); - MCAuto o2n=ret->zipConnectivityTraducer(compType); + MCAuto o2n=ret->zipConnectivityTraducer(compType); corr.resize(meshes.size()); std::size_t nbOfMeshes=meshes.size(); - int offset=0; - const int *o2nPtr=o2n->getConstPointer(); + mcIdType offset=0; + const mcIdType *o2nPtr=o2n->begin(); for(std::size_t i=0;igetNumberOfCells(); + DataArrayIdType *tmp=DataArrayIdType::New(); + mcIdType curNbOfCells=meshes[i]->getNumberOfCells(); tmp->alloc(curNbOfCells,1); std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer()); offset+=curNbOfCells; @@ -8208,7 +6929,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector res=DataArrayDouble::Aggregate(coords); std::vector::const_iterator it=meshes.begin(); - int offset=(*it)->getNumberOfNodes(); + mcIdType offset=(*it)->getNumberOfNodes(); (*it++)->setCoords(res); for(;it!=meshes.end();it++) { - int oldNumberOfNodes=(*it)->getNumberOfNodes(); + mcIdType oldNumberOfNodes=(*it)->getNumberOfNodes(); (*it)->setCoords(res); (*it)->shiftNodeNumbersInConn(offset); offset+=oldNumberOfNodes; @@ -8262,9 +6983,9 @@ void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vectorfindCommonTuples(eps,-1,comm,commI); - MCAuto tmp1(comm),tmp2(commI); - int oldNbOfNodes=coo->getNumberOfTuples(); - int newNbOfNodes; - MCAuto o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes); + MCAuto tmp1(comm),tmp2(commI); + mcIdType oldNbOfNodes=coo->getNumberOfTuples(); + mcIdType newNbOfNodes; + MCAuto o2n=DataArrayIdType::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes); if(oldNbOfNodes==newNbOfNodes) return ; - MCAuto newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes); + MCAuto newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes); for(std::vector::const_iterator it=meshes.begin();it!=meshes.end();it++) { - (*it)->renumberNodesInConn(o2n->getConstPointer()); + (*it)->renumberNodesInConn(o2n->begin()); (*it)->setCoords(newCoords); - } + } } + /*! - * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [ \a connBg , \a connEnd ) and returns its extruded cell by inserting the result at the end of ret. - * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset - * \param isQuad specifies the policy of connectivity. - * @ret in/out parameter in which the result will be append + * This static operates only for coords in 3D. The polygon is specified by its connectivity nodes in [ \a begin , \a end ). */ -void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector& ret) +bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const mcIdType *begin, const mcIdType *end, const double *coords) { - INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0]; - const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType); - ret.push_back(cm.getExtrudedType()); - int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev; - switch(flatType) - { - case INTERP_KERNEL::NORM_POINT1: - { - ret.push_back(connBg[1]); - ret.push_back(connBg[1]+nbOfNodesPerLev); - break; - } - case INTERP_KERNEL::NORM_SEG2: - { - int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz}; - ret.insert(ret.end(),conn,conn+4); - break; - } - case INTERP_KERNEL::NORM_SEG3: - { - int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev}; - ret.insert(ret.end(),conn,conn+8); - break; - } - case INTERP_KERNEL::NORM_QUAD4: - { - int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz}; - ret.insert(ret.end(),conn,conn+8); - break; - } - case INTERP_KERNEL::NORM_TRI3: - { - int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz}; - ret.insert(ret.end(),conn,conn+6); - break; - } - case INTERP_KERNEL::NORM_TRI6: + std::size_t i, ip1; + double v[3]={0.,0.,0.}; + std::size_t sz=std::distance(begin,end); + if(!isQuadratic) + for(i=0;i > ii(ret); - std::copy(connBg+1,connEnd,ii); - *ii++=-1; - std::reverse_iterator rConnBg(connEnd); - std::reverse_iterator rConnEnd(connBg+1); - std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus(),deltaz)); - std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd); - for(std::size_t i=0;i0.); } /*! - * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ). + * The polyhedron is specified by its connectivity nodes in [ \a begin , \a end ). */ -bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords) +bool MEDCouplingUMesh::IsPolyhedronWellOriented(const mcIdType *begin, const mcIdType *end, const double *coords) { - std::vector > edges; + std::vector > edges; std::size_t nbOfFaces=std::count(begin,end,-1)+1; - const int *bgFace=begin; + const mcIdType *bgFace=begin; for(std::size_t i=0;i p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]); + std::pair p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]); if(std::find(edges.begin(),edges.end(),p1)!=edges.end()) return false; edges.push_back(p1); } bgFace=endFace+1; } - return INTERP_KERNEL::calculateVolumeForPolyh2(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION; + return INTERP_KERNEL::calculateVolumeForPolyh2(begin,ToIdType(std::distance(begin,end)),coords)>-EPS_FOR_POLYH_ORIENTATION; } /*! * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ). */ -bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords) +bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const mcIdType *begin, const mcIdType *end, const double *coords) { double vec0[3],vec1[3]; std::size_t sz=std::distance(begin,end); if(sz%2!=0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !"); - int nbOfNodes=(int)sz/2; - INTERP_KERNEL::areaVectorOfPolygon(begin,nbOfNodes,coords,vec0); + mcIdType nbOfNodes=ToIdType(sz/2); + INTERP_KERNEL::areaVectorOfPolygon(begin,nbOfNodes,coords,vec0); const double *pt0=coords+3*begin[0]; const double *pt1=coords+3*begin[nbOfNodes]; vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2]; return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.; } -void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end) +void MEDCouplingUMesh::CorrectExtrudedStaticCell(mcIdType *begin, mcIdType *end) { std::size_t sz=std::distance(begin,end); - INTERP_KERNEL::AutoPtr tmp=new int[sz]; + INTERP_KERNEL::AutoPtr tmp=new mcIdType[sz]; std::size_t nbOfNodes(sz/2); - std::copy(begin,end,(int *)tmp); + std::copy(begin,end,(mcIdType *)tmp); for(std::size_t j=1;j(begin,4,coords,vec0); + INTERP_KERNEL::areaVectorOfPolygon(begin,4,coords,vec0); const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4]; return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.; } /*! - * This method performs a simplyfication of a single polyedron cell. To do that each face of cell whose connectivity is defined by [ \b begin , \b end ) + * This method performs a simplyfication of a single polyedron cell. To do that each face of cell whose connectivity is defined by [ \b begin , \b end ) * is compared with the others in order to find faces in the same plane (with approx of eps). If any, the cells are grouped together and projected to * a 2D space. * @@ -8525,62 +7164,75 @@ bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, con * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded) * \param [out] res the result is put at the end of the vector without any alteration of the data. */ -void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) +void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, mcIdType index, DataArrayIdType *res, MEDCouplingUMesh *faces, + DataArrayIdType *E_Fi, DataArrayIdType *E_F, DataArrayIdType *F_Ei, DataArrayIdType *F_E) { - int nbFaces=std::count(begin+1,end,-1)+1; + mcIdType nbFaces = E_Fi->getIJ(index + 1, 0) - E_Fi->getIJ(index, 0); MCAuto v=DataArrayDouble::New(); v->alloc(nbFaces,3); double *vPtr=v->getPointer(); - MCAuto p=DataArrayDouble::New(); p->alloc(nbFaces,1); + MCAuto p=DataArrayDouble::New(); p->alloc(nbFaces,2); double *pPtr=p->getPointer(); - const int *stFaceConn=begin+1; - for(int i=0;igetPointer(), *e_f = E_F->getPointer(), *f_ei = F_Ei->getPointer(), *f_e = F_E->getPointer(); + const mcIdType *f_idx = faces->getNodalConnectivityIndex()->getPointer(), *f_cnn = faces->getNodalConnectivity()->getPointer(); + for(mcIdType i=0;igetConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr); - stFaceConn=endFaceConn+1; + mcIdType face = e_f[e_fi[index] + i]; + ComputeVecAndPtOfFace(eps, coords->begin(), f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1], vPtr, pPtr); + // to differentiate faces going to different cells: + pPtr++, *pPtr = 0; + for (mcIdType j = f_ei[face]; j < f_ei[face + 1]; j++) + *pPtr += FromIdType(f_e[j]); } pPtr=p->getPointer(); vPtr=v->getPointer(); - DataArrayInt *comm1=0,*commI1=0; + DataArrayIdType *comm1=0,*commI1=0; v->findCommonTuples(eps,-1,comm1,commI1); - MCAuto comm1Auto(comm1),commI1Auto(commI1); - const int *comm1Ptr=comm1->getConstPointer(); - const int *commI1Ptr=commI1->getConstPointer(); - int nbOfGrps1=commI1Auto->getNumberOfTuples()-1; - res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED); - // - MCAuto mm=MEDCouplingUMesh::New("",3); - mm->setCoords(const_cast(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1); - mm->finishInsertingCells(); + for (mcIdType i = 0; i < nbFaces; i++) + if (comm1->findIdFirstEqual(i) < 0) + { + comm1->pushBackSilent(i); + commI1->pushBackSilent(comm1->getNumberOfTuples()); + } + MCAuto comm1Auto(comm1),commI1Auto(commI1); + const mcIdType *comm1Ptr=comm1->begin(); + const mcIdType *commI1Ptr=commI1->begin(); + mcIdType nbOfGrps1=commI1Auto->getNumberOfTuples()-1; + res->pushBackSilent(ToIdType(INTERP_KERNEL::NORM_POLYHED)); // - for(int i=0;i tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]); - DataArrayInt *comm2=0,*commI2=0; + DataArrayIdType *comm2=0,*commI2=0; tmpgrp2->findCommonTuples(eps,-1,comm2,commI2); - MCAuto comm2Auto(comm2),commI2Auto(commI2); - const int *comm2Ptr=comm2->getConstPointer(); - const int *commI2Ptr=commI2->getConstPointer(); - int nbOfGrps2=commI2Auto->getNumberOfTuples()-1; - for(int j=0;jfindIdFirstEqual(j) < 0) + { + comm2->pushBackSilent(j); + commI2->pushBackSilent(comm2->getNumberOfTuples()); + } + MCAuto comm2Auto(comm2),commI2Auto(commI2); + const mcIdType *comm2Ptr=comm2->begin(); + const mcIdType *commI2Ptr=commI2->begin(); + mcIdType nbOfGrps2=commI2Auto->getNumberOfTuples()-1; + for(mcIdType j=0;jinsertAtTheEnd(begin,end); + mcIdType face = e_f[e_fi[index] + comm1Ptr[commI1Ptr[i] + comm2Ptr[commI2Ptr[j]]]]; //hmmm + res->insertAtTheEnd(f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1]); res->pushBackSilent(-1); } else { - int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]]; - MCAuto ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1); + mcIdType pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]]; + MCAuto ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1); ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]); - DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New(); - MCAuto mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef(); - MCAuto mm3=static_cast(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true)); - MCAuto idsNodeTmp=mm3->zipCoordsTraducer(); - MCAuto idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes()); - const int *idsNodePtr=idsNode->getConstPointer(); - double center[3]; center[0]=pPtr[pointId]*vPtr[3*vecId]; center[1]=pPtr[pointId]*vPtr[3*vecId+1]; center[2]=pPtr[pointId]*vPtr[3*vecId+2]; + ids2->transformWithIndArr(e_f + e_fi[index], e_f + e_fi[index + 1]); + MCAuto mm3=static_cast(faces->buildPartOfMySelf(ids2->begin(),ids2->end(),true)); + MCAuto idsNodeTmp=mm3->zipCoordsTraducer(); + MCAuto idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes()); + const mcIdType *idsNodePtr=idsNode->begin(); + double center[3]; center[0]=pPtr[2*pointId]*vPtr[3*vecId]; center[1]=pPtr[2*pointId]*vPtr[3*vecId+1]; center[2]=pPtr[2*pointId]*vPtr[3*vecId+2]; double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.; double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]; if(std::abs(norm)>eps) @@ -8590,13 +7242,13 @@ void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble } mm3->changeSpaceDimension(2); MCAuto mm4=mm3->buildSpreadZonesWithPoly(); - const int *conn4=mm4->getNodalConnectivity()->getConstPointer(); - const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer(); - int nbOfCells=mm4->getNumberOfCells(); - for(int k=0;kgetNodalConnectivity()->begin(); + const mcIdType *connI4=mm4->getNodalConnectivityIndex()->begin(); + mcIdType nbOfCells=mm4->getNumberOfCells(); + for(mcIdType k=0;kpushBackSilent(idsNodePtr[*work]); res->pushBackSilent(-1); } @@ -8609,7 +7261,7 @@ void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble /*! * This method computes the normalized vector of the plane and the pos of the point belonging to the plane and the line defined by the vector going * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ). - * + * * \param [in] eps below that value the dot product of 2 vectors is considered as colinears * \param [in] coords coordinates expected to have 3 components. * \param [in] begin start of the nodal connectivity of the face. @@ -8617,7 +7269,7 @@ void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble * \param [out] v the normalized vector of size 3 * \param [out] p the pos of plane */ -void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) +void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const mcIdType *begin, const mcIdType *end, double *v, double *p) { std::size_t nbPoints=std::distance(begin,end); if(nbPoints<3) @@ -8663,15 +7315,15 @@ void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, c * This method tries to obtain a well oriented polyhedron. * If the algorithm fails, an exception will be thrown. */ -void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) +void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(mcIdType *begin, mcIdType *end, const double *coords) { - std::list< std::pair > edgesOK,edgesFinished; + std::list< std::pair > edgesOK,edgesFinished; std::size_t nbOfFaces=std::count(begin,end,-1)+1; std::vector isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented isPerm[0]=true; - int *bgFace=begin,*endFace=std::find(begin+1,end,-1); + mcIdType *bgFace=begin,*endFace=std::find(begin+1,end,-1); std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace); - for(std::size_t l=0;l p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); } + for(std::size_t l=0;l p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); } // while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end()) { @@ -8686,25 +7338,25 @@ void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, c bool b; for(std::size_t j=0;j p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]); - std::pair p2(p1.second,p1.first); + std::pair p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]); + std::pair p2(p1.second,p1.first); bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end(); bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end(); if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; } } if(isPerm[i]) - { + { if(!b) std::reverse(bgFace+1,endFace); for(std::size_t j=0;j p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]); - std::pair p2(p1.second,p1.first); + std::pair p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]); + std::pair p2(p1.second,p1.first); if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end()) { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); } if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end()) { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); } - std::list< std::pair >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2); + std::list< std::pair >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2); if(it!=edgesOK.end()) { edgesOK.erase(it); @@ -8722,7 +7374,7 @@ void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, c } if(!edgesOK.empty()) { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); } - if(INTERP_KERNEL::calculateVolumeForPolyh2(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION) + if(INTERP_KERNEL::calculateVolumeForPolyh2(begin,ToIdType(std::distance(begin,end)),coords)<-EPS_FOR_POLYH_ORIENTATION) {//not lucky ! The first face was not correctly oriented : reorient all faces... bgFace=begin; for(std::size_t i=0;igetNumberOfNodes()); - const int *n2oPtr(n2o->getConstPointer()); - MCAuto revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New()); - skin->getReverseNodalConnectivity(revNodal,revNodalI); - const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer()); - const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer()); - const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer()); - MCAuto ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1); - int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON; - if(nbOfNodesExpected<1) - return ret.retn(); - int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]); - *work++=n2oPtr[prevNode]; - for(int i=1;i conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3); - conn.erase(prevNode); - if(conn.size()==1) - { - int curNode(*(conn.begin())); - *work++=n2oPtr[curNode]; - std::set shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]); - shar.erase(prevCell); - if(shar.size()==1) - { - prevCell=*(shar.begin()); - prevNode=curNode; - } - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !"); - } - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !"); - } - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !"); - } - return ret.retn(); -} - -DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const -{ - int nbOfNodesExpected(skin->getNumberOfNodes()); - int nbOfTurn(nbOfNodesExpected/2); - const int *n2oPtr(n2o->getConstPointer()); - MCAuto revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New()); - skin->getReverseNodalConnectivity(revNodal,revNodalI); - const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer()); - const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer()); - const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer()); - MCAuto ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1); - int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG; - if(nbOfNodesExpected<1) - return ret.retn(); - int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]); - *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++; - for(int i=1;i conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3); - conn.erase(prevNode); - if(conn.size()==1) - { - int curNode(*(conn.begin())); - *work=n2oPtr[curNode]; - std::set shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]); - shar.erase(prevCell); - if(shar.size()==1) - { - int curCell(*(shar.begin())); - work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]]; - prevCell=curCell; - prevNode=curNode; - work++; - } - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !"); - } - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !"); - } - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !"); - } - return ret.retn(); -} /*! * This method makes the assumption spacedimension == meshdimension == 2. * This method works only for linear cells. - * + * * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0) */ -DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const +DataArrayIdType *MEDCouplingUMesh::buildUnionOf2DMesh() const { if(getMeshDimension()!=2 || getSpaceDimension()!=2) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !"); MCAuto skin(computeSkin()); - int oldNbOfNodes(skin->getNumberOfNodes()); - MCAuto o2n(skin->zipCoordsTraducer()); - int nbOfNodesExpected(skin->getNumberOfNodes()); - MCAuto n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes)); - int nbCells(skin->getNumberOfCells()); + mcIdType oldNbOfNodes(skin->getNumberOfNodes()); + MCAuto o2n(skin->zipCoordsTraducer()); + mcIdType nbOfNodesExpected(skin->getNumberOfNodes()); + MCAuto n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes)); + mcIdType nbCells=skin->getNumberOfCells(); if(nbCells==nbOfNodesExpected) return buildUnionOf2DMeshLinear(skin,n2o); else if(2*nbCells==nbOfNodesExpected) @@ -8853,23 +7414,23 @@ DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const /*! * This method makes the assumption spacedimension == meshdimension == 3. * This method works only for linear cells. - * + * * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0) */ -DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const +DataArrayIdType *MEDCouplingUMesh::buildUnionOf3DMesh() const { if(getMeshDimension()!=3 || getSpaceDimension()!=3) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !"); MCAuto m=computeSkin(); - const int *conn=m->getNodalConnectivity()->getConstPointer(); - const int *connI=m->getNodalConnectivityIndex()->getConstPointer(); - int nbOfCells=m->getNumberOfCells(); - MCAuto ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1); - int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED; + const mcIdType *conn=m->getNodalConnectivity()->begin(); + const mcIdType *connI=m->getNodalConnectivityIndex()->begin(); + mcIdType nbOfCells=m->getNumberOfCells(); + MCAuto ret=DataArrayIdType::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1); + mcIdType *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED; if(nbOfCells<1) return ret.retn(); work=std::copy(conn+connI[0]+1,conn+connI[1],work); - for(int i=1;igetMeshDimension(); - MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New(); - MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New(); + MEDCoupling::DataArrayIdType* indexr=MEDCoupling::DataArrayIdType::New(); + MEDCoupling::DataArrayIdType* revConn=MEDCoupling::DataArrayIdType::New(); this->getReverseNodalConnectivity(revConn,indexr); - const int* indexr_ptr=indexr->getConstPointer(); - const int* revConn_ptr=revConn->getConstPointer(); + const mcIdType* indexr_ptr=indexr->begin(); + const mcIdType* revConn_ptr=revConn->begin(); - const MEDCoupling::DataArrayInt* index; - const MEDCoupling::DataArrayInt* conn; + const MEDCoupling::DataArrayIdType* index; + const MEDCoupling::DataArrayIdType* conn; conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!! index=this->getNodalConnectivityIndex(); - int nbCells=this->getNumberOfCells(); - const int* index_ptr=index->getConstPointer(); - const int* conn_ptr=conn->getConstPointer(); + mcIdType nbCells=this->getNumberOfCells(); + const mcIdType* index_ptr=index->begin(); + const mcIdType* conn_ptr=conn->begin(); //creating graph arcs (cell to cell relations) //arcs are stored in terms of (index,value) notation @@ -8916,25 +7477,25 @@ MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const //warning here one node have less than or equal effective number of cell with it //but cell could have more than effective nodes //because other equals nodes in other domain (with other global inode) - std::vector cell2cell_index(nbCells+1,0); - std::vector cell2cell; + std::vector cell2cell_index(nbCells+1,0); + std::vector cell2cell; cell2cell.reserve(3*nbCells); - for (int icell=0; icell counter; - for (int iconn=index_ptr[icell]+1; iconn counter; + for (mcIdType iconn=index_ptr[icell]+1; iconn::iterator iter=counter.find(icell2); + mcIdType icell2=revConn_ptr[iconnr]; + std::map::iterator iter=counter.find(icell2); if (iter!=counter.end()) (iter->second)++; else counter.insert(std::make_pair(icell2,1)); } } - for (std::map::const_iterator iter=counter.begin(); + for (std::map::const_iterator iter=counter.begin(); iter!=counter.end(); iter++) if (iter->second >= meshDim) { @@ -8945,39 +7506,18 @@ MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const indexr->decrRef(); revConn->decrRef(); cell2cell_index[0]=0; - for (int icell=0; icell\n"; @@ -8996,15 +7536,15 @@ void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData } ofs << " \n"; ofs << " \n"; - const int *cPtr=_nodal_connec->getConstPointer(); - const int *cIPtr=_nodal_connec_index->getConstPointer(); - MCAuto faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1); - MCAuto types=DataArrayInt::New(); types->alloc(nbOfCells,1); - MCAuto offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1); - MCAuto connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1); - int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer(); - int szFaceOffsets=0,szConn=0; - for(int i=0;ibegin(); + const mcIdType *cIPtr=_nodal_connec_index->begin(); + MCAuto faceoffsets=DataArrayIdType::New(); faceoffsets->alloc(nbOfCells,1); + MCAuto types=DataArrayIdType::New(); types->alloc(nbOfCells,1); + MCAuto offsets=DataArrayIdType::New(); offsets->alloc(nbOfCells,1); + MCAuto connectivity=DataArrayIdType::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1); + mcIdType *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer(); + mcIdType szFaceOffsets=0,szConn=0; + for(mcIdType i=0;i c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1); - *w3=szConn+(int)c.size(); szConn+=(int)c.size(); + std::set c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1); + *w3=szConn+ToIdType(c.size()); szConn+=ToIdType(c.size()); w4=std::copy(c.begin(),c.end(),w4); } } types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1); types->writeVTK(ofs,8,"UInt8","types",byteData); - offsets->writeVTK(ofs,8,"Int32","offsets",byteData); + std::string vtkTypeName = Traits::VTKReprStr; + offsets->writeVTK(ofs,8,vtkTypeName,"offsets",byteData); if(szFaceOffsets!=0) {//presence of Polyhedra connectivity->reAlloc(szConn); - faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData); - MCAuto faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1); + faceoffsets->writeVTK(ofs,8,vtkTypeName,"faceoffsets",byteData); + MCAuto faces=DataArrayIdType::New(); faces->alloc(szFaceOffsets,1); w1=faces->getPointer(); - for(int i=0;iwriteVTK(ofs,8,"Int32","faces",byteData); + faces->writeVTK(ofs,8,vtkTypeName,"faces",byteData); } - connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData); + connectivity->writeVTK(ofs,8,vtkTypeName,"connectivity",byteData); ofs << " \n"; ofs << " \n"; ofs << " \n"; @@ -9071,8 +7612,8 @@ void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const { stream << std::endl << "Nodal connectivity NOT set !"; return ; } if(!_nodal_connec_index->isAllocated()) { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; } - int lgth=_nodal_connec_index->getNumberOfTuples(); - int cpt=_nodal_connec_index->getNumberOfComponents(); + mcIdType lgth=_nodal_connec_index->getNumberOfTuples(); + std::size_t cpt=_nodal_connec_index->getNumberOfComponents(); if(cpt!=1 || lgth<1) return ; stream << std::endl << "Number of cells : " << lgth-1 << "."; @@ -9088,1756 +7629,147 @@ std::string MEDCouplingUMesh::getVTKFileExtension() const return std::string("vtu"); } -/*! - * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and - * returns a result mesh constituted by polygons. - * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains - * all nodes from m2. - * The meshes should be in 2D space. In - * addition, returns two arrays mapping cells of the result mesh to cells of the input - * meshes. - * \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1 - * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes) - * \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2 - * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes) - * \param [in] eps - precision used to detect coincident mesh entities. - * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result - * cell an id of the cell of \a m1 it comes from. The caller is to delete - * this array using decrRef() as it is no more needed. - * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result - * cell an id of the cell of \a m2 it comes from. -1 value means that a - * result cell comes from a cell (or part of cell) of \a m1 not overlapped by - * any cell of \a m2. The caller is to delete this array using decrRef() as - * it is no more needed. - * \return MEDCouplingUMesh * - the result 2D mesh which is 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 in any of the meshes. - * \throw If the nodal connectivity of cells is not defined in any of the meshes. - * \throw If any of the meshes is not a 2D mesh in 2D space. - * - * \sa conformize2D, mergeNodes - */ -MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, - double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) -{ - if(!m1 || !m2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !"); - m1->checkFullyDefined(); - m2->checkFullyDefined(); - if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!"); - - // Step 1: compute all edge intersections (new nodes) - std::vector< std::vector > intersectEdge1, colinear2, subDiv2; - MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes - DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0; - std::vector addCoo,addCoordsQuadratic; // coordinates of newly created nodes - IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2, - m1Desc,desc1,descIndx1,revDesc1,revDescIndx1, - addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2); - revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef(); - MCAuto dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2); - MCAuto dd5(m1Desc),dd6(m2Desc); - - // Step 2: re-order newly created nodes according to the ordering found in m2 - std::vector< std::vector > intersectEdge2; - BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2); - subDiv2.clear(); dd5=0; dd6=0; - - // Step 3: - std::vector cr,crI; //no DataArrayInt because interface with Geometric2D - std::vector cNb1,cNb2; //no DataArrayInt because interface with Geometric2D - BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo, - /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2); - - // Step 4: Prepare final result: - MCAuto addCooDa(DataArrayDouble::New()); - addCooDa->alloc((int)(addCoo.size())/2,2); - std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer()); - MCAuto addCoordsQuadraticDa(DataArrayDouble::New()); - addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2); - std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer()); - std::vector coordss(4); - coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa; - MCAuto coo(DataArrayDouble::Aggregate(coordss)); - MCAuto ret(MEDCouplingUMesh::New("Intersect2D",2)); - MCAuto conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer()); - MCAuto connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer()); - MCAuto c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer()); - MCAuto c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer()); - ret->setConnectivity(conn,connI,true); - ret->setCoords(coo); - cellNb1=c1.retn(); cellNb2=c2.retn(); - return ret.retn(); -} -/// @cond INTERNAL -bool IsColinearOfACellOf(const std::vector< std::vector >& intersectEdge1, const std::vector& candidates, int start, int stop, int& retVal) +/** + * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that + * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors). + * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here. + * The caller is to deal with the resulting DataArrayIdType. + * \throw If the coordinate array is not set. + * \throw If the nodal connectivity of the cells is not defined. + * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1 + * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments) + * + * \sa DataArrayIdType::sortEachPairToMakeALinkedList + */ +DataArrayIdType *MEDCouplingUMesh::orderConsecutiveCells1D() const { - if(candidates.empty()) - return false; - for(std::vector::const_iterator it=candidates.begin();it!=candidates.end();it++) + checkFullyDefined(); + if(getMeshDimension()!=1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !"); + + // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments: + MCAuto _d(DataArrayIdType::New()),_dI(DataArrayIdType::New()); + MCAuto _rD(DataArrayIdType::New()),_rDI(DataArrayIdType::New()); + MCAuto m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI)); + const mcIdType *d(_d->begin()), *dI(_dI->begin()); + const mcIdType *rD(_rD->begin()), *rDI(_rDI->begin()); + MCAuto _dsi(_rDI->deltaShiftIndex()); + const mcIdType * dsi(_dsi->begin()); + MCAuto dsii = _dsi->findIdsNotInRange(0,3); + m_points=0; + if (dsii->getNumberOfTuples()) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!"); + + mcIdType nc=getNumberOfCells(); + MCAuto result(DataArrayIdType::New()); + result->alloc(nc,1); + + // set of edges not used so far + std::set edgeSet; + for (mcIdType i=0; i& pool(intersectEdge1[*it]); - int tmp[2]; tmp[0]=start; tmp[1]=stop; - if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end()) - { - retVal=*it+1; - return true; - } - tmp[0]=stop; tmp[1]=start; - if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end()) - { - retVal=-*it-1; - return true; - } - } - return false; -} - -MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector >& intersectEdge2, const DataArrayDouble *coords1, const std::vector& addCoo, const std::map& mergedNodes, const std::vector< std::vector >& colinear2, const std::vector< std::vector >& intersectEdge1, - MCAuto& idsInRetColinear, MCAuto& idsInMesh1DForIdsInRetColinear) -{ - idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1); - idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1); - int nCells(mesh1D->getNumberOfCells()); - if(nCells!=(int)intersectEdge2.size()) - throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !"); - const DataArrayDouble *coo2(mesh1D->getCoords()); - const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin()); - const double *coo2Ptr(coo2->begin()); - int offset1(coords1->getNumberOfTuples()); - int offset2(offset1+coo2->getNumberOfTuples()); - int offset3(offset2+addCoo.size()/2); - std::vector addCooQuad; - MCAuto cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0); - int tmp[4],cicnt(0),kk(0); - for(int i=0;i,int> m; - INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m)); - const std::vector& subEdges(intersectEdge2[i]); - int nbSubEdge(subEdges.size()/2); - for(int j=0;j linePiece; + // fills a list of consecutive segment linked to startSeg. This can go forward or backward. + for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward { - MCAuto n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)); - MCAuto e2(e->buildEdgeLyingOnMe(n1,n2)); - INTERP_KERNEL::Edge *e2Ptr(e2); - std::map::const_iterator itm; - if(dynamic_cast(e2Ptr)) - { - tmp[0]=INTERP_KERNEL::NORM_SEG3; - itm=mergedNodes.find(subEdges[2*j]); - tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j]; - itm=mergedNodes.find(subEdges[2*j+1]); - tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1]; - tmp[3]=offset3+(int)addCooQuad.size()/2; - double tmp2[2]; - e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2); - cicnt+=4; - cOut->insertAtTheEnd(tmp,tmp+4); - ciOut->pushBackSilent(cicnt); - } - else - { - tmp[0]=INTERP_KERNEL::NORM_SEG2; - itm=mergedNodes.find(subEdges[2*j]); - tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j]; - itm=mergedNodes.find(subEdges[2*j+1]); - tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1]; - cicnt+=3; - cOut->insertAtTheEnd(tmp,tmp+3); - ciOut->pushBackSilent(cicnt); - } - int tmp00; - if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00)) + // Fill the list forward (resp. backward) from the start segment: + mcIdType activeSeg = startSeg; + mcIdType prevPointId = -20; + mcIdType ptId; + while (!edgeSet.empty()) { - idsInRetColinear->pushBackSilent(kk); - idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00); - } - } - e->decrRef(); - } - MCAuto ret(MEDCouplingUMesh::New(mesh1D->getName(),1)); - ret->setConnectivity(cOut,ciOut,true); - MCAuto arr3(DataArrayDouble::New()); - arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2); - MCAuto arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2); - std::vector coordss(4); - coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4; - MCAuto arr(DataArrayDouble::Aggregate(coordss)); - ret->setCoords(arr); - return ret.retn(); -} - -MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector >& intersectEdge1) -{ - std::vector allEdges; - for(const int *it2(descBg);it2!=descEnd;it2++) - { - const std::vector& edge1(intersectEdge1[std::abs(*it2)-1]); - if(*it2>0) - allEdges.insert(allEdges.end(),edge1.begin(),edge1.end()); - else - allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend()); - } - std::size_t nb(allEdges.size()); - if(nb%2!=0) - throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !"); - std::size_t nbOfEdgesOf2DCellSplit(nb/2); - MCAuto ret(MEDCouplingUMesh::New("",2)); - ret->setCoords(coords); - ret->allocateCells(1); - std::vector connOut(nbOfEdgesOf2DCellSplit); - for(std::size_t kk=0;kkinsertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]); - return ret.retn(); -} + if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg + { + if (direction==0) + linePiece.push_back(activeSeg); + else + linePiece.push_front(activeSeg); + edgeSet.erase(activeSeg); + } -MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector >& intersectEdge1) -{ - const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin()); - const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]])); - std::size_t ii(0); - unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1)); - if(sz!=std::distance(descBg,descEnd)) - throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !"); - INTERP_KERNEL::AutoPtr tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]); - std::vector allEdges,centers; - const double *coordsPtr(coords->begin()); - MCAuto addCoo(DataArrayDouble::New()); addCoo->alloc(0,1); - int offset(coords->getNumberOfTuples()); - for(const int *it2(descBg);it2!=descEnd;it2++,ii++) - { - INTERP_KERNEL::NormalizedCellType typeOfSon; - cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon); - const std::vector& edge1(intersectEdge1[std::abs(*it2)-1]); - if(*it2>0) - allEdges.insert(allEdges.end(),edge1.begin(),edge1.end()); - else - allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend()); - if(edge1.size()==2) - centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center. - else - {//the current edge has been subsplit -> create corresponding centers. - std::size_t nbOfCentersToAppend(edge1.size()/2); - std::map< MCAuto,int> m; - MCAuto ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m)); - std::vector::const_iterator it3(allEdges.end()-edge1.size()); - for(std::size_t k=0;kgetMiddleOfPoints(aa,bb,tmpp); - addCoo->insertAtTheEnd(tmpp,tmpp+2); - centers.push_back(offset+k); + mcIdType ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1]; + ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2); + if (dsi[ptId] == 1) // hitting the end of the line + break; + prevPointId = ptId; + mcIdType seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1]; + activeSeg = (seg1 == activeSeg) ? seg2 : seg1; } } + // Done, save final piece into DA: + std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx); + newIdx += ToIdType(linePiece.size()); + + // identify next valid start segment (one which is not consumed) + if(!edgeSet.empty()) + startSeg = *(edgeSet.begin()); } - std::size_t nb(allEdges.size()); - if(nb%2!=0) - throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !"); - std::size_t nbOfEdgesOf2DCellSplit(nb/2); - MCAuto ret(MEDCouplingUMesh::New("",2)); - if(addCoo->empty()) - ret->setCoords(coords); - else - { - addCoo->rearrange(2); - addCoo=DataArrayDouble::Aggregate(coords,addCoo); - ret->setCoords(addCoo); - } - ret->allocateCells(1); - std::vector connOut(nbOfEdgesOf2DCellSplit); - for(std::size_t kk=0;kkinsertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]); - return ret.retn(); + while (!edgeSet.empty()); + return result.retn(); } -/*! - * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity - * of those edges. +/** + * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg + * and in \a subNodesInSegI using \ref numbering-indirect storage mode. + * To do the work this method can optionally needs information about middle of subedges for quadratic cases if + * a minimal creation of new nodes is wanted. + * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add + * nodes if a SEG3 is split without information of middle. + * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to + * avoid to have a non conform mesh. * - * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()] + * \return mcIdType - the number of new nodes created (in most of cases 0). + * + * \throw If \a this is not coherent. + * \throw If \a this has not spaceDim equal to 2. + * \throw If \a this has not meshDim equal to 2. + * \throw If some subcells needed to be split are orphan. + * \sa MEDCouplingUMesh::conformize2D */ -MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector >& intersectEdge1) -{ - const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D))); - if(!cm.isQuadratic()) - return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1); - else - return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1); -} - -void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector& conn, const std::vector< MCAuto >& edges) +mcIdType MEDCouplingUMesh::split2DCells(const DataArrayIdType *desc, const DataArrayIdType *descI, const DataArrayIdType *subNodesInSeg, const DataArrayIdType *subNodesInSegI, const DataArrayIdType *midOpt, const DataArrayIdType *midOptI) { - bool isQuad(false); - for(std::vector< MCAuto >::const_iterator it=edges.begin();it!=edges.end();it++) + if(!desc || !descI || !subNodesInSeg || !subNodesInSegI) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !"); + desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated(); + if(getSpaceDimension()!=2 || getMeshDimension()!=2) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !"); + if(midOpt==0 && midOptI==0) { - const INTERP_KERNEL::Edge *ee(*it); - if(dynamic_cast(ee)) - isQuad=true; + split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI); + return 0; } - if(!isQuad) - mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]); + else if(midOpt!=0 && midOptI!=0) + return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI); else - { - const double *coo(mesh2D->getCoords()->begin()); - std::size_t sz(conn.size()); - std::vector addCoo; - std::vector conn2(conn); - int offset(mesh2D->getNumberOfNodes()); - for(std::size_t i=0;igetMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i - addCoo.insert(addCoo.end(),tmp,tmp+2); - conn2.push_back(offset+(int)i); - } - mesh2D->getCoords()->rearrange(1); - mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size()); - mesh2D->getCoords()->rearrange(2); - mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]); - } + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all."); } /*! - * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve. + * This method compute the convex hull of a single 2D cell. This method tries to conserve at maximum the given input connectivity. In particular, if the orientation of cell is not clockwise + * as in MED format norm. If definitely the result of Jarvis algorithm is not matchable with the input connectivity, the result will be copied into \b nodalConnecOut parameter and + * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON. + * This method excepts that \b coords parameter is expected to be in dimension 2. [ \b nodalConnBg , \b nodalConnEnd ) is the nodal connectivity of the input + * cell (geometric cell type included at the position 0). If the meshdimension of the input cell is not equal to 2 an INTERP_KERNEL::Exception will be thrown. * - * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using - * a set of edges defined in \a splitMesh1D. - */ -void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector& edge1Bis, const std::vector< MCAuto >& edge1BisPtr, - std::vector< std::vector >& out0, std::vector< std::vector< MCAuto > >& out1) -{ - std::size_t nb(edge1Bis.size()/2); - std::size_t nbOfEdgesOf2DCellSplit(nb/2); - int iEnd(splitMesh1D->getNumberOfCells()); - if(iEnd==0) - throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !"); - std::size_t ii,jj; - const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin()); - for(ii=0;ii single output cell - out0.resize(1); out1.resize(1); - std::vector& connOut(out0[0]); - connOut.resize(nbOfEdgesOf2DCellSplit); - std::vector< MCAuto >& edgesPtr(out1[0]); - edgesPtr.resize(nbOfEdgesOf2DCellSplit); - for(std::size_t kk=0;kk& connOutLeft(out0[0]); - std::vector& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1] - std::vector< MCAuto >& eleft(out1[0]); - std::vector< MCAuto >& eright(out1[1]); - for(std::size_t k=ii;k > ees(iEnd); - for(int ik=0;ik,int> m; - MCAuto ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m)); - ees[ik]=ee; - } - for(int ik=iEnd-1;ik>=0;ik--) - connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]); - for(std::size_t k=jj+1;k& edges, const std::vector< MCAuto >& edgesPtr); -public: - std::vector _edges; - std::vector< MCAuto > _edges_ptr; -}; - -CellInfo::CellInfo(const std::vector& edges, const std::vector< MCAuto >& edgesPtr) -{ - std::size_t nbe(edges.size()); - std::vector edges2(2*nbe); std::vector< MCAuto > edgesPtr2(2*nbe); - for(std::size_t i=0;i& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { } - EdgeInfo(int istart, int iend, int pos, const MCAuto& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { } - bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; } - void somethingHappendAt(int pos, const std::vector< MCAuto >& newLeft, const std::vector< MCAuto >& newRight); - void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const; -private: - int _istart; - int _iend; - MCAuto _mesh; - MCAuto _edge; - int _left; - int _right; -}; - -void EdgeInfo::somethingHappendAt(int pos, const std::vector< MCAuto >& newLeft, const std::vector< MCAuto >& newRight) + * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered. + */ +bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const mcIdType *nodalConnBg, const mcIdType *nodalConnEnd, DataArrayIdType *nodalConnecOut) { - const MEDCouplingUMesh *mesh(_mesh); - if(mesh) - return ; - if(_rightpos) - { _left++; _right++; return ; } - if(_right==pos) - { - bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end()); - if((isLeft && isRight) || (!isLeft && !isRight)) - throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !"); - if(isLeft) - return ; - if(isRight) - { - _right++; - return ; - } - } - if(_left==pos) + std::size_t sz=std::distance(nodalConnBg,nodalConnEnd); + if(sz>=4) { - bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end()); - if((isLeft && isRight) || (!isLeft && !isRight)) - throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !"); - if(isLeft) - { - _right++; - return ; - } - if(isRight) + const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg); + if(cm.getDimension()==2) { - _left++; - _right++; - return ; - } - } -} - -void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const -{ - const MEDCouplingUMesh *mesh(_mesh); - if(!mesh) - { - neighbors[0]=offset+_left; neighbors[1]=offset+_right; - } - else - {// not fully splitting cell case - if(mesh2D->getNumberOfCells()==1) - {//little optimization. 1 cell no need to find in which cell mesh is ! - neighbors[0]=offset; neighbors[1]=offset; - return; - } - else - { - MCAuto barys(mesh->computeCellCenterOfMass()); - int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps)); - if(cellId==-1) - throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !"); - neighbors[0]=offset+cellId; neighbors[1]=offset+cellId; - } - } -} - -class VectorOfCellInfo -{ -public: - VectorOfCellInfo(const std::vector& edges, const std::vector< MCAuto >& edgesPtr); - std::size_t size() const { return _pool.size(); } - int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const; - void setMeshAt(int pos, const MCAuto& mesh, int istart, int iend, const MCAuto& mesh1DInCase, const std::vector< std::vector >& edges, const std::vector< std::vector< MCAuto > >& edgePtrs); - const std::vector& getConnOf(int pos) const { return get(pos)._edges; } - const std::vector< MCAuto >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; } - MCAuto getZeMesh() const { return _ze_mesh; } - void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const; -private: - int getZePosOfEdgeGivenItsGlobalId(int pos) const; - void updateEdgeInfo(int pos, const std::vector< MCAuto >& newLeft, const std::vector< MCAuto >& newRight); - const CellInfo& get(int pos) const; - CellInfo& get(int pos); -private: - std::vector _pool; - MCAuto _ze_mesh; - std::vector _edge_info; -}; - -VectorOfCellInfo::VectorOfCellInfo(const std::vector& edges, const std::vector< MCAuto >& edgesPtr):_pool(1) -{ - _pool[0]._edges=edges; - _pool[0]._edges_ptr=edgesPtr; -} - -int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const -{ - if(_pool.empty()) - throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !"); - if(_pool.size()==1) - return 0; - const MEDCouplingUMesh *zeMesh(_ze_mesh); - if(!zeMesh) - throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !"); - MCAuto barys(mesh->computeCellCenterOfMass()); - return zeMesh->getCellContainingPoint(barys->begin(),eps); -} - -void VectorOfCellInfo::setMeshAt(int pos, const MCAuto& mesh, int istart, int iend, const MCAuto& mesh1DInCase, const std::vector< std::vector >& edges, const std::vector< std::vector< MCAuto > >& edgePtrs) -{ - get(pos);//to check pos - bool isFast(pos==0 && _pool.size()==1); - std::size_t sz(edges.size()); - // dealing with edges - if(sz==1) - _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase)); - else - _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back())); - // - std::vector pool(_pool.size()-1+sz); - for(int i=0;i > ms; - if(pos>0) - { - MCAuto elt(static_cast(_ze_mesh->buildPartOfMySelfSlice(0,pos,true))); - ms.push_back(elt); - } - ms.push_back(mesh); - if(pos<_ze_mesh->getNumberOfCells()-1) - { - MCAuto elt(static_cast(_ze_mesh->buildPartOfMySelfSlice(pos+1,_ze_mesh->getNumberOfCells(),true))); - ms.push_back(elt); - } - std::vector< const MEDCouplingUMesh *> ms2(ms.size()); - for(std::size_t j=0;j=0 !"); - int ret(0); - for(std::vector::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++) - { - if((*it).isInMyRange(pos)) - return ret; - } - throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !"); -} - -void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MCAuto >& newLeft, const std::vector< MCAuto >& newRight) -{ - get(pos);//to check; - if(_edge_info.empty()) - return ; - std::size_t sz(_edge_info.size()-1); - for(std::size_t i=0;i=(int)_pool.size()) - throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !"); - return _pool[pos]; -} - -CellInfo& VectorOfCellInfo::get(int pos) -{ - if(pos<0 || pos>=(int)_pool.size()) - throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !"); - return _pool[pos]; -} - -/*! - * Given : - * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell. - * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above. - * - * This method returns the 2D mesh and feeds \a idsLeftRight using offset. - * - * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells. - * - * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge. - */ -MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector& allEdges, const std::vector< MCAuto >& allEdgesPtr, int offset, - MCAuto& idsLeftRight) -{ - int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells()); - if(nbCellsInSplitMesh1D==0) - throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !"); - const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin()); - std::size_t nb(allEdges.size()),jj; - if(nb%2!=0) - throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !"); - std::vector edge1Bis(nb*2); - std::vector< MCAuto > edge1BisPtr(nb*2); - std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()); - std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb); - std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()); - std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb); - // - idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2); - int *idsLeftRightPtr(idsLeftRight->getPointer()); - VectorOfCellInfo pool(edge1Bis,edge1BisPtr); - for(int iStart=0;iStart partOfSplitMesh1D(static_cast(splitMesh1D->buildPartOfMySelfSlice(iStart,iEnd,1,true))); - int pos(pool.getPositionOf(eps,partOfSplitMesh1D)); - // - MCAutoretTmp(MEDCouplingUMesh::New("",2)); - retTmp->setCoords(splitMesh1D->getCoords()); - retTmp->allocateCells(); - - std::vector< std::vector > out0; - std::vector< std::vector< MCAuto > > out1; - - BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1); - for(std::size_t cnt=0;cnt >& intersectEdge1, int offset, - MCAuto& idsLeftRight) -{ - const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin()); - // - std::vector allEdges; - std::vector< MCAuto > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D - for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode - { - int edgeId(std::abs(*it)-1); - std::map< MCAuto,int> m; - MCAuto ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m)); - const std::vector& edge1(intersectEdge1[edgeId]); - if(*it>0) - allEdges.insert(allEdges.end(),edge1.begin(),edge1.end()); - else - allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend()); - std::size_t sz(edge1.size()); - for(std::size_t cnt=0;cntgetCoords()->begin()); - if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1) - return *candidatesIn2DBg; - int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1); - MCAuto cur1D(static_cast(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true))); - if(cellIdInMesh1DSplitRelative<0) - cur1D->changeOrientationOfCells(); - const int *c1D(cur1D->getNodalConnectivity()->begin()); - const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0])); - for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++) - { - MCAuto cur2D(static_cast(mesh2DSplit->buildPartOfMySelf(it,it+1,true))); - const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin()); - const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]])); - unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1)); - INTERP_KERNEL::AutoPtr tmpPtr(new int[ci[1]-ci[0]]); - for(unsigned it2=0;it2checkFullyDefined(); - mesh1D->checkFullyDefined(); - const std::vector& compNames(mesh2D->getCoords()->getInfoOnComponents()); - if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !"); - // Step 1: compute all edge intersections (new nodes) - std::vector< std::vector > intersectEdge1, colinear2, subDiv2; - std::vector addCoo,addCoordsQuadratic; // coordinates of newly created nodes - INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps; - INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps; - // - // Build desc connectivity - DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New()); - MCAuto dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1); - MCAuto m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1)); - std::map mergedNodes; - Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes); - // use mergeNodes to fix intersectEdge1 - for(std::vector< std::vector >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++) - { - std::size_t n((*it0).size()/2); - int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]); - std::map::const_iterator it1; - it1=mergedNodes.find(eltStart); - if(it1!=mergedNodes.end()) - (*it0)[0]=(*it1).second; - it1=mergedNodes.find(eltEnd); - if(it1!=mergedNodes.end()) - (*it0)[2*n-1]=(*it1).second; - } - // - MCAuto addCooDa(DataArrayDouble::New()); - addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2); - // Step 2: re-order newly created nodes according to the ordering found in m2 - std::vector< std::vector > intersectEdge2; - BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2); - subDiv2.clear(); - // Step 3: compute splitMesh1D - MCAuto idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear; - MCAuto ret2(DataArrayInt::New()); ret2->alloc(0,1); - MCAuto ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1, - idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear)); - MCAuto ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits::max()); ret3->rearrange(2); - MCAuto idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells())); - // deal with cells in mesh2D that are not cut but only some of their edges are - MCAuto idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCopy()); - idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1); - idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique(); - MCAuto out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells - if(!idsInDesc2DToBeRefined->empty()) - { - DataArrayInt *out0(0),*outi0(0); - MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0); - MCAuto outi0s(outi0); - out0s=out0; - out0s=out0s->buildUnique(); - out0s->sort(true); - } - // - MCAuto ret1NonCol(static_cast(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end()))); - MCAuto baryRet1(ret1NonCol->computeCellCenterOfMass()); - MCAuto elts,eltsIndex; - mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex); - MCAuto eltsIndex2(eltsIndex->deltaShiftIndex()); - MCAuto eltsIndex3(eltsIndex2->findIdsEqual(1)); - if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells()) - throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !"); - MCAuto cellsToBeModified(elts->buildUnique()); - MCAuto untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells())); - if((DataArrayInt *)out0s) - untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one - std::vector< MCAuto > outMesh2DSplit; - // OK all is ready to insert in ret2 mesh - if(!untouchedCells->empty()) - {// the most easy part, cells in mesh2D not impacted at all - outMesh2DSplit.push_back(static_cast(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end()))); - outMesh2DSplit.back()->setCoords(ret1->getCoords()); - ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end()); - } - if((DataArrayInt *)out0s) - {// here dealing with cells in out0s but not in cellsToBeModified - MCAuto fewModifiedCells(out0s->buildSubstraction(cellsToBeModified)); - const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin()); - for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++) - { - outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1)); - ret1->setCoords(outMesh2DSplit.back()->getCoords()); - } - int offset(ret2->getNumberOfTuples()); - ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end()); - MCAuto partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1); - partOfRet3->fillWithValue(std::numeric_limits::max()); partOfRet3->rearrange(2); - int kk(0),*ret3ptr(partOfRet3->getPointer()); - for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++) - { - int faceId(std::abs(*it)-1); - for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++) - { - int tmp(fewModifiedCells->findIdFirstEqual(*it2)); - if(tmp!=-1) - { - if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1]) - ret3ptr[2*kk]=tmp+offset; - if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1]) - ret3ptr[2*kk+1]=tmp+offset; - } - else - {//the current edge is shared by a 2D cell that will be split just after - if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1]) - ret3ptr[2*kk]=-(*it2+1); - if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1]) - ret3ptr[2*kk+1]=-(*it2+1); - } - } - } - m1Desc->setCoords(ret1->getCoords()); - ret1NonCol->setCoords(ret1->getCoords()); - ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true); - if(!outMesh2DSplit.empty()) - { - DataArrayDouble *da(outMesh2DSplit.back()->getCoords()); - for(std::vector< MCAuto >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++) - (*itt)->setCoords(da); - } - } - cellsToBeModified=cellsToBeModified->buildUniqueNotSorted(); - for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++) - { - MCAuto idsNonColPerCell(elts->findIdsEqual(*it)); - idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end()); - MCAuto idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end())); - MCAuto partOfMesh1CuttingCur2DCell(static_cast(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end()))); - MCAuto partOfRet3; - MCAuto splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3)); - ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true); - outMesh2DSplit.push_back(splitOfOneCell); - for(int i=0;igetNumberOfCells();i++) - ret2->pushBackSilent(*it); - } - // - std::size_t nbOfMeshes(outMesh2DSplit.size()); - std::vector tmp(nbOfMeshes); - for(std::size_t i=0;igetCoords()->setInfoOnComponents(compNames); - MCAuto ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp)); - // To finish - filter ret3 - std::numeric_limits::max() -> -1 - negate values must be resolved. - ret3->rearrange(1); - MCAuto edgesToDealWith(ret3->findIdsStricltyNegative()); - for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++) - { - int old2DCellId(-ret3->getIJ(*it,0)-1); - MCAuto candidates(ret2->findIdsEqual(old2DCellId)); - ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3 - } - ret3->changeValue(std::numeric_limits::max(),-1); - ret3->rearrange(2); - // - splitMesh1D=ret1.retn(); - splitMesh2D=ret2D.retn(); - cellIdInMesh2D=ret2.retn(); - cellIdInMesh1D=ret3.retn(); -} - -/** - * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the - * (newly created) nodes corresponding to the edge intersections. - * Output params: - * @param[out] cr, crI connectivity of the resulting mesh - * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2 - * TODO: describe input parameters - */ -void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1, - const std::vector >& intesctEdges1, const std::vector< std::vector >& colinear2, - const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector >& intesctEdges2, - const std::vector& addCoords, - std::vector& addCoordsQuadratic, std::vector& cr, std::vector& crI, std::vector& cNb1, std::vector& cNb2) -{ - static const int SPACEDIM=2; - const double *coo1(m1->getCoords()->getConstPointer()); - const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer()); - int offset1(m1->getNumberOfNodes()); - const double *coo2(m2->getCoords()->getConstPointer()); - const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer()); - int offset2(offset1+m2->getNumberOfNodes()); - int offset3(offset2+((int)addCoords.size())/2); - MCAuto bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree()); - const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin()); - // Here a BBTree on 2D-cells, not on segments: - BBTree myTree(bbox2,0,0,m2->getNumberOfCells(),eps); - int ncell1(m1->getNumberOfCells()); - crI.push_back(0); - for(int i=0;i candidates2; - myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2); - std::map mapp; - std::map mappRev; - INTERP_KERNEL::QuadraticPolygon pol1; - INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]]; - const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ); - // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects: - MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev); - // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes. - pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1, - desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1); - // - std::set edges1;// store all edges of pol1 that are NOT consumed by intersect cells. If any after iteration over candidates2 -> a part of pol1 should appear in result - std::set edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1. - INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1); - for(it1.first();!it1.finished();it1.next()) - edges1.insert(it1.current()->getPtr()); - // - std::map > edgesIn2ForShare; // common edges - std::vector pol2s(candidates2.size()); - int ii=0; - for(std::vector::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++) - { - INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]]; - const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2); - // Complete mapping with elements coming from the current cell it2 in mesh2: - MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev); - // pol2 is the new QP in the final merged result. - pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2, - pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare); - } - ii=0; - for(std::vector::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++) - { - INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]); - pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2); - //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2); - pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2); - } - // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched - // by m2 but that we still want to keep in the final result. - if(!edges1.empty()) - { - try - { - INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2); - } - catch(INTERP_KERNEL::Exception& e) - { - std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what(); - throw INTERP_KERNEL::Exception(oss.str()); - } - } - for(std::map::const_iterator it=mappRev.begin();it!=mappRev.end();it++) - (*it).second->decrRef(); - } -} - -/** - * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that - * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors). - * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here. - * The caller is to deal with the resulting DataArrayInt. - * \throw If the coordinate array is not set. - * \throw If the nodal connectivity of the cells is not defined. - * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1 - * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments) - * - * \sa DataArrayInt::sortEachPairToMakeALinkedList - */ -DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const -{ - checkFullyDefined(); - if(getMeshDimension()!=1) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !"); - - // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments: - MCAuto _d(DataArrayInt::New()),_dI(DataArrayInt::New()); - MCAuto _rD(DataArrayInt::New()),_rDI(DataArrayInt::New()); - MCAuto m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI)); - const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer()); - const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer()); - MCAuto _dsi(_rDI->deltaShiftIndex()); - const int * dsi(_dsi->getConstPointer()); - MCAuto dsii = _dsi->findIdsNotInRange(0,3); - m_points=0; - if (dsii->getNumberOfTuples()) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!"); - - int nc(getNumberOfCells()); - MCAuto result(DataArrayInt::New()); - result->alloc(nc,1); - - // set of edges not used so far - std::set edgeSet; - for (int i=0; i linePiece; - // fills a list of consecutive segment linked to startSeg. This can go forward or backward. - for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward - { - // Fill the list forward (resp. backward) from the start segment: - int activeSeg = startSeg; - int prevPointId = -20; - int ptId; - while (!edgeSet.empty()) - { - if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg - { - if (direction==0) - linePiece.push_back(activeSeg); - else - linePiece.push_front(activeSeg); - edgeSet.erase(activeSeg); - } - - int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1]; - ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2); - if (dsi[ptId] == 1) // hitting the end of the line - break; - prevPointId = ptId; - int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1]; - activeSeg = (seg1 == activeSeg) ? seg2 : seg1; - } - } - // Done, save final piece into DA: - std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx); - newIdx += linePiece.size(); - - // identify next valid start segment (one which is not consumed) - if(!edgeSet.empty()) - startSeg = *(edgeSet.begin()); - } - while (!edgeSet.empty()); - return result.retn(); -} - -/// @cond INTERNAL - -void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map,int>& m, int forbVal0, int forbVal1, std::vector& isect) -{ - MCAuto nTmp(n); nTmp->incrRef(); - std::map,int>::const_iterator it(m.find(nTmp)); - if(it==m.end()) - throw INTERP_KERNEL::Exception("Internal error in remapping !"); - int v((*it).second); - if(v==forbVal0 || v==forbVal1) - return ; - if(std::find(isect.begin(),isect.end(),v)==isect.end()) - isect.push_back(v); -} - -bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map,int>& m, int forbVal0, int forbVal1, std::vector& isect) -{ - int sz(c.size()); - if(sz<=1) - return false; - bool presenceOfOn(false); - for(int i=0;igetLoc()!=INTERP_KERNEL::FULL_ON_1) - continue ; - IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect); - IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect); - } - return presenceOfOn; -} - -/// @endcond - -/** - * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg - * and in \a subNodesInSegI using \ref numbering-indirect storage mode. - * To do the work this method can optionally needs information about middle of subedges for quadratic cases if - * a minimal creation of new nodes is wanted. - * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add - * nodes if a SEG3 is split without information of middle. - * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to - * avoid to have a non conform mesh. - * - * \return int - the number of new nodes created (in most of cases 0). - * - * \throw If \a this is not coherent. - * \throw If \a this has not spaceDim equal to 2. - * \throw If \a this has not meshDim equal to 2. - * \throw If some subcells needed to be split are orphan. - * \sa MEDCouplingUMesh::conformize2D - */ -int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI) -{ - if(!desc || !descI || !subNodesInSeg || !subNodesInSegI) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !"); - desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated(); - if(getSpaceDimension()!=2 || getMeshDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !"); - if(midOpt==0 && midOptI==0) - { - split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI); - return 0; - } - else if(midOpt!=0 && midOptI!=0) - return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI); - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all."); -} - -/*! - * \b WARNING this method is \b potentially \b non \b const (if returned array is empty). - * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) ! - * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method - * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2). - * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method. - * - * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells. - * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type. - * - * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too. - * This method expects that all nodes in \a this are not closer than \a eps. - * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method. - * - * \param [in] eps the relative error to detect merged edges. - * \return DataArrayInt * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array - * that the user is expected to deal with. - * - * \throw If \a this is not coherent. - * \throw If \a this has not spaceDim equal to 2. - * \throw If \a this has not meshDim equal to 2. - * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells - */ -DataArrayInt *MEDCouplingUMesh::conformize2D(double eps) -{ - static const int SPACEDIM=2; - checkConsistencyLight(); - if(getSpaceDimension()!=2 || getMeshDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !"); - MCAuto desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New()); - MCAuto mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1)); - const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer()); - MCAuto bboxArr(mDesc->getBoundingBoxForBBTree()); - const double *bbox(bboxArr->begin()),*coords(getCoords()->begin()); - int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells()); - std::vector< std::vector > intersectEdge(nDescCell),overlapEdge(nDescCell); - std::vector addCoo; - BBTree myTree(bbox,0,0,nDescCell,-eps); - INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps; - INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps; - for(int i=0;i candidates; - myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates); - for(std::vector::const_iterator it=candidates.begin();it!=candidates.end();it++) - if(*it>i) - { - std::map,int> m; - INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)), - *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m)); - INTERP_KERNEL::MergePoints merge; - INTERP_KERNEL::QuadraticPolygon c1,c2; - e1->intersectWith(e2,merge,c1,c2); - e1->decrRef(); e2->decrRef(); - if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i])) - overlapEdge[i].push_back(*it); - if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it])) - overlapEdge[*it].push_back(i); - } - } - // splitting done. sort intersect point in intersectEdge. - std::vector< std::vector > middle(nDescCell); - int nbOf2DCellsToBeSplit(0); - bool middleNeedsToBeUsed(false); - std::vector cells2DToTreat(nDescCell,false); - for(int i=0;i& isect(intersectEdge[i]); - int sz((int)isect.size()); - if(sz>1) - { - std::map,int> m; - INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)); - e->sortSubNodesAbs(coords,isect); - e->decrRef(); - } - if(sz!=0) - { - int idx0(rdi[i]),idx1(rdi[i+1]); - if(idx1-idx0!=1) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !"); - if(!cells2DToTreat[rd[idx0]]) - { - cells2DToTreat[rd[idx0]]=true; - nbOf2DCellsToBeSplit++; - } - // try to reuse at most eventual 'middle' of SEG3 - std::vector& mid(middle[i]); - mid.resize(sz+1,-1); - if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3) - { - middleNeedsToBeUsed=true; - const std::vector& candidates(overlapEdge[i]); - std::vector trueCandidates; - for(std::vector::const_iterator itc=candidates.begin();itc!=candidates.end();itc++) - if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3) - trueCandidates.push_back(*itc); - int stNode(c[ci[i]+1]),endNode(isect[0]); - for(int j=0;j::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++) - { - int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]); - if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode)) - { mid[j]=*itc; break; } - } - stNode=endNode; - endNode=j ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1); - if(nbOf2DCellsToBeSplit==0) - return ret.retn(); - // - int *retPtr(ret->getPointer()); - for(int i=0;i mSafe,nSafe,oSafe,pSafe,qSafe,rSafe; - DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0); - MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n; - DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p; - if(middleNeedsToBeUsed) - { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; } - MCAuto modif(static_cast(buildPartOfMySelf(ret->begin(),ret->end(),true))); - int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe)); - setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important. - setPartOfMySelf(ret->begin(),ret->end(),*modif); - { - bool areNodesMerged; int newNbOfNodes; - if(nbOfNodesCreated!=0) - MCAuto tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes)); - } - return ret.retn(); -} - -/*! - * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell. - * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision). - * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected - * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call. - * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells - * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes. - * - * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified - * using new instance, idem for coordinates. - * - * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this. - * - * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized. - * - * \throw If \a this is not coherent. - * \throw If \a this has not spaceDim equal to 2. - * \throw If \a this has not meshDim equal to 2. - * - * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D. - */ -DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps) -{ - MCAuto ret(DataArrayInt::New()); ret->alloc(0,1); - checkConsistencyLight(); - if(getSpaceDimension()!=2 || getMeshDimension()!=2) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !"); - INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps; - INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps; - int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes()); - const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin()); - MCAuto newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0); - MCAuto appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug. - const double *coords(_coords->begin()); - int *newciptr(newci->getPointer()); - for(int i=0;ipushBackSilent(i); - newciptr[1]=newc->getNumberOfTuples(); - } - // - if(ret->empty()) - return ret.retn(); - if(!appendedCoords->empty()) - { - appendedCoords->rearrange(2); - MCAuto newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components - //non const part - setCoords(newCoords); - } - //non const part - setConnectivity(newc,newci,true); - return ret.retn(); -} - -/*! - * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop. - * So for all edge \a i in \a m1Desc \a intersectEdge1[i] is of length 2*n where n is the number of sub edges. - * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j]. - * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo - * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it. - * \param [out] addCoo - nodes to be append at the end - * \param [out] mergedNodes - gives all pair of nodes of \a m2Desc that have same location than some nodes in \a m1Desc. key is id in \a m2Desc offseted and value is id in \a m1Desc. - */ -void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps, - std::vector< std::vector >& intersectEdge1, std::vector< std::vector >& colinear2, std::vector< std::vector >& subDiv2, std::vector& addCoo, std::map& mergedNodes) -{ - static const int SPACEDIM=2; - INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps; - INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps; - const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer()); - // Build BB tree of all edges in the tool mesh (second mesh) - MCAuto bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree()); - const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin()); - int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells()); - intersectEdge1.resize(nDescCell1); - colinear2.resize(nDescCell2); - subDiv2.resize(nDescCell2); - BBTree myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps); - - std::vector candidates1(1); - int offset1(m1Desc->getNumberOfNodes()); - int offset2(offset1+m2Desc->getNumberOfNodes()); - for(int i=0;i candidates2; // edges of mesh2 candidate for intersection - myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2); - if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1 - { - std::map map1,map2; - // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format - INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2); - candidates1[0]=i; - INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1); - // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one - // This trick guarantees that Node * are discriminant (i.e. form a unique identifier) - std::set nodes; - pol1->getAllNodes(nodes); pol2->getAllNodes(nodes); - std::size_t szz(nodes.size()); - std::vector< MCAuto > nodesSafe(szz); - std::set::const_iterator itt(nodes.begin()); - for(std::size_t iii=0;iiiincrRef(); nodesSafe[iii]=*itt; } - // end of protection - // Performs egde cutting: - pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes); - delete pol2; - delete pol1; - } - else - // Copy the edge (take only the two first points, ie discard quadratic point at this stage) - intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3); - } -} - -/*! - * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2). - * It builds the descending connectivity of the two meshes, and then using a binary tree - * it computes the edge intersections. This results in new points being created : they're stored in addCoo. - * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs(). - */ -void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, - std::vector< std::vector >& intersectEdge1, std::vector< std::vector >& colinear2, std::vector< std::vector >& subDiv2, - MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1, - std::vector& addCoo, - MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2) -{ - // Build desc connectivity - desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New(); - desc2=DataArrayInt::New(); - descIndx2=DataArrayInt::New(); - revDesc2=DataArrayInt::New(); - revDescIndx2=DataArrayInt::New(); - MCAuto dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1); - MCAuto dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2); - m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1); - m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2); - MCAuto dd9(m1Desc),dd10(m2Desc); - std::map notUsedMap; - Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap); - m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef(); - m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef(); -} - -/*! - * This method performs the 2nd step of Partition of 2D mesh. - * This method has 4 inputs : - * - a mesh 'm1' with meshDim==1 and a SpaceDim==2 - * - a mesh 'm2' with meshDim==1 and a SpaceDim==2 - * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted. - * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2' - * Nodes end up lying consecutively on a cutted edge. - * \param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. - * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1') - * \param m2 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. - * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes. - * \param[out] intersectEdge the same content as subDiv, but correclty oriented. - */ -void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, - const std::vector& addCoo, - const std::vector< std::vector >& subDiv, std::vector< std::vector >& intersectEdge) -{ - int offset1=m1->getNumberOfNodes(); - int ncell=m2->getNumberOfCells(); - const int *c=m2->getNodalConnectivity()->getConstPointer(); - const int *cI=m2->getNodalConnectivityIndex()->getConstPointer(); - const double *coo=m2->getCoords()->getConstPointer(); - const double *cooBis=m1->getCoords()->getConstPointer(); - int offset2=offset1+m2->getNumberOfNodes(); - intersectEdge.resize(ncell); - for(int i=0;i& divs=subDiv[i]; - int nnode=cI[1]-cI[0]-1; - std::map > mapp2; - std::map mapp22; - for(int j=0;j(nn,true); - mapp22[nn]=nnid+offset1; - } - INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1); - for(std::map >::const_iterator it=mapp2.begin();it!=mapp2.end();it++) - ((*it).second.first)->decrRef(); - std::vector addNodes(divs.size()); - std::map mapp3; - for(std::size_t j=0;jsortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]); - for(std::vector::const_iterator it=addNodes.begin();it!=addNodes.end();it++) - (*it)->decrRef(); - e->decrRef(); - } -} - -/*! - * This method is part of the Slice3D algorithm. It is the first step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method). - * This method allows to compute given the status of 3D curve cells and the descending connectivity 3DSurf->3DCurve to deduce the intersection of each 3D surf cells - * with a plane. The result will be put in 'cut3DSuf' out parameter. - * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially. - * \param [out] nodesOnPlane, returns all the nodes that are on the plane. - * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh. - * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh. - * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh. - * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh. - * \param [in] desc is the descending connectivity 3DSurf->3DCurve - * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve - * \param [out] cut3DSuf input/output param. - */ -void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector& cut3DCurve, std::vector& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf, - const int *nodal3DCurve, const int *nodalIndx3DCurve, - const int *desc, const int *descIndx, - std::vector< std::pair >& cut3DSurf) -{ - std::set nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end()); - int nbOf3DSurfCell=(int)cut3DSurf.size(); - for(int i=0;i res; - int offset=descIndx[i]; - int nbOfSeg=descIndx[i+1]-offset; - for(int j=0;j-1) - res.push_back(status); - else - { - res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]); - res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]); - } - } - } - switch(res.size()) - { - case 2: - { - cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1]; - break; - } - case 1: - case 0: - { - std::set s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]); - std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector >(res)); - if(res.size()==2) - { - cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1]; - } - else - { - cut3DSurf[i].first=-1; cut3DSurf[i].second=-1; - } - break; - } - default: - {// case when plane is on a multi colinear edge of a polyhedron - if((int)res.size()==2*nbOfSeg) - { - cut3DSurf[i].first=-2; cut3DSurf[i].second=i; - } - else - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !"); - } - } - } -} - -/*! - * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown. - * This method is part of the Slice3D algorithm. It is the second step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method). - * This method allows to compute given the result of 3D surf cells with plane and the descending connectivity 3D->3DSurf to deduce the intersection of each 3D cells - * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters. - * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve). - * \param desc is the descending connectivity 3D->3DSurf - * \param descIndx is the descending connectivity index 3D->3DSurf - */ -void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair >& cut3DSurf, - const int *desc, const int *descIndx, - DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const -{ - checkFullyDefined(); - if(getMeshDimension()!=3 || getSpaceDimension()!=3) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!"); - const int *nodal3D=_nodal_connec->getConstPointer(); - const int *nodalIndx3D=_nodal_connec_index->getConstPointer(); - int nbOfCells=getNumberOfCells(); - for(int i=0;i > m; - int offset=descIndx[i]; - int nbOfFaces=descIndx[i+1]-offset; - int start=-1; - int end=-1; - for(int j=0;j& p=cut3DSurf[desc[offset+j]]; - if(p.first!=-1 && p.second!=-1) - { - if(p.first!=-2) - { - start=p.first; end=p.second; - m[p.first].insert(p.second); - m[p.second].insert(p.first); - } - else - { - const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]); - int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1; - INTERP_KERNEL::AutoPtr tmp=new int[sz]; - INTERP_KERNEL::NormalizedCellType cmsId; - unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId); - start=tmp[0]; end=tmp[nbOfNodesSon-1]; - for(unsigned k=0;k conn(1,(int)INTERP_KERNEL::NORM_POLYGON); - int prev=end; - while(end!=start) - { - std::map >::const_iterator it=m.find(start); - const std::set& s=(*it).second; - std::set s2; s2.insert(prev); - std::set s3; - std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin())); - if(s3.size()==1) - { - int val=*s3.begin(); - conn.push_back(start); - prev=start; - start=val; - } - else - start=end; - } - conn.push_back(end); - if(conn.size()>3) - { - nodalRes->insertAtTheEnd(conn.begin(),conn.end()); - nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples()); - cellIds->pushBackSilent(i); - } - } -} - -/*! - * This method compute the convex hull of a single 2D cell. This method tries to conserve at maximum the given input connectivity. In particular, if the orientation of cell is not clockwise - * as in MED format norm. If definitely the result of Jarvis algorithm is not matchable with the input connectivity, the result will be copied into \b nodalConnecOut parameter and - * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON. - * This method excepts that \b coords parameter is expected to be in dimension 2. [ \b nodalConnBg , \b nodalConnEnd ) is the nodal connectivity of the input - * cell (geometric cell type included at the position 0). If the meshdimension of the input cell is not equal to 2 an INTERP_KERNEL::Exception will be thrown. - * - * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered. - */ -bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) -{ - std::size_t sz=std::distance(nodalConnBg,nodalConnEnd); - if(sz>=4) - { - const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg); - if(cm.getDimension()==2) - { - const int *node=nodalConnBg+1; - int startNode=*node++; + const mcIdType *node=nodalConnBg+1; + mcIdType startNode=*node++; double refX=coords[2*startNode]; for(;node!=nodalConnEnd;node++) { @@ -10847,14 +7779,14 @@ bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, co refX=coords[2*startNode]; } } - std::vector tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode); + std::vector tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode); refX=1e300; double tmp1; double tmp2[2]; double angle0=-M_PI/2; // - int nextNode=-1; - int prevNode=-1; + mcIdType nextNode=-1; + mcIdType prevNode=-1; double resRef; double angleNext=0.; while(nextNode!=startNode) @@ -10889,8 +7821,8 @@ bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, co tmpOut.push_back(nextNode); } } - std::vector tmp3(2*(sz-1)); - std::vector::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin()); + std::vector tmp3(2*(sz-1)); + std::vector::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin()); std::copy(nodalConnBg+1,nodalConnEnd,it); if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end()) { @@ -10904,7 +7836,7 @@ bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, co } else { - nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON); + nodalConnecOut->pushBackSilent(ToIdType(INTERP_KERNEL::NORM_POLYGON)); nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end()); return true; } @@ -10916,331 +7848,29 @@ bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, co throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !"); } -/*! - * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx. - * This method will not impact the size of inout parameter \b arrIndx but the size of \b arr will be modified in case of suppression. - * - * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included) - * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded) - * \param [in,out] arr array in which the remove operation will be done. - * \param [in,out] arrIndx array in the remove operation will modify - * \param [in] offsetForRemoval (by default 0) offset so that for each i in [0,arrIndx->getNumberOfTuples()-1) removal process will be performed in the following range [arr+arrIndx[i]+offsetForRemoval,arr+arr[i+1]) - * \return true if \b arr and \b arrIndx have been modified, false if not. - */ -bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) -{ - if(!arrIndx || !arr) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !"); - if(offsetForRemoval<0) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !"); - std::set s(idsToRemoveBg,idsToRemoveEnd); - int nbOfGrps=arrIndx->getNumberOfTuples()-1; - int *arrIPtr=arrIndx->getPointer(); - *arrIPtr++=0; - int previousArrI=0; - const int *arrPtr=arr->getConstPointer(); - std::vector arrOut;//no utility to switch to DataArrayInt because copy always needed - for(int i=0;ioffsetForRemoval) - { - for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++) - { - if(s.find(*work)==s.end()) - arrOut.push_back(*work); - } - } - previousArrI=*arrIPtr; - *arrIPtr=(int)arrOut.size(); - } - if(arr->getNumberOfTuples()==(int)arrOut.size()) - return false; - arr->alloc((int)arrOut.size(),1); - std::copy(arrOut.begin(),arrOut.end(),arr->getPointer()); - return true; -} - -/*! - * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn - * (\ref numbering-indirect). - * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ). - * The selection of extraction is done standardly in new2old format. - * This method returns indexed arrays (\ref numbering-indirect) 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::ExtractFromIndexedArraysSlice - */ -void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, - DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) -{ - if(!arrIn || !arrIndxIn) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !"); - arrIn->checkAllocated(); 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(); - MCAuto arro=DataArrayInt::New(); - MCAuto arrIo=DataArrayInt::New(); - arrIo->alloc((int)(sz+1),1); - const int *idsIt=idsOfSelectBg; - 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::ExtractFromIndexedArrays : 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()); - } - } - arro->alloc(lgth,1); - work=arro->getPointer(); - idsIt=idsOfSelectBg; - 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::ExtractFromIndexedArrays : 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()); - } - } - arrOut=arro.retn(); - arrIndexOut=arrIo.retn(); -} - -/*! - * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn - * (\ref numbering-indirect). - * 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 (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut). - * - * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included) - * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded) - * \param [in] idsOfSelectStep - * \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::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, - DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) -{ - if(!arrIn || !arrIndxIn) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !"); - arrIn->checkAllocated(); arrIndxIn->checkAllocated(); - if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !"); - int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : 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::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !"); - int maxSizeOfArr=arrIn->getNumberOfTuples(); - MCAuto arro=DataArrayInt::New(); - MCAuto arrIo=DataArrayInt::New(); - arrIo->alloc((int)(sz+1),1); - int idsIt=idsOfSelectStart; - int *work=arrIo->getPointer(); - *work++=0; - int lgth=0; - for(int i=0;i=0 && idsIt=work[-1]) - *work=lgth; - else - { - std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : 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()); - } - } - arro->alloc(lgth,1); - work=arro->getPointer(); - idsIt=idsOfSelectStart; - for(int 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::ExtractFromIndexedArraysSlice : 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()); - } - } - 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 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] srcArrIndex index array of \b srcArr - * \param [out] arrOut the resulting array - * \param [out] arrIndexOut the index array of the resulting array \b arrOut - * - * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx - */ -void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, - const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex, - DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) -{ - if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !"); - MCAuto arro=DataArrayInt::New(); - MCAuto arrIo=DataArrayInt::New(); - int nbOfTuples=arrIndxIn->getNumberOfTuples()-1; - std::vector v(nbOfTuples,true); - int offset=0; - const int *arrIndxInPtr=arrIndxIn->getConstPointer(); - const int *srcArrIndexPtr=srcArrIndex->getConstPointer(); - for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++) - { - if(*it>=0 && *itgetConstPointer(); - arrIo->alloc(nbOfTuples+1,1); - arro->alloc(arrIn->getNumberOfTuples()+offset,1); - const int *arrInPtr=arrIn->getConstPointer(); - const int *srcArrPtr=srcArr->getConstPointer(); - int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0; - int *arroPtr=arro->getPointer(); - for(int ii=0;iigetNumberOfTuples()-1; - const int *arrIndxInPtr=arrIndxIn->getConstPointer(); - const int *srcArrIndexPtr=srcArrIndex->getConstPointer(); - int *arrInOutPtr=arrInOut->getPointer(); - const int *srcArrPtr=srcArr->getConstPointer(); - for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++) - { - if(*it>=0 && *itgetNumberOfTuples()-1. - * + * * \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 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process. * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone */ -DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) +DataArrayIdType *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayIdType *arrIn, const DataArrayIdType *arrIndxIn) { - int seed=0,nbOfDepthPeelingPerformed=0; + mcIdType seed=0,nbOfDepthPeelingPerformed=0; return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed); } /*! * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn. * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method. - * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]]. + * This method start from id 0 that will be contained in output DataArrayIdType. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]]. * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step. * A negative value in \b arrIn means that it is ignored. * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1. @@ -11253,15 +7883,15 @@ DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *a * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process. * \sa MEDCouplingUMesh::partitionBySpreadZone */ -DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) +DataArrayIdType *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const mcIdType *seedBg, const mcIdType *seedEnd, const DataArrayIdType *arrIn, const DataArrayIdType *arrIndxIn, mcIdType nbOfDepthPeeling, mcIdType& nbOfDepthPeelingPerformed) { nbOfDepthPeelingPerformed=0; if(!arrIndxIn) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !"); - int nbOfTuples=arrIndxIn->getNumberOfTuples()-1; + mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1; if(nbOfTuples<=0) { - DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1); + DataArrayIdType *ret=DataArrayIdType::New(); ret->alloc(0,1); return ret; } // @@ -11269,160 +7899,7 @@ DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *se return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed); } -DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) -{ - nbOfDepthPeelingPerformed=0; - if(!seedBg || !seedEnd || !arrIn || !arrIndxIn) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !"); - int nbOfTuples=arrIndxIn->getNumberOfTuples()-1; - std::vector fetched2(nbOfTuples,false); - int i=0; - for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++) - { - if(*seedElt>=0 && *seedEltgetConstPointer(); - const int *arrIndxPtr=arrIndxIn->getConstPointer(); - int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits::max(); - std::vector idsToFetch1(seedBg,seedEnd); - std::vector idsToFetch2; - std::vector *idsToFetch=&idsToFetch1; - std::vector *idsToFetchOther=&idsToFetch2; - while(!idsToFetch->empty() && nbOfDepthPeelingPerformed::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++) - for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++) - if(!fetched[*it2]) - { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); } - std::swap(idsToFetch,idsToFetchOther); - idsToFetchOther->clear(); - nbOfDepthPeelingPerformed++; - } - int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true); - i=0; - MCAuto ret=DataArrayInt::New(); ret->alloc(lgth,1); - int *retPtr=ret->getPointer(); - for(std::vector::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++) - if(*it) - *retPtr++=i; - return ret.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 is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays. - * - * \param [in] start begin of set of ids of the input extraction (included) - * \param [in] end end of set of ids of the input extraction (excluded) - * \param [in] step step of the set of ids in range mode. - * \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] srcArrIndex index array of \b srcArr - * \param [out] arrOut the resulting array - * \param [out] arrIndexOut the index array of the resulting array \b arrOut - * - * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays - */ -void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, - const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex, - DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) -{ - if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !"); - MCAuto arro=DataArrayInt::New(); - MCAuto arrIo=DataArrayInt::New(); - int nbOfTuples=arrIndxIn->getNumberOfTuples()-1; - int offset=0; - const int *arrIndxInPtr=arrIndxIn->getConstPointer(); - const int *srcArrIndexPtr=srcArrIndex->getConstPointer(); - int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : "); - int it=start; - for(int i=0;i=0 && itgetConstPointer(); - arrIo->alloc(nbOfTuples+1,1); - arro->alloc(arrIn->getNumberOfTuples()+offset,1); - const int *arrInPtr=arrIn->getConstPointer(); - const int *srcArrPtr=srcArr->getConstPointer(); - int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0; - int *arroPtr=arro->getPointer(); - for(int ii=0;iigetNumberOfTuples()-1; - const int *arrIndxInPtr=arrIndxIn->getConstPointer(); - const int *srcArrIndexPtr=srcArrIndex->getConstPointer(); - int *arrInOutPtr=arrInOut->getPointer(); - const int *srcArrPtr=srcArr->getConstPointer(); - int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : "); - int it=start; - for(int i=0;i=0 && it partition=partitionBySpreadZone(); - std::vector< MCAuto > partitionAuto; partitionAuto.reserve(partition.size()); - std::copy(partition.begin(),partition.end(),std::back_insert_iterator > >(partitionAuto)); + std::vector partition=partitionBySpreadZone(); + std::vector< MCAuto > partitionAuto; partitionAuto.reserve(partition.size()); + std::copy(partition.begin(),partition.end(),std::back_insert_iterator > >(partitionAuto)); MCAuto ret=MEDCouplingUMesh::New(getName(),mdim); ret->setCoords(getCoords()); - ret->allocateCells((int)partition.size()); + ret->allocateCells(ToIdType(partition.size())); // - for(std::vector::const_iterator it=partition.begin();it!=partition.end();it++) + for(std::vector::const_iterator it=partition.begin();it!=partition.end();it++) { MCAuto tmp=static_cast(buildPartOfMySelf((*it)->begin(),(*it)->end(),true)); - MCAuto cell; + MCAuto cell; switch(mdim) { case 2: @@ -11463,7 +7940,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !"); } - ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1); + ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1); } // ret->finishInsertingCells(); @@ -11475,45 +7952,56 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const * This method only needs a well defined connectivity. Coordinates are not considered here. * This method returns a vector of \b newly allocated arrays that the caller has to deal with. */ -std::vector MEDCouplingUMesh::partitionBySpreadZone() const +std::vector MEDCouplingUMesh::partitionBySpreadZone() const { - int nbOfCellsCur=getNumberOfCells(); - std::vector ret; + DataArrayIdType *neigh=0,*neighI=0; + computeNeighborsOfCells(neigh,neighI); + MCAuto neighAuto(neigh),neighIAuto(neighI); + return PartitionBySpreadZone(neighAuto,neighIAuto); +} + +std::vector MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayIdType *arrIn, const DataArrayIdType *arrIndxIn) +{ + if(!arrIn || !arrIndxIn) + throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !"); + arrIn->checkAllocated(); arrIndxIn->checkAllocated(); + mcIdType nbOfTuples(arrIndxIn->getNumberOfTuples()); + if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1) + throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !"); + mcIdType nbOfCellsCur(nbOfTuples-1); + std::vector ret; if(nbOfCellsCur<=0) return ret; - DataArrayInt *neigh=0,*neighI=0; - computeNeighborsOfCells(neigh,neighI); - MCAuto neighAuto(neigh),neighIAuto(neighI); std::vector fetchedCells(nbOfCellsCur,false); - std::vector< MCAuto > ret2; - int seed=0; + std::vector< MCAuto > ret2; + mcIdType seed=0; while(seed >::iterator it=ret2.begin();it!=ret2.end();it++) + for(std::vector< MCAuto >::iterator it=ret2.begin();it!=ret2.end();it++) ret.push_back((*it).retn()); return ret; } /*! * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a - * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method. + * newly allocated DataArrayIdType instance with 2 components ready to be interpreted as input of DataArrayIdType::findRangeIdForEachTuple method. * * \param [in] code a code with the same format than those returned by MEDCouplingUMesh::getDistributionOfTypes except for the code[3*k+2] that should contain start id of chunck. - * \return a newly allocated DataArrayInt to be managed by the caller. + * \return a newly allocated DataArrayIdType to be managed by the caller. * \throw In case of \a code has not the right format (typically of size 3*n) */ -DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector& code) +DataArrayIdType *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector& code) { - MCAuto ret=DataArrayInt::New(); + MCAuto ret=DataArrayIdType::New(); std::size_t nb=code.size()/3; if(code.size()%3!=0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !"); - ret->alloc((int)nb,2); - int *retPtr=ret->getPointer(); + ret->alloc(nb,2); + mcIdType *retPtr=ret->getPointer(); for(std::size_t i=0;i 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints + * 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. See INTERP_KERNEL::SplittingPolicy for the images. - * \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, + * \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 DataArrayIdType 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. * - * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output + * \warning This method operates on each cells in this independently ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther. - * + * * \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::sortHexa8EachOther */ -MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const +MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayIdType *& n2oCells, mcIdType& nbOfAdditionalPoints) const { 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()); + mcIdType nbOfCells=getNumberOfCells(); + mcIdType nbNodes(getNumberOfNodes()); MCAuto ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4)); - MCAuto ret(DataArrayInt::New()); ret->alloc(nbOfCells,1); - int *retPt(ret->getPointer()); - MCAuto newConn(DataArrayInt::New()); newConn->alloc(0,1); + MCAuto ret(DataArrayIdType::New()); ret->alloc(nbOfCells,1); + mcIdType *retPt(ret->getPointer()); + MCAuto newConn(DataArrayIdType::New()); newConn->alloc(0,1); MCAuto addPts(DataArrayDouble::New()); addPts->alloc(0,1); - const int *oldc(_nodal_connec->begin()); - const int *oldci(_nodal_connec_index->begin()); + const mcIdType *oldc(_nodal_connec->begin()); + const mcIdType *oldci(_nodal_connec_index->begin()); const double *coords(_coords->begin()); - for(int i=0;i a; std::vector b; + std::vector 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]); + std::size_t nbOfTet(a.size()/4); *retPt=ToIdType(nbOfTet); + const mcIdType *aa(&a[0]); if(!b.empty()) { - for(std::vector::iterator it=a.begin();it!=a.end();it++) + 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; + nbNodes+=ToIdType(b.size()/3); } for(std::size_t j=0;jinsertAtTheEnd(aa,aa+4); @@ -11597,287 +8086,6 @@ MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& return ret0.retn(); } -/*! - * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch). - * - * \sa MEDCouplingUMesh::split2DCells - */ -void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI) -{ - checkConnectivityFullyDefined(); - int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+subNodesInSeg->getNumberOfTuples()); - MCAuto c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach); - const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin()); - int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer()); - int prevPosOfCi(ciPtr[0]); - for(int i=0;iend()!=cPtr) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !"); - _nodal_connec->decrRef(); - _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON); -} - -int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter) -{ - if(id!=-1) - return id; - else - { - int ret(nodesCnter++); - double newPt[2]; - e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt); - addCoo.insertAtTheEnd(newPt,newPt+2); - return ret; - } -} - -int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter) -{ - if(id!=-1) - return id; - else - { - int ret(nodesCnter++); - double newPt[2]; - e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt); - addCoo.insertAtTheEnd(newPt,newPt+2); - return ret; - } -} - - -/// @cond INTERNAL - -void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector& middles) -{ - int tmp[3]; - int trueStart(start>=0?start:nbOfEdges+start); - tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp]; - newConnOfCell->insertAtTheEnd(tmp,tmp+3); - if(linOrArc) - { - if(stp-start>1) - { - int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2); - InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2); - middles.push_back(tmp3+offset); - } - else - middles.push_back(connBg[trueStart+nbOfEdges]); - } -} - -void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector& middles) -{ - int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]); - newConnOfCell->pushBackSilent(tmpEnd); - if(linOrArc) - { - if(stp-start>1) - { - int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2); - InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2); - middles.push_back(tmp3+offset); - } - else - middles.push_back(connBg[start+nbOfEdges]); - } -} - -void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector& middles) -{ - // only the quadratic point to deal with: - if(linOrArc) - { - if(stp-start>1) - { - int tmpSrt(connBg[start]),tmpEnd(connBg[stp]); - int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2); - InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2); - middles.push_back(tmp3+offset); - } - else - middles.push_back(connBg[start+nbOfEdges]); - } -} - -/// @endcond - -/*! - * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) . - * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair). - */ -bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords) -{ - std::size_t sz(std::distance(connBg,connEnd)); - if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell. - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !"); - sz--; - INTERP_KERNEL::AutoPtr tmpConn(new int[sz]); - const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0])); - unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)); - unsigned nbOfHit(0); // number of fusions operated - int posBaseElt(0),posEndElt(0),nbOfTurn(0); - const unsigned int maxNbOfHit = cm.isQuadratic() ? nbs-2 : nbs-3; // a quad cell is authorized to end up with only two edges, a linear one has to keep 3 at least - INTERP_KERNEL::NormalizedCellType typeOfSon; - std::vector middles; - bool ret(false); - for(;(nbOfTurn+nbOfHit),int> m; - INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m)); - posEndElt = posBaseElt+1; - - // Look backward first: are the final edges of the cells colinear with the first ones? - // This initializes posBaseElt. - if(nbOfTurn==0) - { - for(unsigned i=1;iareColinears(); - if(isColinear) - { - nbOfHit++; - posBaseElt--; - ret=true; - } - delete eint; - eCand->decrRef(); - if(!isColinear) - break; - } - } - // Now move forward: - const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward - for(unsigned j=fwdStart+1;jareColinears()); - if(isColinear) - { - nbOfHit++; - posEndElt++; - ret=true; - } - delete eint; - eCand->decrRef(); - if(!isColinear) - break; - } - //push [posBaseElt,posEndElt) in newConnOfCell using e - // The if clauses below are (volontary) not mutually exclusive: on a quad cell with 2 edges, the end of the connectivity is also its begining! - if(nbOfTurn==0) - // at the begining of the connectivity (insert type) - EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles); - else if((nbOfHit+nbOfTurn) != (nbs-1)) - // in the middle - EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles); - if ((nbOfHit+nbOfTurn) == (nbs-1)) - // at the end (only quad points to deal with) - EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles); - posBaseElt=posEndElt; - e->decrRef(); - } - if(!middles.empty()) - newConnOfCell->insertAtTheEnd(middles.begin(),middles.end()); - return ret; -} - -/*! - * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object. - * - * \return int - the number of new nodes created. - * \sa MEDCouplingUMesh::split2DCells - */ -int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI) -{ - checkConsistencyLight(); - int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes()); - MCAuto c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach); - MCAuto addCoo(DataArrayDouble::New()); addCoo->alloc(0,1); - const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin()); - const int *midPtr(mid->begin()),*midIPtr(midI->begin()); - const double *oldCoordsPtr(getCoords()->begin()); - int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer()); - int prevPosOfCi(ciPtr[0]); - for(int i=0;i ns(3); - ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]); - ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]); - ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]); - MCAuto e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns)); - for(int k=0;kend()!=cPtr) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !"); - _nodal_connec->decrRef(); - _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG); - addCoo->rearrange(2); - MCAuto coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate - setCoords(coo); - return addCoo->getNumberOfTuples(); -} - -void MEDCouplingUMesh::ComputeAllTypesInternal(std::set& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex) -{ - if(nodalConnec && nodalConnecIndex) - { - types.clear(); - const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer()); - int nbOfElem(nodalConnecIndex->getNbOfElems()-1); - if(nbOfElem>0) - for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++) - types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]); - } -} - MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)), _own_cell(true),_cell_id(-1),_nb_cell(0) { @@ -11896,7 +8104,7 @@ MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator() delete _cell; } -MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc), +MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, mcIdType bg, mcIdType end):_mesh(mesh),_cell(itc), _own_cell(false),_cell_id(bg-1), _nb_cell(end) { @@ -11933,7 +8141,7 @@ MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry() _mesh->decrRef(); } -MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type), +MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, mcIdType bg, mcIdType end):_mesh(mesh),_type(type), _itc(itc), _bg(bg),_end(end) { @@ -11952,7 +8160,7 @@ INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const return _type; } -int MEDCouplingUMeshCellEntry::getNumberOfElems() const +mcIdType MEDCouplingUMeshCellEntry::getNumberOfElems() const { return _end-_bg; } @@ -11980,13 +8188,13 @@ MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator() MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt() { - const int *c=_mesh->getNodalConnectivity()->getConstPointer(); - const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer(); + const mcIdType *c=_mesh->getNodalConnectivity()->begin(); + const mcIdType *ci=_mesh->getNodalConnectivityIndex()->begin(); if(_cell_id<_nb_cell) { INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]]; - int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type))); - int startId=_cell_id; + mcIdType nbOfElems=ToIdType(std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)))); + mcIdType startId=_cell_id; _cell_id+=nbOfElems; return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id); } @@ -12019,7 +8227,7 @@ std::string MEDCouplingUMeshCell::repr() const { std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr(); oss << " : "; - std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator(oss," ")); + std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator(oss," ")); return oss.str(); } else @@ -12034,7 +8242,7 @@ INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const return INTERP_KERNEL::NORM_ERROR; } -const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const +const mcIdType *MEDCouplingUMeshCell::getAllConn(mcIdType& lgth) const { lgth=_conn_lgth; if(_conn_lgth!=NOTICABLE_FIRST_VAL)