-// Copyright (C) 2007-2012 CEA/DEN, EDF R&D
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
* permutation to remove duplicated nodes.
* \param [in] precision - minimal absolute distance between two nodes at which they are
* considered not coincident.
- * \param [in] limitNodeId - limit node id. Nodes with id strictly lower than \a
- * limitTupleId are \b not considered. Put -1 to this parameter to have
- * all nodes treated.
+ * \param [in] limitNodeId - limit node id. If all nodes within a group of coincident
+ * nodes have id strictly lower than \a limitTupleId then they are not
+ * returned. Put -1 to this parameter to have all nodes returned.
* \param [out] areNodesMerged - is set to \a true if any coincident nodes found.
* \param [out] newNbOfNodes - returns number of unique nodes.
* \return DataArrayInt * - the permutation array in "Old to New" mode. For more
DataArrayInt *comm,*commI;
findCommonNodes(precision,limitNodeId,comm,commI);
int oldNbOfNodes=getNumberOfNodes();
- DataArrayInt *ret=buildNewNumberingFromCommonNodesFormat(comm,commI,newNbOfNodes);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildNewNumberingFromCommonNodesFormat(comm,commI,newNbOfNodes);
areNodesMerged=(oldNbOfNodes!=newNbOfNodes);
comm->decrRef();
commI->decrRef();
- return ret;
+ return ret.retn();
}
/*!
* Finds nodes coincident within \a prec tolerance.
* Ids of coincident nodes are stored in output arrays.
* A pair of arrays (\a comm, \a commIndex) is called "Surjective Format 2".
- * \param [in] prec - minimal absolute distance between two nodes at which they are
+ * \param [in] prec - minimal absolute distance (using infinite norm) between two nodes at which they are
* considered not coincident.
- * \param [in] limitNodeId - limit node id. Nodes with id strictly lower than \a
- * limitTupleId are \b not considered. Put -1 to this parameter to have
- * all nodes treated.
+ * \param [in] limitNodeId - limit node id. If all nodes within a group of coincident
+ * nodes have id strictly lower than \a limitTupleId then they are not
+ * returned. Put -1 to this parameter to have all nodes treated.
* \param [out] comm - the array holding ids of coincident nodes.
* \a comm->getNumberOfComponents() == 1.
* \a comm->getNumberOfTuples() == \a commIndex->back(). The caller
* \param [in] pos - pointer to coordinates of the point. This array is expected to
* be of length \a this->getSpaceDimension() at least, else the
* behavior is not warranted.
- * \param [in] eps - the lowest distance between a point and a node at which the node is
+ * \param [in] eps - the lowest distance between a point and a node (using infinite norm) at which the node is
* not returned by this method.
* \return DataArrayInt * - a new instance of DataArrayInt holding ids of nodes
* close to the point. The caller is to delete this
* behavior is not warranted.
* \param [in] nbOfPoints - number of points whose coordinates are given by \a pos
* parameter.
- * \param [in] eps - the lowest distance between a point and a node at which the node is
+ * \param [in] eps - the lowest distance between (using infinite norm) a point and a node at which the node is
* not returned by this method.
* \param [out] c - array returning ids of nodes located closer than \a eps to the
* given points. The caller
return DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfNodes(),comm->begin(),commIndex->begin(),commIndex->end(),newNbOfNodes);
}
-/*
- * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
- * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
- * This value is asked because often known by the caller of this method.
- * @param newNodeNumbers array specifying the new numbering in old2New convention..
- * @param newNbOfNodes the new number of nodes.
+/*!
+ * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
+ * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
+ * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
+ * array is modified accordingly.
+ * \param [in] newNodeNumbers - a permutation array, of length \a
+ * this->getNumberOfNodes(), in "Old to New" mode.
+ * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
+ * \param [in] newNbOfNodes - number of nodes remaining after renumbering.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ *
+ * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
+ * \ref py_mcumesh_renumberNodes "Here is a Python example".
*/
void MEDCouplingPointSet::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
{
if(!_coords)
throw INTERP_KERNEL::Exception("MEDCouplingPointSet::renumberNodes : no coords specified !");
MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=_coords->renumberAndReduce(newNodeNumbers,newNbOfNodes);
- setCoords(newCoords);
+ renumberNodesInConn(newNodeNumbers);
+ setCoords(newCoords);//let it here not before renumberNodesInConn because old number of nodes is sometimes used...
}
-/*
- * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
- * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
- * This value is asked because often known by the caller of this method.
- * Contrary to ParaMEDMEM::MEDCouplingPointSet::renumberNodes method for merged nodes the barycenter of them is computed here.
+/*!
+ * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
+ * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
+ * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
+ * array is modified accordingly. In contrast to renumberNodes(), location
+ * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
+ * \param [in] newNodeNumbers - a permutation array, of length \a
+ * this->getNumberOfNodes(), in "Old to New" mode.
+ * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
+ * \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
+ * actually one more than the maximal id in \a newNodeNumbers.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
*
- * @param newNodeNumbers array specifying the new numbering.
- * @param newNbOfNodes the new number of nodes.
+ * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
+ * \ref py_mcumesh_renumberNodes "Here is a Python example".
*/
void MEDCouplingPointSet::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
{
ptToFill=std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)div[i]));
setCoords(newCoords);
newCoords->decrRef();
+ renumberNodesInConn(newNodeNumbers);
}
/*!
* This method recenter coordinates of nodes in \b this in order to be centered at the origin to benefit about the advantages of the precision to be around the box
* around origin of 'radius' 1.
*
+ * \warning this method is non const and alterates coordinates in \b this without modifying.
* \param [in] eps absolute epsilon. under that value of delta between max and min no scale is performed.
*
- * \warning this method is non const and alterates coordinates in \b this without modifying.
*/
void MEDCouplingPointSet::recenterForMaxPrecision(double eps) throw(INTERP_KERNEL::Exception)
{
std::vector<const DataArrayDouble *> coo(ms.size());
int spaceDim=(*it)->getSpaceDimension();
coo[0]=(*it++)->getCoords();
+ if(!coo[0]->isAllocated())
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : first element in coordinates is not allocated !");
for(int i=1;it!=ms.end();it++,i++)
{
const DataArrayDouble *tmp=(*it)->getCoords();
if(tmp)
{
- if((*it)->getSpaceDimension()==spaceDim)
- coo[i]=tmp;
+ if(tmp->isAllocated())
+ {
+ if((*it)->getSpaceDimension()==spaceDim)
+ coo[i]=tmp;
+ else
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : Mismatch in SpaceDim !");
+ }
else
- throw INTERP_KERNEL::Exception("Mismatch in SpaceDim during call of MergeNodesArray !");
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : Presence of a non allocated array !");
}
else
- throw INTERP_KERNEL::Exception("Empty coords detected during call of MergeNodesArray !");
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : Empty coords detected !");
}
return DataArrayDouble::Aggregate(coo);
}
*/
MEDCouplingMesh *MEDCouplingPointSet::buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const
{
- MEDCouplingPointSet *ret=buildPartOfMySelf(start,end,true);
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> ret=buildPartOfMySelf(start,end,true);
arr=ret->zipCoordsTraducer();
- return ret;
+ return ret.retn();
}
+/*!
+ * This method specialized the MEDCouplingMesh::buildPartRange
+ *
+ * \sa MEDCouplingUMesh::buildPartOfMySelf2
+ */
+MEDCouplingMesh *MEDCouplingPointSet::buildPartRange(int beginCellIds, int endCellIds, int stepCellIds) const throw(INTERP_KERNEL::Exception)
+{
+ return buildPartOfMySelf2(beginCellIds,endCellIds,stepCellIds,true);
+}
+
+/*!
+ * This method specialized the MEDCouplingMesh::buildPartRangeAndReduceNodes
+ *
+ * \param [out] beginOut valid only if \a arr not NULL !
+ * \param [out] endOut valid only if \a arr not NULL !
+ * \param [out] stepOut valid only if \a arr not NULL !
+ * \param [out] arr correspondance old to new in node ids.
+ *
+ * \sa MEDCouplingUMesh::buildPartOfMySelf2
+ */
+MEDCouplingMesh *MEDCouplingPointSet::buildPartRangeAndReduceNodes(int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt*& arr) const throw(INTERP_KERNEL::Exception)
+{
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> ret=buildPartOfMySelf2(beginCellIds,endCellIds,stepCellIds,true);
+ arr=ret->zipCoordsTraducer();
+ return ret.retn();
+}
/*!
* 'This' is expected to be of spaceDim==2. Idem for 'center' and 'vect'
delete pol;
return ret;
}
+
+/*!
+ * This method compares 2 cells coming from two unstructured meshes : \a this and \a other.
+ * This method compares 2 cells having the same id 'cellId' in \a this and \a other.
+ */
+bool MEDCouplingPointSet::areCellsFrom2MeshEqual(const MEDCouplingPointSet *other, int cellId, double prec) const
+{
+ if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
+ return false;
+ std::vector<int> c1,c2;
+ getNodeIdsOfCell(cellId,c1);
+ other->getNodeIdsOfCell(cellId,c2);
+ std::size_t sz=c1.size();
+ if(sz!=c2.size())
+ return false;
+ for(std::size_t i=0;i<sz;i++)
+ {
+ std::vector<double> n1,n2;
+ getCoordinatesOfNode(c1[0],n1);
+ other->getCoordinatesOfNode(c2[0],n2);
+ std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
+ std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
+ if(*std::max_element(n1.begin(),n1.end())>prec)
+ return false;
+ }
+ return true;
+}
+
+/*!
+ * Substitutes node coordinates array of \a this mesh with that of \a other mesh
+ * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
+ * meshes match with a specified precision, else an exception is thrown and \a this
+ * remains unchanged. In case of success the nodal connectivity of \a this mesh
+ * is permuted according to new order of nodes.
+ * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
+ * coordinates (and so more expensive) than simple equality.
+ * \param [in] other - the other mesh whose node coordinates array will be used by
+ * \a this mesh in case of their equality.
+ * \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
+ * \throw If the coordinates array of \a this is not set.
+ * \throw If the coordinates array of \a other is not set.
+ * \throw If the coordinates of \a this and \a other do not match.
+ */
+void MEDCouplingPointSet::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
+{
+ const DataArrayDouble *coords=other.getCoords();
+ if(!coords)
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute : No coords specified in other !");
+ if(!_coords)
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
+ int otherNbOfNodes=other.getNumberOfNodes();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
+ _coords->incrRef();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
+ setCoords(newCoords);
+ bool areNodesMerged;
+ int newNbOfNodes;
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
+ if(!areNodesMerged)
+ {
+ setCoords(oldCoords);
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
+ }
+ int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
+ const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
+ if(pt!=da->getConstPointer()+da->getNbOfElems())
+ {
+ setCoords(oldCoords);
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
+ }
+ setCoords(oldCoords);
+ renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
+ setCoords(coords);
+}
+
+MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
+{
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> ret=buildPartOfMySelfKeepCoords(begin,end);
+ if(!keepCoords)
+ ret->zipCoords();
+ return ret.retn();
+}
+
+MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
+{
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> ret=buildPartOfMySelfKeepCoords2(start,end,step);
+ if(!keepCoords)
+ ret->zipCoords();
+ return ret.retn();
+}
+
+/*!
+ Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
+ copy are selected basing on specified node ids and the value of \a fullyIn
+ parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the
+ array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
+ node is in the array of node ids. The created mesh shares the node coordinates array
+ with \a this mesh.
+ * \param [in] begin - the array of node ids.
+ * \param [in] end - a pointer to the (last+1)-th element of \a begin.
+ * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
+ * array \a begin are copied, else cells whose any node is in the
+ * array \a begin are copied.
+ * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
+ * to delete this mesh using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If any node id in \a begin is not valid.
+ *
+ * \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
+ * \ref py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
+ */
+MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
+{
+ DataArrayInt *cellIdsKept=0;
+ fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
+ return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
+}
+
+/*!
+ * Removes duplicates of cells from \a this mesh and returns an array mapping between
+ * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
+ * equal cells found.
+ * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
+ * to write this mesh to the MED file, its cells must be sorted using
+ * sortCellsInMEDFileFrmt().
+ * \param [in] compType - specifies a cell comparison technique. Meaning of its
+ * valid values [0,1,2] is as follows.
+ * - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
+ * connectivity and type. This is the strongest policy.
+ * - 1 : "permuted same orientation". Two cells are considered equal \c iff they
+ * are based on same nodes and have the same type and orientation.
+ * - 2 : "nodal". Two cells are considered equal \c iff they
+ * are based on same nodes and have the same type. This is the weakest
+ * policy, it can be used by users not sensitive to cell orientation.
+ * \param [in] startCellId - specifies the cell id at which search for equal cells
+ * starts. By default it is 0, which means that all cells in \a this will be
+ * scanned.
+ * \return DataArrayInt - a new instance of DataArrayInt, of length \a
+ * this->getNumberOfCells() before call of this method. The caller is to
+ * delete this array using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If the nodal connectivity includes an invalid id.
+ *
+ * \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
+ * \ref py_mcumesh_zipConnectivityTraducer "Here is a Python example".
+ */
+DataArrayInt *MEDCouplingPointSet::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
+{
+ DataArrayInt *commonCells=0,*commonCellsI=0;
+ findCommonCells(compType,startCellId,commonCells,commonCellsI);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
+ int newNbOfCells=-1;
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
+ commonCellsI->end(),newNbOfCells);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> self=buildPartOfMySelf(ret2->begin(),ret2->end(),true);
+ shallowCopyConnectivityFrom(self);
+ return ret.retn();
+}
+
+/*!
+ * Checks if \a this and \a other meshes are geometrically equivalent, else an
+ * exception is thrown. The meshes are
+ * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
+ * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
+ * the \a other mesh (with use of a specified cell comparison technique). The mapping
+ * from \a other to \a this for nodes and cells is returned via out parameters.
+ * \param [in] other - the mesh to compare with.
+ * \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
+ * each method in description of MEDCouplingPointSet::zipConnectivityTraducer().
+ * \param [in] prec - the precision used to compare nodes of the two meshes.
+ * \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
+ * to delete this array using decrRef() as it is no more needed.
+ * \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
+ * to delete this array using decrRef() as it is no more needed.
+ * \throw If the two meshes do not match.
+ *
+ * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
+ * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
+ */
+void MEDCouplingPointSet::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+ DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
+{
+ if(!other)
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalWith : input is null !");
+ const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
+ if(!otherC)
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalWith : other is not a PointSet mesh !");
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> m=dynamic_cast<MEDCouplingPointSet *>(mergeMyselfWith(otherC));
+ bool areNodesMerged;
+ int newNbOfNodes;
+ int oldNbOfNodes=getNumberOfNodes();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
+ //mergeNodes
+ if(!areNodesMerged)
+ throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
+ const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
+ if(pt!=da->getConstPointer()+da->getNbOfElems())
+ throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
+ m->renumberNodes(da->getConstPointer(),newNbOfNodes);
+ //
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
+ da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
+ //
+ da=m->zipConnectivityTraducer(cellCompPol);
+ int nbCells=getNumberOfCells();
+ int maxId=-1;
+ if(nbCells!=0)
+ maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells);
+ pt=std::find_if(da->getConstPointer()+nbCells,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
+ if(pt!=da->getConstPointer()+da->getNbOfElems())
+ throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(nbCells,da->getNbOfElems(),1);
+ nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
+ cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
+}
+
+/*!
+ * Checks if \a this and \a other meshes are geometrically equivalent, else an
+ * exception is thrown. The meshes are considered equivalent if (1) they share one
+ * node coordinates array and (2) they contain the same cells (with use of a specified
+ * cell comparison technique). The mapping from cells of the \a other to ones of \a this
+ * is returned via an out parameter.
+ * \param [in] other - the mesh to compare with.
+ * \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
+ * each method in description of MEDCouplingPointSet::zipConnectivityTraducer().
+ * \param [in] prec - a not used parameter.
+ * \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
+ * to delete this array using decrRef() as it is no more needed.
+ * \throw If the two meshes do not match.
+ *
+ * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
+ * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
+ */
+void MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+ DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
+{
+ if(!other)
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith : input is null !");
+ const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
+ if(!otherC)
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith : other is not a PointSet mesh !");
+ if(_coords!=otherC->_coords)
+ throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> m=mergeMyselfWithOnSameCoords(otherC);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
+ int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
+ const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
+ if(pt!=da->getConstPointer()+da->getNbOfElems())
+ {
+ throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
+ }
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
+ cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
+}
+
+void MEDCouplingPointSet::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
+{
+ MEDCouplingMesh::checkFastEquivalWith(other,prec);
+ //other not null checked by the line before
+ const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
+ if(!otherC)
+ throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkFastEquivalWith : fails because other is not a pointset mesh !");
+ int nbOfCells=getNumberOfCells();
+ if(nbOfCells<1)
+ return ;
+ bool status=true;
+ status&=areCellsFrom2MeshEqual(otherC,0,prec);
+ status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
+ status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
+ if(!status)
+ throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
+}
+
+/*!
+ * Finds cells whose all or some nodes are in a given array of node ids.
+ * \param [in] begin - the array of node ids.
+ * \param [in] end - a pointer to the (last+1)-th element of \a begin.
+ * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
+ * array \a begin are returned only, else cells whose any node is in the
+ * array \a begin are returned.
+ * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
+ * cells. The caller is to delete this array using decrRef() as it is no more
+ * needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If any cell id in \a begin is not valid.
+ *
+ * \sa MEDCouplingPointSet::getCellIdsFullyIncludedInNodeIds
+ *
+ * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
+ * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
+ */
+DataArrayInt *MEDCouplingPointSet::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
+{
+ DataArrayInt *cellIdsKept=0;
+ fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
+ cellIdsKept->setName(getName().c_str());
+ return cellIdsKept;
+}
+
+/*!
+ * Finds cells whose all nodes are in a given array of node ids.
+ * This method is a specialization of MEDCouplingPointSet::getCellIdsLyingOnNodes (true
+ * as last input argument).
+ * \param [in] partBg - the array of node ids.
+ * \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
+ * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
+ * cells. The caller is to delete this array using decrRef() as it is no
+ * more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If any cell id in \a partBg is not valid.
+ *
+ * \sa MEDCouplingPointSet::getCellIdsLyingOnNodes
+ *
+ * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
+ * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
+ */
+DataArrayInt *MEDCouplingPointSet::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
+{
+ return getCellIdsLyingOnNodes(partBg,partEnd,true);
+}
+
+/*!
+ * Removes unused nodes (the node coordinates array is shorten) and returns an array
+ * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
+ * array mean that the corresponding old node is no more used.
+ * \return DataArrayInt * - a new instance of DataArrayInt of length \a
+ * this->getNumberOfNodes() before call of this method. The caller is to
+ * delete this array using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If the nodal connectivity includes an invalid id.
+ *
+ * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
+ * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
+ */
+DataArrayInt *MEDCouplingPointSet::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
+{
+ int newNbOfNodes=-1;
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> traducer=getNodeIdsInUse(newNbOfNodes);
+ renumberNodes(traducer->getConstPointer(),newNbOfNodes);
+ return traducer.retn();
+}
+
+/*!
+ * Merges nodes equal within \a precision and returns an array describing the
+ * permutation used to remove duplicate nodes.
+ * \param [in] precision - minimal absolute distance between two nodes at which they are
+ * considered not coincident.
+ * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
+ * \param [out] newNbOfNodes - number of nodes remaining after the removal.
+ * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
+ * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
+ * is to delete this array using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ *
+ * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
+ * \ref py_mcumesh_mergeNodes "Here is a Python example".
+ */
+DataArrayInt *MEDCouplingPointSet::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
+{
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
+ if(areNodesMerged)
+ renumberNodes(ret->begin(),newNbOfNodes);
+ return ret.retn();
+}
+
+/*!
+ * Merges nodes equal within \a precision and returns an array describing the
+ * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
+ * of merged nodes is changed to be at their barycenter.
+ * \param [in] precision - minimal absolute distance between two nodes at which they are
+ * considered not coincident.
+ * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
+ * \param [out] newNbOfNodes - number of nodes remaining after the removal.
+ * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
+ * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
+ * is to delete this array using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ *
+ * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
+ * \ref py_mcumesh_mergeNodes "Here is a Python example".
+ */
+DataArrayInt *MEDCouplingPointSet::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
+{
+ DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
+ if(areNodesMerged)
+ renumberNodes2(ret->getConstPointer(),newNbOfNodes);
+ return ret;
+}