+
+/*!
+ * 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, mcIdType cellId, double prec) const
+{
+ if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
+ return false;
+ std::vector<mcIdType> 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(),[](double c){return fabs(c);});
+ 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)
+{
+ 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 !");
+ mcIdType otherNbOfNodes=other.getNumberOfNodes();
+ MCAuto<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
+ _coords->incrRef();
+ MCAuto<DataArrayDouble> oldCoords=_coords;
+ setCoords(newCoords);
+ bool areNodesMerged;
+ mcIdType newNbOfNodes;
+ MCAuto<DataArrayIdType> 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 !");
+ }
+ mcIdType maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
+ const mcIdType *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind(std::greater<mcIdType>(),std::placeholders::_1,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 mcIdType *begin, const mcIdType *end, bool keepCoords) const
+{
+ MCAuto<MEDCouplingPointSet> ret=buildPartOfMySelfKeepCoords(begin,end);
+ if(!keepCoords)
+ ret->zipCoords();
+ return ret.retn();
+}
+
+MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelfSlice(mcIdType start, mcIdType end, mcIdType step, bool keepCoords) const
+{
+ MCAuto<MEDCouplingPointSet> ret=buildPartOfMySelfKeepCoordsSlice(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.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
+ * \ref py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
+ * \endif
+ */
+MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelfNode(const mcIdType *begin, const mcIdType *end, bool fullyIn) const
+{
+ DataArrayIdType *cellIdsKept=0;
+ fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
+ MCAuto<DataArrayIdType> 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 DataArrayIdType - a new instance of DataArrayIdType, 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.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
+ * \ref py_mcumesh_zipConnectivityTraducer "Here is a Python example".
+ * \endif
+ */
+DataArrayIdType *MEDCouplingPointSet::zipConnectivityTraducer(int compType, mcIdType startCellId)
+{
+ DataArrayIdType *commonCells(nullptr),*commonCellsI(nullptr);
+ findCommonCells(compType,startCellId,commonCells,commonCellsI);
+ MCAuto<DataArrayIdType> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
+ mcIdType newNbOfCells=-1;
+ MCAuto<DataArrayIdType> ret=DataArrayIdType::ConvertIndexArrayToO2N(ToIdType(getNumberOfCells()),commonCells->begin(),commonCellsI->begin(),commonCellsI->end(),newNbOfCells);
+ MCAuto<DataArrayIdType> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
+ MCAuto<MEDCouplingPointSet> self=buildPartOfMySelf(ret2->begin(),ret2->end(),true);
+ shallowCopyConnectivityFrom(self);
+ return ret.retn();
+}
+
+/*!
+ * This const method states if the nodal connectivity of this fetches all nodes in \a this.
+ * In other words, this method looks is there are no orphan nodes in \a this.
+ * \sa zipCoordsTraducer, getNodeIdsInUse, computeFetchedNodeIds.
+ */
+bool MEDCouplingPointSet::areAllNodesFetched() const
+{
+ checkFullyDefined();
+ mcIdType nbNodes(getNumberOfNodes());
+ std::vector<bool> fetchedNodes(nbNodes,false);
+ computeNodeIdsAlg(fetchedNodes);
+ return std::find(fetchedNodes.begin(),fetchedNodes.end(),false)==fetchedNodes.end();
+}
+
+/*!
+ * 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.
+ *
+ * If \a cellCor is null (or Py_None) it means that for all #i cell in \a other is equal to cell # i in \a this.
+ *
+ * If \a nodeCor is null (or Py_None) it means that for all #i node in \a other is equal to node # i in \a this.
+ *
+ * So null (or Py_None) returned in \a cellCor and/or \a nodeCor means identity array. This is for optimization reason to avoid building
+ * useless arrays for some \a levOfCheck (for example 0).
+ *
+ * \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.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
+ * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
+ * \endif
+ */
+void MEDCouplingPointSet::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+ DataArrayIdType *&cellCor, DataArrayIdType *&nodeCor) const
+{
+ 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 !");
+ MCAuto<MEDCouplingPointSet> m=dynamic_cast<MEDCouplingPointSet *>(mergeMyselfWith(otherC));
+ bool areNodesMerged;
+ mcIdType newNbOfNodes;
+ mcIdType oldNbOfNodes=getNumberOfNodes();
+ MCAuto<DataArrayIdType> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
+ //mergeNodes
+ if(!areNodesMerged && oldNbOfNodes != 0)
+ throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
+ const mcIdType *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind(std::greater<mcIdType>(),std::placeholders::_1,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);
+ //
+ MCAuto<DataArrayIdType> nodeCor2=da->subArray(oldNbOfNodes);
+ da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
+ //
+ da=m->zipConnectivityTraducer(cellCompPol);
+ mcIdType nbCells=ToIdType(getNumberOfCells());
+ if (nbCells != ToIdType(other->getNumberOfCells()))
+ throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
+ mcIdType dan(da->getNumberOfTuples());
+ if (dan)
+ {
+ MCAuto<DataArrayIdType> da1(DataArrayIdType::New()),da2(DataArrayIdType::New());
+ da1->alloc(dan/2,1); da2->alloc(dan/2,1);
+ std::copy(da->getConstPointer(), da->getConstPointer()+dan/2, da1->getPointer());
+ std::copy(da->getConstPointer()+dan/2, da->getConstPointer()+dan, da2->getPointer());
+ da1->sort(); da2->sort();
+ if (!da1->isEqualWithoutConsideringStr(*da2))
+ throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
+ }
+ MCAuto<DataArrayIdType> cellCor2=da->selectByTupleIdSafeSlice(nbCells,ToIdType(da->getNbOfElems()),1);
+ nodeCor=nodeCor2->isIota(nodeCor2->getNumberOfTuples())?0:nodeCor2.retn();
+ cellCor=cellCor2->isIota(cellCor2->getNumberOfTuples())?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.
+ *
+ * If \a cellCor is null (or Py_None) it means that for all #i cell in \a other is equal to cell # i in \a this.
+ *
+ * \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.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
+ * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
+ * \endif
+ */
+void MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+ DataArrayIdType *&cellCor) const
+{
+ 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 !");
+ MCAuto<MEDCouplingPointSet> m=mergeMyselfWithOnSameCoords(otherC);
+ MCAuto<DataArrayIdType> da=m->zipConnectivityTraducer(cellCompPol);
+ mcIdType maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
+ const mcIdType *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind(std::greater<mcIdType>(),std::placeholders::_1,maxId));
+ if(pt!=da->getConstPointer()+da->getNbOfElems())
+ {
+ throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
+ }
+ MCAuto<DataArrayIdType> cellCor2=da->selectByTupleIdSafeSlice(ToIdType(getNumberOfCells()),ToIdType(da->getNbOfElems()),1);
+ cellCor=cellCor2->isIota(cellCor2->getNumberOfTuples())?0:cellCor2.retn();
+}
+
+void MEDCouplingPointSet::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
+{
+ 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 !");
+ mcIdType nbOfCells=ToIdType(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 DataArrayIdType * - a new instance of DataArrayIdType 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
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
+ * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
+ * \endif
+ */
+DataArrayIdType *MEDCouplingPointSet::getCellIdsLyingOnNodes(const mcIdType *begin, const mcIdType *end, bool fullyIn) const
+{
+ DataArrayIdType *cellIdsKept=0;
+ fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
+ cellIdsKept->setName(getName());
+ 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 DataArrayIdType * - a new instance of DataArrayIdType 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
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
+ * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
+ * \endif
+ */
+DataArrayIdType *MEDCouplingPointSet::getCellIdsFullyIncludedInNodeIds(const mcIdType *partBg, const mcIdType *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 DataArrayIdType * - a new instance of DataArrayIdType 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.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
+ * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
+ * \endif
+ */
+DataArrayIdType *MEDCouplingPointSet::zipCoordsTraducer()
+{
+ mcIdType newNbOfNodes=-1;
+ MCAuto<DataArrayIdType> 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 DataArrayIdType * - the permutation array in "Old to New" mode. For more
+ * info on "Old to New" mode see \ref numbering. 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.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
+ * \ref py_mcumesh_mergeNodes "Here is a Python example".
+ * \endif
+ */
+DataArrayIdType *MEDCouplingPointSet::mergeNodes(double precision, bool& areNodesMerged, mcIdType& newNbOfNodes)
+{
+ MCAuto<DataArrayIdType> 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 DataArrayIdType * - the permutation array in "Old to New" mode. For more
+ * info on "Old to New" mode see \ref numbering. 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.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
+ * \ref py_mcumesh_mergeNodes "Here is a Python example".
+ * \endif
+ */
+DataArrayIdType *MEDCouplingPointSet::mergeNodesCenter(double precision, bool& areNodesMerged, mcIdType& newNbOfNodes)
+{
+ DataArrayIdType *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
+ if(areNodesMerged)
+ renumberNodesCenter(ret->getConstPointer(),newNbOfNodes);
+ return ret;
+}