Salome HOME
Copyright update 2021
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingPointSet.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingPointSet.hxx"
22 #include "MCAuto.hxx"
23 #include "MEDCoupling1GTUMesh.hxx"
24 #include "MEDCouplingUMesh.hxx"
25 #include "MEDCouplingMemArray.hxx"
26 #include "PlanarIntersector.txx"
27 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
28 #include "InterpKernelGeo2DNode.hxx"
29 #include "DirectedBoundingBox.hxx"
30 #include "InterpKernelAutoPtr.hxx"
31
32 #include <cmath>
33 #include <limits>
34 #include <numeric>
35 #include <sstream>
36
37 using namespace MEDCoupling;
38
39 MEDCouplingPointSet::MEDCouplingPointSet():_coords(0)
40 {
41 }
42
43 MEDCouplingPointSet::MEDCouplingPointSet(const MEDCouplingPointSet& other, bool deepCpy):MEDCouplingMesh(other),_coords(0)
44 {
45   if(other._coords)
46     _coords=other._coords->performCopyOrIncrRef(deepCpy);
47 }
48
49 MEDCouplingPointSet::~MEDCouplingPointSet()
50 {
51   if(_coords)
52     _coords->decrRef();
53 }
54
55 mcIdType MEDCouplingPointSet::getNumberOfNodes() const
56 {
57   if(_coords)
58     return _coords->getNumberOfTuples();
59   else
60     throw INTERP_KERNEL::Exception("Unable to get number of nodes because no coordinates specified !");
61 }
62
63 int MEDCouplingPointSet::getSpaceDimension() const
64 {
65   if(_coords)
66     return (int)_coords->getNumberOfComponents();
67   else
68     throw INTERP_KERNEL::Exception("Unable to get space dimension because no coordinates specified !");
69 }
70
71 void MEDCouplingPointSet::updateTime() const
72 {
73   if(_coords)
74     {
75       updateTimeWith(*_coords);
76     }
77 }
78
79 std::size_t MEDCouplingPointSet::getHeapMemorySizeWithoutChildren() const
80 {
81   return MEDCouplingMesh::getHeapMemorySizeWithoutChildren();
82 }
83
84 std::vector<const BigMemoryObject *> MEDCouplingPointSet::getDirectChildrenWithNull() const
85 {
86   std::vector<const BigMemoryObject *> ret;
87   ret.push_back(_coords);
88   return ret;
89 }
90
91 void MEDCouplingPointSet::setCoords(const DataArrayDouble *coords)
92 {
93   if( coords != _coords )
94     {
95       if (_coords)
96         _coords->decrRef();
97       _coords=const_cast<DataArrayDouble *>(coords);
98       if(_coords)
99         _coords->incrRef();
100       declareAsNew();
101     }
102 }
103
104 /*!
105  * Returns a pointer to the array of point coordinates held by \a this.
106  *  \return DataArrayDouble * - the pointer to the array of point coordinates. The
107  *          caller is to delete this array using decrRef() as it is no more needed.
108  */
109 DataArrayDouble *MEDCouplingPointSet::getCoordinatesAndOwner() const
110 {
111   if(_coords)
112     _coords->incrRef();
113   return _coords;
114 }
115
116 /*!
117  * Copies string attributes from an \a other mesh. The copied strings are
118  * - mesh name
119  * - mesh description
120  * - time units
121  * - textual data of the coordinates array (name and components info)
122  *
123  *  \param [in] other - the mesh to copy string attributes from.
124  */
125 void MEDCouplingPointSet::copyTinyStringsFrom(const MEDCouplingMesh *other)
126 {
127   MEDCouplingMesh::copyTinyStringsFrom(other);
128   const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
129   if(!otherC)
130     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::copyTinyStringsFrom : meshes have not same type !");
131   if(_coords && otherC->_coords)
132     _coords->copyStringInfoFrom(*otherC->_coords);
133 }
134
135 bool MEDCouplingPointSet::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
136 {
137   if(!other)
138     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::isEqualIfNotWhy : null mesh instance in input !");
139   const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
140   if(!otherC)
141     {
142       reason="mesh given in input is not castable in MEDCouplingPointSet !";
143       return false;
144     }
145   if(!MEDCouplingMesh::isEqualIfNotWhy(other,prec,reason))
146     return false;
147   if(!areCoordsEqualIfNotWhy(*otherC,prec,reason))
148     return false;
149   return true;
150 }
151
152 /*!
153  * Checks equality of point coordinates with coordinates of an \a other mesh.
154  *        None textual data is considered.
155  *  \param [in] other - the mesh to compare coordinates with \a this one.
156  *  \param [in] prec - precision value to compare coordinates.
157  *  \return bool - \a true if coordinates of points are equal, \a false else.
158  */
159 bool MEDCouplingPointSet::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
160 {
161   const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
162   if(!otherC)
163     return false;
164   if(!areCoordsEqualWithoutConsideringStr(*otherC,prec))
165     return false;
166   return true;
167 }
168
169 bool MEDCouplingPointSet::areCoordsEqualIfNotWhy(const MEDCouplingPointSet& other, double prec, std::string& reason) const
170 {
171   if(_coords==0 && other._coords==0)
172     return true;
173   if(_coords==0 || other._coords==0)
174     {
175       reason="Only one PointSet between the two this and other has coordinate defined !";
176       return false;
177     }
178   if(_coords==other._coords)
179     return true;
180   bool ret=_coords->isEqualIfNotWhy(*other._coords,prec,reason);
181   if(!ret)
182     reason.insert(0,"Coordinates DataArray do not match : ");
183   return ret;
184 }
185
186 /*!
187  * Checks equality of point coordinates with \a other point coordinates.
188  *        Textual data (name and components info) \b is compared as well.
189  *  \param [in] other - the point coordinates to compare with \a this one.
190  *  \param [in] prec - precision value to compare coordinates.
191  *  \return bool - \a true if coordinates of points are equal, \a false else.
192  */
193 bool MEDCouplingPointSet::areCoordsEqual(const MEDCouplingPointSet& other, double prec) const
194 {
195   std::string tmp;
196   return areCoordsEqualIfNotWhy(other,prec,tmp);
197 }
198
199 /*!
200  * Checks equality of point coordinates with \a other point coordinates.
201  *        None textual data is considered.
202  *  \param [in] other - the point coordinates to compare with \a this one.
203  *  \param [in] prec - precision value to compare coordinates.
204  *  \return bool - \a true if coordinates of points are equal, \a false else.
205  */
206 bool MEDCouplingPointSet::areCoordsEqualWithoutConsideringStr(const MEDCouplingPointSet& other, double prec) const
207 {
208   if(_coords==0 && other._coords==0)
209     return true;
210   if(_coords==0 || other._coords==0)
211     return false;
212   if(_coords==other._coords)
213     return true;
214   return _coords->isEqualWithoutConsideringStr(*other._coords,prec);
215 }
216
217 /*!
218  * Returns coordinates of \a nodeId-th node.
219  *  \param [in] nodeId - the ID of the node of interest.
220  *  \param [in,out] coo - the array filled with coordinates of the \a nodeId-th
221  *         node. This array is not cleared before filling in, the coordinates are
222  *         appended to its end.
223  *  \throw If the coordinates array is not set.
224  *  \throw If \a nodeId is not a valid index for the coordinates array.
225  *
226  *  \if ENABLE_EXAMPLES
227  *  \ref cpp_mcpointset_getcoordinatesofnode "Here is a C++ example".<br>
228  *  \ref  py_mcpointset_getcoordinatesofnode "Here is a Python example".
229  *  \endif
230  */
231 void MEDCouplingPointSet::getCoordinatesOfNode(mcIdType nodeId, std::vector<double>& coo) const
232 {
233   if(!_coords)
234     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::getCoordinatesOfNode : no coordinates array set !");
235   mcIdType nbNodes=getNumberOfNodes();
236   if(nodeId>=0 && nodeId<nbNodes)
237     {
238       const double *cooPtr=_coords->getConstPointer();
239       std::size_t spaceDim=getSpaceDimension();
240       coo.insert(coo.end(),cooPtr+spaceDim*nodeId,cooPtr+spaceDim*(nodeId+1));
241     }
242   else
243     {
244       std::ostringstream oss; oss << "MEDCouplingPointSet::getCoordinatesOfNode : request of nodeId \"" << nodeId << "\" but it should be in [0,"<< nbNodes << ") !";
245       throw INTERP_KERNEL::Exception(oss.str().c_str());
246     }
247 }
248
249 /*!
250  * Finds nodes equal within \a precision and returns an array describing the 
251  * permutation to remove duplicated nodes.
252  *  \param [in] precision - minimal absolute distance between two nodes at which they are
253  *              considered not coincident.
254  *  \param [in] limitNodeId - limit node id. If all nodes within a group of coincident
255  *              nodes have id strictly lower than \a limitTupleId then they are not
256  *              returned. Put -1 to this parameter to have all nodes returned.
257  *  \param [out] areNodesMerged - is set to \a true if any coincident nodes found.
258  *  \param [out] newNbOfNodes - returns number of unique nodes.
259  *  \return DataArrayIdType * - the permutation array in "Old to New" mode. For more 
260  *          info on "Old to New" mode see \ref numbering. The caller
261  *          is to delete this array using decrRef() as it is no more needed.
262  *  \throw If the coordinates array is not set.
263  */
264 DataArrayIdType *MEDCouplingPointSet::buildPermArrayForMergeNode(double precision, mcIdType limitNodeId, bool& areNodesMerged, mcIdType& newNbOfNodes) const
265 {
266   DataArrayIdType *comm,*commI;
267   findCommonNodes(precision,limitNodeId,comm,commI);
268   mcIdType oldNbOfNodes=getNumberOfNodes();
269   MCAuto<DataArrayIdType> ret=buildNewNumberingFromCommonNodesFormat(comm,commI,newNbOfNodes);
270   areNodesMerged=(oldNbOfNodes!=newNbOfNodes);
271   comm->decrRef();
272   commI->decrRef();
273   return ret.retn();
274 }
275
276 /*!
277  * Finds nodes coincident within \a prec tolerance.
278  * Ids of coincident nodes are stored in output arrays in the \ref numbering-indirect format.
279  *  \param [in] prec - minimal absolute distance (using infinite norm) between two nodes at which they are
280  *              considered not coincident.
281  *  \param [in] limitNodeId - limit node id. If all nodes within a group of coincident
282  *              nodes have id strictly lower than \a limitTupleId then they are not
283  *              returned. Put -1 to this parameter to have all nodes treated.
284  *  \param [out] comm - the array holding ids of coincident nodes.
285  *               \a comm->getNumberOfComponents() == 1. 
286  *               \a comm->getNumberOfTuples() == \a commIndex->back(). The caller
287  *               is to delete this array using decrRef() as it is no more needed.
288  *  \param [out] commIndex - the array dividing all ids stored in \a comm into
289  *               groups of (ids of) coincident nodes (\ref numbering-indirect). Its every value is a tuple
290  *               index where a next group of nodes begins. For example the second
291  *               group of nodes in \a comm is described by following range of indices:
292  *               [ \a commIndex[1], \a commIndex[2] ). \a commIndex->getNumberOfTuples()-1
293  *               gives the number of groups of coincident nodes. The caller
294  *               is to delete this array using decrRef() as it is no more needed.
295  *  \throw If the coordinates array is not set.
296  *
297  *  \if ENABLE_EXAMPLES
298  *  \ref cpp_mcpointset_findcommonnodes "Here is a C++ example".<br>
299  *  \ref  py_mcpointset_findcommonnodes "Here is a Python example".
300  *  \endif
301  */
302 void MEDCouplingPointSet::findCommonNodes(double prec, mcIdType limitNodeId, DataArrayIdType *&comm, DataArrayIdType *&commIndex) const
303 {
304   if(!_coords)
305     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findCommonNodes : no coords specified !");
306   _coords->findCommonTuples(prec,limitNodeId,comm,commIndex);
307 }
308
309 /*!
310  * Finds nodes located at distances lower that \a eps from a given point.
311  *  \param [in] pos - pointer to coordinates of the point.  This array is expected to
312  *         be of length \a this->getSpaceDimension() at least, else the
313  *         behavior is not warranted.
314  *  \param [in] eps - the lowest distance between a point and a node (using infinite norm) at which the node is
315  *          not returned by this method.
316  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of nodes
317  *          close to the point. The caller is to delete this
318  *          array using decrRef() as it is no more needed.
319  *  \throw If the coordinates array is not set.
320  *
321  *  \if ENABLE_EXAMPLES
322  *  \ref cpp_mcpointset_getnodeidsnearpoint "Here is a C++ example".<br>
323  *  \ref  py_mcpointset_getnodeidsnearpoint "Here is a Python example".
324  *  \endif
325  */
326 DataArrayIdType *MEDCouplingPointSet::getNodeIdsNearPoint(const double *pos, double eps) const
327 {
328   DataArrayIdType *c=0,*cI=0;
329   getNodeIdsNearPoints(pos,1,eps,c,cI);
330   MCAuto<DataArrayIdType> cITmp(cI);
331   return c;
332 }
333
334 /*!
335  * Finds nodes located at distances lower that \a eps from given points.
336  *  \param [in] pos - pointer to coordinates of the points. This array is expected to
337  *         be of length \a nbOfPoints * \a this->getSpaceDimension() at least, else the
338  *         behavior is not warranted.
339  *  \param [in] nbOfPoints - number of points whose coordinates are given by \a pos
340  *         parameter. 
341  *  \param [in] eps - the lowest distance between (using infinite norm) a point and a node at which the node is
342  *         not returned by this method.
343  *  \param [out] c - array (\ref numbering-indirect) returning ids of nodes located closer than \a eps to the
344  *         given points. The caller
345  *         is to delete this array using decrRef() as it is no more needed.
346  *  \param [out] cI - for each i-th given point, the array specifies tuples of \a c
347  *         holding ids of nodes close to the i-th point (\ref numbering-indirect). <br>The i-th value of \a cI is an
348  *         index of tuple of \a c holding id of a first (if any) node close to the
349  *         i-th given point. Difference between the i-th and (i+1)-th value of \a cI
350  *         (i.e. \a cI[ i+1 ] - \a cI[ i ]) defines number of nodes close to the i-th
351  *         point (that can be zero!). For example, the group of nodes close to the
352  *         second point is described by following range of indices [ \a cI[1], \a cI[2] ).
353  *         The caller is to delete this array using decrRef() as it is no more needed.
354  *  \throw If the coordinates array is not set.
355  *
356  *  \if ENABLE_EXAMPLES
357  *  \ref cpp_mcpointset_getnodeidsnearpoints "Here is a C++ example".<br>
358  *  \ref  py_mcpointset_getnodeidsnearpoints "Here is a Python example".
359  *  \endif
360  */
361 void MEDCouplingPointSet::getNodeIdsNearPoints(const double *pos, mcIdType nbOfPoints, double eps, DataArrayIdType *& c, DataArrayIdType *& cI) const
362 {
363   if(!_coords)
364     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::getNodeIdsNearPoint : no coordiantes set !");
365   std::size_t spaceDim=getSpaceDimension();
366   MCAuto<DataArrayDouble> points=DataArrayDouble::New();
367   points->useArray(pos,false,DeallocType::CPP_DEALLOC,nbOfPoints,spaceDim);
368   _coords->computeTupleIdsNearTuples(points,eps,c,cI);
369 }
370
371 /*!
372  * @param comm in param in the same format than one returned by findCommonNodes method (\ref numbering-indirect).
373  * @param commIndex in param in the same format than one returned by findCommonNodes method (\ref numbering-indirect).
374  * @param newNbOfNodes new number of nodes
375  * @return the old to new correspondence array.
376  */
377 DataArrayIdType *MEDCouplingPointSet::buildNewNumberingFromCommonNodesFormat(const DataArrayIdType *comm, const DataArrayIdType *commIndex,
378                                                                           mcIdType& newNbOfNodes) const
379 {
380   if(!_coords)
381     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::buildNewNumberingFromCommonNodesFormat : no coords specified !");
382   return DataArrayIdType::ConvertIndexArrayToO2N(getNumberOfNodes(),comm->begin(),commIndex->begin(),commIndex->end(),newNbOfNodes);
383 }
384
385 /*!
386  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
387  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
388  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
389  * array is modified accordingly.
390  *  \param [in] newNodeNumbers - a permutation array, of length \a
391  *         this->getNumberOfNodes(), in "Old to New" mode. 
392  *         See \ref numbering for more info on renumbering modes.
393  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering.
394  *  \throw If the coordinates array is not set.
395  *  \throw If the nodal connectivity of cells is not defined.
396  *
397  *  \if ENABLE_EXAMPLES
398  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
399  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
400  *  \endif
401  */
402 void MEDCouplingPointSet::renumberNodes(const mcIdType *newNodeNumbers, mcIdType newNbOfNodes)
403 {
404   if(!_coords)
405     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::renumberNodes : no coords specified !");
406   MCAuto<DataArrayDouble> newCoords=_coords->renumberAndReduce(newNodeNumbers,newNbOfNodes);
407   renumberNodesInConn(newNodeNumbers);
408   setCoords(newCoords);//let it here not before renumberNodesInConn because old number of nodes is sometimes used...
409 }
410
411 /*!
412  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
413  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
414  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
415  * array is modified accordingly. In contrast to renumberNodes(), location
416  * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
417  *  \param [in] newNodeNumbers - a permutation array, of length \a
418  *         this->getNumberOfNodes(), in "Old to New" mode. 
419  *         See \ref numbering for more info on renumbering modes.
420  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
421  *         actually one more than the maximal id in \a newNodeNumbers.
422  *  \throw If the coordinates array is not set.
423  *  \throw If the nodal connectivity of cells is not defined.
424  *
425  *  \if ENABLE_EXAMPLES
426  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
427  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
428  *  \endif
429  */
430 void MEDCouplingPointSet::renumberNodesCenter(const mcIdType *newNodeNumbers, mcIdType newNbOfNodes)
431 {
432   DataArrayDouble *newCoords=DataArrayDouble::New();
433   std::vector<mcIdType> div(newNbOfNodes);
434   std::size_t spaceDim=getSpaceDimension();
435   newCoords->alloc(newNbOfNodes,spaceDim);
436   newCoords->copyStringInfoFrom(*_coords);
437   newCoords->fillWithZero();
438   mcIdType oldNbOfNodes=getNumberOfNodes();
439   double *ptToFill=newCoords->getPointer();
440   const double *oldCoordsPtr=_coords->getConstPointer();
441   for(mcIdType i=0;i<oldNbOfNodes;i++)
442     {
443       std::transform(oldCoordsPtr+i*spaceDim,oldCoordsPtr+(i+1)*spaceDim,ptToFill+newNodeNumbers[i]*spaceDim,
444                      ptToFill+newNodeNumbers[i]*spaceDim,std::plus<double>());
445       div[newNodeNumbers[i]]++;
446     }
447   for(mcIdType i=0;i<newNbOfNodes;i++)
448     ptToFill=std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind(std::multiplies<double>(),std::placeholders::_1,1./(double)div[i]));
449   setCoords(newCoords);
450   newCoords->decrRef();
451   renumberNodesInConn(newNodeNumbers);
452 }
453
454 /*!
455  * Computes the minimum box bounding all nodes. The edges of the box are parallel to
456  * the Cartesian coordinate axes. The bounding box is described by coordinates of its
457  * two extremum points with minimal and maximal coordinates.
458  *  \param [out] bbox - array filled with coordinates of extremum points in "no
459  *         interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin, zMax (if in 3D). This
460  *         array, of length 2 * \a this->getSpaceDimension() at least, is to be
461  *         pre-allocated by the caller.
462  *  \throw If the coordinates array is not set.
463  *
464  *  \if ENABLE_EXAMPLES
465  *  \ref cpp_mcpointset_getBoundingBox "Here is a C++ example".<br>
466  *  \ref  py_mcpointset_getBoundingBox "Here is a Python example".
467  *  \endif
468  */
469 void MEDCouplingPointSet::getBoundingBox(double *bbox) const
470 {
471   if(!_coords)
472     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::getBoundingBox : Coordinates not set !");
473   _coords->getMinMaxPerComponent(bbox);
474 }
475
476 /*!
477  * Removes "free" nodes, i.e. nodes not used to define any element.
478  *  \throw If the coordinates array is not set.
479  *  \throw If the elements are not defined.
480  */
481 void MEDCouplingPointSet::zipCoords()
482 {
483   checkFullyDefined();
484   DataArrayIdType *traducer=zipCoordsTraducer();
485   traducer->decrRef();
486 }
487
488 /*! \cond HIDDEN_ITEMS */
489 struct MEDCouplingCompAbs
490 {
491   bool operator()(double x, double y) { return std::abs(x)<std::abs(y);}
492 };
493 /*! \endcond */
494
495 /*!
496  * Returns the carateristic dimension of \a this point set, that is a maximal
497  * absolute values of node coordinates.
498  *  \throw If the coordinates array is not set.
499  */
500 double MEDCouplingPointSet::getCaracteristicDimension() const
501 {
502   if(!_coords)
503     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::getCaracteristicDimension : Coordinates not set !");
504   const double *coords=_coords->getConstPointer();
505   std::size_t nbOfValues=_coords->getNbOfElems();
506   return std::abs(*std::max_element(coords,coords+nbOfValues,MEDCouplingCompAbs()));
507 }
508
509 /*!
510  * 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
511  * around origin of 'radius' 1.
512  *
513  * \warning this method is non const and alterates coordinates in \b this without modifying.
514  * \param [in] eps absolute epsilon. under that value of delta between max and min no scale is performed.
515  *
516  */
517 void MEDCouplingPointSet::recenterForMaxPrecision(double eps)
518 {
519   if(!_coords)
520     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::recenterForMaxPrecision : Coordinates not set !");
521   _coords->recenterForMaxPrecision(eps);
522   updateTime();
523 }
524
525 /*!
526  * Rotates \a this set of nodes by \a angle around either an axis (in 3D) or a point
527  * (in 2D). 
528  *  \param [in] center - coordinates either of an origin of rotation axis (in 3D) or
529  *         of center of rotation (in 2D). This array is to be of size \a
530  *         this->getSpaceDimension() at least.
531  *  \param [in] vector - 3 components of a vector defining direction of the rotation
532  *         axis in 3D. In 2D this parameter is not used.
533  *  \param [in] angle - the rotation angle in radians.
534  *  \throw If the coordinates array is not set.
535  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
536  *  \throw If \a center == NULL
537  *  \throw If \a vector == NULL && \a this->getSpaceDimension() == 3.
538  *  \throw If Magnitude of \a vector is zero.
539  *
540  *  \if ENABLE_EXAMPLES
541  *  \ref cpp_mcpointset_rotate "Here is a C++ example".<br>
542  *  \ref  py_mcpointset_rotate "Here is a Python example".
543  *  \endif
544  */
545 void MEDCouplingPointSet::rotate(const double *center, const double *vector, double angle)
546 {
547   std::size_t spaceDim=getSpaceDimension();
548   if(spaceDim==3)
549     rotate3D(center,vector,angle);
550   else if(spaceDim==2)
551     rotate2D(center,angle);
552   else
553     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::rotate : invalid space dim for rotation must be 2 or 3");
554   _coords->declareAsNew();
555   updateTime();
556 }
557
558 /*!
559  * Translates \a this set of nodes. 
560  *  \param [in] vector - components of a translation vector. This array is to be of
561  *         size \a this->getSpaceDimension() at least. 
562  *  \throw If the coordinates array is not set.
563  *  \throw If \a vector == NULL.
564  *
565  *  \if ENABLE_EXAMPLES
566  *  \ref cpp_mcpointset_translate "Here is a C++ example".<br>
567  *  \ref  py_mcpointset_translate "Here is a Python example".
568  *  \endif
569  */
570 void MEDCouplingPointSet::translate(const double *vector)
571 {
572   if(!vector)
573     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::translate : NULL input vector !");
574   if(!_coords)
575     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::translate : no coordinates set !");
576   double *coords=_coords->getPointer();
577   mcIdType nbNodes=getNumberOfNodes();
578   std::size_t dim=getSpaceDimension();
579   for(mcIdType i=0; i<nbNodes; i++)
580     for(std::size_t idim=0; idim<dim;idim++)
581       coords[i*dim+idim]+=vector[idim];
582   _coords->declareAsNew();
583   updateTime();
584 }
585
586
587 /*!
588  * Applies scaling transformation to \a this set of nodes. 
589  *  \param [in] point - coordinates of a scaling center. This array is to be of
590  *         size \a this->getSpaceDimension() at least.
591  *  \param [in] factor - a scale factor.
592  *  \throw If the coordinates array is not set.
593  *  \throw If \a point == NULL.
594  *
595  *  \if ENABLE_EXAMPLES
596  *  \ref cpp_mcpointset_scale "Here is a C++ example".<br>
597  *  \ref  py_mcpointset_scale "Here is a Python example".
598  *  \endif
599  */
600 void MEDCouplingPointSet::scale(const double *point, double factor)
601 {
602   if(!point)
603     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::scale : NULL input point !");
604   if(!_coords)
605     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::scale : no coordinates set !");
606   double *coords=_coords->getPointer();
607   mcIdType nbNodes=getNumberOfNodes();
608   std::size_t dim=getSpaceDimension();
609   for(mcIdType i=0;i<nbNodes;i++)
610     {
611       std::transform(coords+i*dim,coords+(i+1)*dim,point,coords+i*dim,std::minus<double>());
612       std::transform(coords+i*dim,coords+(i+1)*dim,coords+i*dim,std::bind(std::multiplies<double>(),std::placeholders::_1,factor));
613       std::transform(coords+i*dim,coords+(i+1)*dim,point,coords+i*dim,std::plus<double>());
614     }
615   _coords->declareAsNew();
616   updateTime();
617 }
618
619 /*!
620  * Converts \a this set of points to an other dimension by changing number of
621  * components of point coordinates. If the dimension increases, added components
622  * are filled with \a dftValue. If the dimension decreases, last components are lost.
623  * If the new dimension is same as \a this->getSpaceDimension(), nothing is done.
624  *  \param [in] newSpaceDim - the new space dimension.
625  *  \param [in] dftValue - the value to assign to added components of point coordinates
626  *         (if the dimension increases).
627  *  \throw If the coordinates array is not set.
628  *  \throw If \a newSpaceDim < 1.
629  */
630 void MEDCouplingPointSet::changeSpaceDimension(int newSpaceDim, double dftValue)
631 {
632   if(getCoords()==0)
633     throw INTERP_KERNEL::Exception("changeSpaceDimension must be called on an MEDCouplingPointSet instance with coordinates set !");
634   if(newSpaceDim<1)
635     throw INTERP_KERNEL::Exception("changeSpaceDimension must be called a newSpaceDim >=1 !");
636   int oldSpaceDim=getSpaceDimension();
637   if(newSpaceDim==oldSpaceDim)
638     return ;
639   DataArrayDouble *newCoords=getCoords()->changeNbOfComponents(newSpaceDim,dftValue);
640   setCoords(newCoords);
641   newCoords->decrRef();
642   updateTime();
643 }
644
645 /*!
646  * Substitutes \a this->_coords with \a other._coords provided that coordinates of
647  * the two point sets match with a specified precision, else an exception is thrown.
648  *  \param [in] other - the other point set whose coordinates array will be used by
649  *         \a this point set in case of their equality.
650  *  \param [in] epsilon - the precision used to compare coordinates.
651  *  \throw If the coordinates array of \a this is not set.
652  *  \throw If the coordinates array of \a other is not set.
653  *  \throw If the coordinates of \a this and \a other do not match.
654  */
655 void MEDCouplingPointSet::tryToShareSameCoords(const MEDCouplingPointSet& other, double epsilon)
656 {
657   if(_coords==other._coords)
658     return ;
659   if(!_coords)
660     throw INTERP_KERNEL::Exception("Current instance has no coords whereas other has !");
661   if(!other._coords)
662     throw INTERP_KERNEL::Exception("Other instance has no coords whereas current has !");
663   if(!_coords->isEqualWithoutConsideringStr(*other._coords,epsilon))
664     throw INTERP_KERNEL::Exception("Coords are not the same !");
665   setCoords(other._coords);
666 }
667
668 /*!
669  * This method duplicates the nodes whose ids are in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) and put the result of their duplication at the end
670  * of existing node ids.
671  * 
672  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
673  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
674  */
675 void MEDCouplingPointSet::duplicateNodesInCoords(const mcIdType *nodeIdsToDuplicateBg, const mcIdType *nodeIdsToDuplicateEnd)
676 {
677   if(!_coords)
678     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::duplicateNodesInCoords : no coords set !");
679   MCAuto<DataArrayDouble> newCoords=_coords->selectByTupleIdSafe(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
680   MCAuto<DataArrayDouble> newCoords2=DataArrayDouble::Aggregate(_coords,newCoords);
681   setCoords(newCoords2);
682 }
683
684 /*!
685  * Finds nodes located at distance lower that \a eps from a specified plane.
686  *  \param [in] pt - 3 components of a point defining location of the plane.
687  *  \param [in] vec - 3 components of a normal vector to the plane. Vector magnitude
688  *         must be greater than 10*\a eps.
689  *  \param [in] eps - maximal distance of a node from the plane at which the node is
690  *         considered to lie on the plane.
691  *  \param [in,out] nodes - a vector returning ids of found nodes. This vector is not
692  *         cleared before filling in.
693  *  \throw If the coordinates array is not set.
694  *  \throw If \a pt == NULL.
695  *  \throw If \a vec == NULL.
696  *  \throw If the magnitude of \a vec is zero.
697  *  \throw If \a this->getSpaceDimension() != 3.
698  */
699 void MEDCouplingPointSet::findNodesOnPlane(const double *pt, const double *vec, double eps, std::vector<mcIdType>& nodes) const
700 {
701   if(getSpaceDimension()!=3)
702     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnPlane : Invalid spacedim to be applied on this ! Must be equal to 3 !");
703   if(!pt)
704     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnPlane : NULL point pointer specified !");
705   if(!vec)
706     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnPlane : NULL vector pointer specified !");
707   mcIdType nbOfNodes=getNumberOfNodes();
708   double a=vec[0],b=vec[1],c=vec[2],d=-pt[0]*vec[0]-pt[1]*vec[1]-pt[2]*vec[2];
709   double deno=sqrt(a*a+b*b+c*c);
710   if(deno<std::numeric_limits<double>::min())
711     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnPlane : vector pointer specified has norm equal to 0. !");
712   const double *work=_coords->getConstPointer();
713   for(mcIdType i=0;i<nbOfNodes;i++)
714     {
715       if(std::abs(a*work[0]+b*work[1]+c*work[2]+d)/deno<eps)
716         nodes.push_back(i);
717       work+=3;
718     }
719 }
720
721 /*!
722  * Finds nodes located at distance lower that \a eps from a specified line in 2D and 3D.
723  *  \param [in] pt - components of coordinates of an initial point of the line. This
724  *         array is to be of size \a this->getSpaceDimension() at least.
725  *  \param [in] vec - components of a vector defining the line direction. This array
726  *         is to be of size \a this->getSpaceDimension() at least. Vector magnitude 
727  *         must be greater than 10*\a eps.
728  *  \param [in] eps - maximal distance of a node from the line at which the node is
729  *         considered to lie on the line.
730  *  \param [in,out] nodes - a vector returning ids of found nodes. This vector is not
731  *         cleared before filling in.
732  *  \throw If the coordinates array is not set.
733  *  \throw If \a pt == NULL.
734  *  \throw If \a vec == NULL.
735  *  \throw If the magnitude of \a vec is zero.
736  *  \throw If ( \a this->getSpaceDimension() != 3 && \a this->getSpaceDimension() != 2 ).
737  */
738 void MEDCouplingPointSet::findNodesOnLine(const double *pt, const double *vec, double eps, std::vector<mcIdType>& nodes) const
739 {
740   std::size_t spaceDim=getSpaceDimension();
741   if(spaceDim!=2 && spaceDim!=3)
742     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnLine : Invalid spacedim to be applied on this ! Must be equal to 2 or 3 !");
743   if(!pt)
744     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnLine : NULL point pointer specified !");
745   if(!vec)
746     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnLine : NULL vector pointer specified !");
747   mcIdType nbOfNodes=getNumberOfNodes();
748   double den=0.;
749   for(std::size_t i=0;i<spaceDim;i++)
750     den+=vec[i]*vec[i];
751   double deno=sqrt(den);
752   if(deno<10.*eps)
753     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::findNodesOnLine : Invalid given direction vector ! Norm is too small !");
754   INTERP_KERNEL::AutoPtr<double> vecn=new double[spaceDim];
755   for(std::size_t i=0;i<spaceDim;i++)
756     vecn[i]=vec[i]/deno;
757   const double *work=_coords->getConstPointer();
758   if(spaceDim==2)
759     {
760       for(mcIdType i=0;i<nbOfNodes;i++)
761         {
762           if(std::abs(vecn[0]*(work[1]-pt[1])-vecn[1]*(work[0]-pt[0]))<eps)
763             nodes.push_back(i);
764           work+=2;
765         }
766     }
767   else
768     {
769       for(mcIdType i=0;i<nbOfNodes;i++)
770         {
771           double a=vecn[0]*(work[1]-pt[1])-vecn[1]*(work[0]-pt[0]);
772           double b=vecn[1]*(work[2]-pt[2])-vecn[2]*(work[1]-pt[1]);
773           double c=vecn[2]*(work[0]-pt[0])-vecn[0]*(work[2]-pt[2]);
774           if(std::sqrt(a*a+b*b+c*c)<eps)
775             nodes.push_back(i);
776           work+=3;
777         }
778     }
779 }
780
781 /*!
782  * Returns a new array of node coordinates by concatenating node coordinates of two
783  * given point sets, so that (1) the number of nodes in the result array is a sum of the
784  * number of nodes of given point sets and (2) the number of component in the result array
785  * is same as that of each of given point sets. Info on components is copied from the first
786  * of the given point set. Space dimension of the given point sets must be the same. 
787  *  \param [in] m1 - a point set whose coordinates will be included in the result array.
788  *  \param [in] m2 - another point set whose coordinates will be included in the
789  *         result array. 
790  *  \return DataArrayDouble * - the new instance of DataArrayDouble.
791  *          The caller is to delete this result array using decrRef() as it is no more
792  *          needed.
793  *  \throw If both \a m1 and \a m2 are NULL.
794  *  \throw If \a m1->getSpaceDimension() != \a m2->getSpaceDimension().
795  */
796 DataArrayDouble *MEDCouplingPointSet::MergeNodesArray(const MEDCouplingPointSet *m1, const MEDCouplingPointSet *m2)
797 {
798   int spaceDim=m1->getSpaceDimension();
799   if(spaceDim!=m2->getSpaceDimension())
800     throw INTERP_KERNEL::Exception("Mismatch in SpaceDim during call of MergeNodesArray !");
801   return DataArrayDouble::Aggregate(m1->getCoords(),m2->getCoords());
802 }
803
804 DataArrayDouble *MEDCouplingPointSet::MergeNodesArray(const std::vector<const MEDCouplingPointSet *>& ms)
805 {
806   if(ms.empty())
807     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : input array must be NON EMPTY !");
808   std::vector<const MEDCouplingPointSet *>::const_iterator it=ms.begin();
809   std::vector<const DataArrayDouble *> coo(ms.size());
810   int spaceDim=(*it)->getSpaceDimension();
811   coo[0]=(*it++)->getCoords();
812   if(!coo[0]->isAllocated())
813     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : first element in coordinates is not allocated !");
814   for(int i=1;it!=ms.end();it++,i++)
815     {
816       const DataArrayDouble *tmp=(*it)->getCoords();
817       if(tmp)
818         {
819           if(tmp->isAllocated())
820             {
821               if((*it)->getSpaceDimension()==spaceDim)
822                 coo[i]=tmp;
823               else
824                 throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : Mismatch in SpaceDim !");
825             }
826           else
827             throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : Presence of a non allocated array !");
828         }
829       else
830         throw INTERP_KERNEL::Exception("MEDCouplingPointSet::MergeNodesArray : Empty coords detected !");
831     }
832   return DataArrayDouble::Aggregate(coo);
833 }
834
835 /*!
836  * Factory to build new instance of instanciable subclasses of MEDCouplingPointSet.
837  * This method is used during unserialization process.
838  */
839 MEDCouplingPointSet *MEDCouplingPointSet::BuildInstanceFromMeshType(MEDCouplingMeshType type)
840 {
841   switch(type)
842     {
843     case UNSTRUCTURED:
844       return MEDCouplingUMesh::New();
845     case SINGLE_STATIC_GEO_TYPE_UNSTRUCTURED:
846       return MEDCoupling1SGTUMesh::New();
847     case SINGLE_DYNAMIC_GEO_TYPE_UNSTRUCTURED:
848       return MEDCoupling1DGTUMesh::New();
849     default:
850       throw INTERP_KERNEL::Exception("Invalid type of mesh specified");
851     }
852 }
853
854 /*!
855  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
856  */
857 void MEDCouplingPointSet::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<mcIdType>& tinyInfo, std::vector<std::string>& littleStrings) const
858 {
859   int it,order;
860   double time=getTime(it,order);
861   if(_coords)
862     {
863       int spaceDim=getSpaceDimension();
864       littleStrings.resize(spaceDim+4);
865       littleStrings[0]=getName();
866       littleStrings[1]=getDescription();
867       littleStrings[2]=_coords->getName();
868       littleStrings[3]=getTimeUnit();
869       for(int i=0;i<spaceDim;i++)
870         littleStrings[i+4]=getCoords()->getInfoOnComponent(i);
871       tinyInfo.clear();
872       tinyInfo.push_back(getType());
873       tinyInfo.push_back(spaceDim);
874       tinyInfo.push_back(getNumberOfNodes());
875       tinyInfo.push_back(it);
876       tinyInfo.push_back(order);
877       tinyInfoD.push_back(time);
878     }
879   else
880     {
881       littleStrings.resize(3);
882       littleStrings[0]=getName();
883       littleStrings[1]=getDescription();
884       littleStrings[2]=getTimeUnit();
885       tinyInfo.clear();
886       tinyInfo.push_back(getType());
887       tinyInfo.push_back(-1);
888       tinyInfo.push_back(-1);
889       tinyInfo.push_back(it);
890       tinyInfo.push_back(order);
891       tinyInfoD.push_back(time);
892     }
893 }
894
895 /*!
896  * Third and final step of serialization process.
897  */
898 void MEDCouplingPointSet::serialize(DataArrayIdType *&a1, DataArrayDouble *&a2) const
899 {
900   if(_coords)
901     {
902       a2=const_cast<DataArrayDouble *>(getCoords());
903       a2->incrRef();
904     }
905   else
906     a2=0;
907 }
908
909 /*!
910  * Second step of serialization process.
911  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
912  */
913 void MEDCouplingPointSet::resizeForUnserialization(const std::vector<mcIdType>& tinyInfo, DataArrayIdType *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
914 {
915   if(tinyInfo[2]>=0 && tinyInfo[1]>=1)
916     {
917       a2->alloc(tinyInfo[2],tinyInfo[1]);
918       littleStrings.resize(tinyInfo[1]+4);
919     }
920   else
921     {
922       littleStrings.resize(3);
923     }
924 }
925
926 /*!
927  * Second and final unserialization process.
928  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
929  */
930 void MEDCouplingPointSet::unserialization(const std::vector<double>& tinyInfoD, const std::vector<mcIdType>& tinyInfo, const DataArrayIdType *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
931 {
932   if(tinyInfo[2]>=0 && tinyInfo[1]>=1)
933     {
934       setCoords(a2);
935       setName(littleStrings[0]);
936       setDescription(littleStrings[1]);
937       a2->setName(littleStrings[2]);
938       setTimeUnit(littleStrings[3]);
939       for(mcIdType i=0;i<tinyInfo[1];i++)
940         getCoords()->setInfoOnComponent(i,littleStrings[i+4]);
941       setTime(tinyInfoD[0],FromIdType<int>(tinyInfo[3]),FromIdType<int>(tinyInfo[4]));
942     }
943   else
944     {
945       setName(littleStrings[0]);
946       setDescription(littleStrings[1]);
947       setTimeUnit(littleStrings[2]);
948       setTime(tinyInfoD[0],FromIdType<int>(tinyInfo[3]),FromIdType<int>(tinyInfo[4]));
949     }
950 }
951
952 void MEDCouplingPointSet::checkConsistencyLight() const
953 {
954   if(!_coords)
955     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkConsistencyLight : no coordinates set !");
956 }
957
958 /*!
959  * Intersect Bounding Box given 2 Bounding Boxes.
960  */
961 bool MEDCouplingPointSet::intersectsBoundingBox(const double* bb1, const double* bb2, int dim, double eps)
962 {
963   double* bbtemp = new double[2*dim];
964   double deltamax=0.0;
965
966   for (int i=0; i< dim; i++)
967     {
968       double delta = bb1[2*i+1]-bb1[2*i];
969       if ( delta > deltamax )
970         {
971           deltamax = delta ;
972         }
973     }
974   for (int i=0; i<dim; i++)
975     {
976       bbtemp[i*2]=bb1[i*2]-deltamax*eps;
977       bbtemp[i*2+1]=bb1[i*2+1]+deltamax*eps;
978     }
979   
980   for (int idim=0; idim < dim; idim++)
981     {
982       bool intersects = (bbtemp[idim*2]<bb2[idim*2+1])
983         && (bb2[idim*2]<bbtemp[idim*2+1]) ;
984       if (!intersects)
985         {
986           delete [] bbtemp;
987           return false; 
988         }
989     }
990   delete [] bbtemp;
991   return true;
992 }
993
994 /*!
995  * Intersect 2 given Bounding Boxes.
996  */
997 bool MEDCouplingPointSet::intersectsBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bb1, const double* bb2, int dim, double eps)
998 {
999   double* bbtemp(new double[2*dim]);
1000   double deltamax(0.0);
1001
1002   for (int i=0; i< dim; i++)
1003     {
1004       double delta = bb2[2*i+1]-bb2[2*i];
1005       if ( delta > deltamax )
1006         {
1007           deltamax = delta ;
1008         }
1009     }
1010   for (int i=0; i<dim; i++)
1011     {
1012       bbtemp[i*2]=bb2[i*2]-deltamax*eps;
1013       bbtemp[i*2+1]=bb2[i*2+1]+deltamax*eps;
1014     }
1015   
1016   bool intersects(!bb1.isDisjointWith(bbtemp));
1017   delete [] bbtemp;
1018   return intersects;
1019 }
1020
1021 /*!
1022  * 'This' is expected to be of spaceDim==3. Idem for 'center' and 'vect'
1023  */
1024 void MEDCouplingPointSet::rotate3D(const double *center, const double *vect, double angle)
1025 {
1026   double *coords(_coords->getPointer());
1027   mcIdType nbNodes(getNumberOfNodes());
1028   DataArrayDouble::Rotate3DAlg(center,vect,angle,nbNodes,coords,coords);
1029 }
1030
1031 /*!
1032  * This method allows to give for each cell in \a trgMesh, how much it interacts with cells of \a srcMesh.
1033  * The returned array can be seen as a weighted array on the target cells of \a trgMesh input parameter.
1034  *
1035  * \param [in] srcMesh - source mesh
1036  * \param [in] trgMesh - target mesh
1037  * \param [in] eps - precision of the detection
1038  * \return DataArrayIdType * - An array that gives for each cell of \a trgMesh, how many cells in \a srcMesh (regarding the precision of detection \a eps) can interacts.
1039  * 
1040  * \throw If \a srcMesh and \a trgMesh have not the same space dimension.
1041  */
1042 DataArrayIdType *MEDCouplingPointSet::ComputeNbOfInteractionsWithSrcCells(const MEDCouplingPointSet *srcMesh, const MEDCouplingPointSet *trgMesh, double eps)
1043 {
1044   if(!srcMesh || !trgMesh)
1045     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::ComputeNbOfInteractionsWithSrcCells : the input meshes must be not NULL !");
1046   MCAuto<DataArrayDouble> sbbox(srcMesh->getBoundingBoxForBBTree(eps)),tbbox(trgMesh->getBoundingBoxForBBTree(eps));
1047   return tbbox->computeNbOfInteractionsWith(sbbox,eps);
1048 }
1049
1050 /*!
1051  * Creates a new MEDCouplingMesh containing a part of cells of \a this mesh. The new
1052  * mesh shares a coordinates array with \a this one. The cells to include to the
1053  * result mesh are specified by an array of cell ids.
1054  *  \param [in] start - an array of cell ids to include to the result mesh.
1055  *  \param [in] end - specifies the end of the array \a start, so that
1056  *              the last value of \a start is \a end[ -1 ].
1057  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
1058  *         delete this mesh using decrRef() as it is no more needed. 
1059  */
1060 MEDCouplingMesh *MEDCouplingPointSet::buildPart(const mcIdType *start, const mcIdType *end) const
1061 {
1062   return buildPartOfMySelf(start,end,true);
1063 }
1064
1065 /*!
1066  * Creates a new MEDCouplingMesh containing a part of cells of \a this mesh. The
1067  * cells to include to the result mesh are specified by an array of cell ids. 
1068  * <br> This method additionally returns a renumbering map in "Old to New" mode
1069  * which allows the caller to know the mapping between nodes in \a this and the result mesh.
1070  *  \param [in] start - an array of cell ids to include to the result mesh.
1071  *  \param [in] end - specifies the end of the array \a start, so that
1072  *              the last value of \a start is \a end[ -1 ].
1073  *  \param [out] arr - a new DataArrayIdType that is the "Old to New" renumbering
1074  *         map. The caller is to delete this array using decrRef() as it is no more needed.
1075  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
1076  *         delete this mesh using decrRef() as it is no more needed. 
1077  */
1078 MEDCouplingMesh *MEDCouplingPointSet::buildPartAndReduceNodes(const mcIdType *start, const mcIdType *end, DataArrayIdType*& arr) const
1079 {
1080   MCAuto<MEDCouplingPointSet> ret=buildPartOfMySelf(start,end,true);
1081   arr=ret->zipCoordsTraducer();
1082   return ret.retn();
1083 }
1084
1085 /*!
1086  * This method specialized the MEDCouplingMesh::buildPartRange.
1087  * This method is equivalent to MEDCouplingMesh::buildPart method except that here the cell ids are specified using slice
1088  * \a beginCellIds \a endCellIds and \a stepCellIds.
1089  * \b WARNING , there is a big difference compared to MEDCouplingMesh::buildPart method.
1090  * If the input range is equal all cells in \a this, \a this is returned !
1091  *
1092  * \return a new ref to be managed by the caller. Warning this ref can be equal to \a this if input slice is exactly equal to the whole cells in the same order.
1093  *
1094  * \sa MEDCouplingUMesh::buildPartOfMySelfSlice
1095  */
1096 MEDCouplingMesh *MEDCouplingPointSet::buildPartRange(mcIdType beginCellIds, mcIdType endCellIds, mcIdType stepCellIds) const
1097 {
1098   if(beginCellIds==0 && endCellIds==ToIdType(getNumberOfCells()) && stepCellIds==1)
1099     {
1100       MEDCouplingMesh *ret(const_cast<MEDCouplingPointSet *>(this));
1101       ret->incrRef();
1102       return ret;
1103     }
1104   else
1105     {
1106       return buildPartOfMySelfSlice(beginCellIds,endCellIds,stepCellIds,true);
1107     }
1108 }
1109
1110 /*!
1111  * This method specialized the MEDCouplingMesh::buildPartRangeAndReduceNodes
1112  *
1113  * \param [out] beginOut valid only if \a arr not NULL !
1114  * \param [out] endOut valid only if \a arr not NULL !
1115  * \param [out] stepOut valid only if \a arr not NULL !
1116  * \param [out] arr correspondence old to new in node ids.
1117  * 
1118  * \sa MEDCouplingUMesh::buildPartOfMySelfSlice
1119  */
1120 MEDCouplingMesh *MEDCouplingPointSet::buildPartRangeAndReduceNodes(mcIdType beginCellIds, mcIdType endCellIds, mcIdType stepCellIds, mcIdType& beginOut, mcIdType& endOut, mcIdType& stepOut, DataArrayIdType*& arr) const
1121 {
1122   MCAuto<MEDCouplingPointSet> ret(buildPartOfMySelfSlice(beginCellIds,endCellIds,stepCellIds,true));
1123   arr=ret->zipCoordsTraducer();
1124   return ret.retn();
1125 }
1126
1127 /*!
1128  * 'This' is expected to be of spaceDim==2. Idem for 'center' and 'vect'
1129  */
1130 void MEDCouplingPointSet::rotate2D(const double *center, double angle)
1131 {
1132   double *coords(_coords->getPointer());
1133   mcIdType nbNodes(getNumberOfNodes());
1134   DataArrayDouble::Rotate2DAlg(center,angle,nbNodes,coords,coords);
1135 }
1136
1137 /// @cond INTERNAL
1138
1139 class DummyClsMCPS
1140 {
1141 public:
1142   static const int MY_SPACEDIM=3;
1143   static const int MY_MESHDIM=2;
1144   typedef mcIdType MyConnType;
1145   static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
1146 };
1147
1148 /// @endcond
1149
1150 /*!
1151  * res should be an empty vector before calling this method.
1152  * This method returns all the node coordinates included in _coords which ids are in [startConn;endConn) and put it into 'res' vector.
1153  * If spaceDim==3 a projection will be done for each nodes on the middle plane containing these all nodes in [startConn;endConn).
1154  * And after each projected nodes are moved to Oxy plane in order to consider these nodes as 2D nodes.
1155  */
1156 void MEDCouplingPointSet::project2DCellOnXY(const mcIdType *startConn, const mcIdType *endConn, std::vector<double>& res) const
1157 {
1158   const double *coords(_coords->getConstPointer());
1159   std::size_t spaceDim(getSpaceDimension());
1160   for(const mcIdType *it=startConn;it!=endConn;it++)
1161     res.insert(res.end(),coords+spaceDim*(*it),coords+spaceDim*(*it+1));
1162   if(spaceDim==2)
1163     return ;
1164   if(spaceDim==3)
1165     {
1166       std::vector<double> cpy(res);
1167       mcIdType nbNodes=ToIdType(std::distance(startConn,endConn));
1168       INTERP_KERNEL::PlanarIntersector<DummyClsMCPS,mcIdType>::Projection(&res[0],&cpy[0],nbNodes,nbNodes,1.e-12,0./*max distance*/,-1./*min dot*/,0.,true);
1169       res.resize(2*nbNodes);
1170       for(mcIdType i=0;i<nbNodes;i++)
1171         {
1172           res[2*i]=cpy[3*i];
1173           res[2*i+1]=cpy[3*i+1];
1174         }
1175       return ;
1176     }
1177   throw INTERP_KERNEL::Exception("Invalid spacedim for project2DCellOnXY !");
1178 }
1179
1180 /*!
1181  * low level method that checks that the 2D cell is not a butterfly cell.
1182  */
1183 bool MEDCouplingPointSet::isButterfly2DCell(const std::vector<double>& res, bool isQuad, double eps)
1184 {
1185   INTERP_KERNEL::QuadraticPlanarPrecision prec(eps);
1186
1187   std::size_t nbOfNodes(res.size()/2);
1188   std::vector<INTERP_KERNEL::Node *> nodes(nbOfNodes);
1189   for(std::size_t i=0;i<nbOfNodes;i++)
1190     {
1191       INTERP_KERNEL::Node *tmp=new INTERP_KERNEL::Node(res[2*i],res[2*i+1]);
1192       nodes[i]=tmp;
1193     }
1194   INTERP_KERNEL::QuadraticPolygon *pol=0;
1195   if(isQuad)
1196     pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
1197   else
1198     pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
1199   bool ret(pol->isButterflyAbs());
1200   delete pol;
1201   return ret;
1202 }
1203
1204 /*!
1205  * This method compares 2 cells coming from two unstructured meshes : \a this and \a other.
1206  * This method compares 2 cells having the same id 'cellId' in \a this and \a other.
1207  */
1208 bool MEDCouplingPointSet::areCellsFrom2MeshEqual(const MEDCouplingPointSet *other, mcIdType cellId, double prec) const
1209 {
1210   if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1211     return false;
1212   std::vector<mcIdType> c1,c2;
1213   getNodeIdsOfCell(cellId,c1);
1214   other->getNodeIdsOfCell(cellId,c2);
1215   std::size_t sz(c1.size());
1216   if(sz!=c2.size())
1217     return false;
1218   for(std::size_t i=0;i<sz;i++)
1219     {
1220       std::vector<double> n1,n2;
1221       getCoordinatesOfNode(c1[0],n1);
1222       other->getCoordinatesOfNode(c2[0],n2);
1223       std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1224       std::transform(n1.begin(),n1.end(),n1.begin(),[](double c){return fabs(c);}); 
1225       if(*std::max_element(n1.begin(),n1.end())>prec)
1226         return false;
1227     }
1228   return true;
1229 }
1230
1231 /*!
1232  * Substitutes node coordinates array of \a this mesh with that of \a other mesh
1233  * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
1234  * meshes match with a specified precision, else an exception is thrown and \a this
1235  * remains unchanged. In case of success the nodal connectivity of \a this mesh
1236  * is permuted according to new order of nodes.
1237  * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
1238  * coordinates (and so more expensive) than simple equality.
1239  *  \param [in] other - the other mesh whose node coordinates array will be used by
1240  *         \a this mesh in case of their equality.
1241  *  \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
1242  *  \throw If the coordinates array of \a this is not set.
1243  *  \throw If the coordinates array of \a other is not set.
1244  *  \throw If the coordinates of \a this and \a other do not match.
1245  */
1246 void MEDCouplingPointSet::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon)
1247 {
1248   const DataArrayDouble *coords=other.getCoords();
1249   if(!coords)
1250     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute : No coords specified in other !");
1251   if(!_coords)
1252     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
1253   mcIdType otherNbOfNodes=other.getNumberOfNodes();
1254   MCAuto<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
1255   _coords->incrRef();
1256   MCAuto<DataArrayDouble> oldCoords=_coords;
1257   setCoords(newCoords);
1258   bool areNodesMerged;
1259   mcIdType newNbOfNodes;
1260   MCAuto<DataArrayIdType> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
1261   if(!areNodesMerged)
1262     {
1263       setCoords(oldCoords);
1264       throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
1265     }
1266   mcIdType maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
1267   const mcIdType *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind(std::greater<mcIdType>(),std::placeholders::_1,maxId));
1268   if(pt!=da->getConstPointer()+da->getNbOfElems())
1269     {
1270       setCoords(oldCoords);
1271       throw INTERP_KERNEL::Exception("MEDCouplingPointSet::tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
1272     }
1273   setCoords(oldCoords);
1274   renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
1275   setCoords(coords);
1276 }
1277
1278 MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelf(const mcIdType *begin, const mcIdType *end, bool keepCoords) const
1279 {
1280   MCAuto<MEDCouplingPointSet> ret=buildPartOfMySelfKeepCoords(begin,end);
1281   if(!keepCoords)
1282     ret->zipCoords();
1283   return ret.retn();
1284 }
1285
1286 MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelfSlice(mcIdType start, mcIdType end, mcIdType step, bool keepCoords) const
1287 {
1288   MCAuto<MEDCouplingPointSet> ret=buildPartOfMySelfKeepCoordsSlice(start,end,step);
1289   if(!keepCoords)
1290     ret->zipCoords();
1291   return ret.retn();
1292 }
1293
1294 /*!
1295  Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
1296  copy are selected basing on specified node ids and the value of \a fullyIn
1297  parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the 
1298  array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
1299  node is in the array of node ids. The created mesh shares the node coordinates array
1300  with \a this mesh.
1301  *  \param [in] begin - the array of node ids.
1302  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
1303  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
1304  *         array \a begin are copied, else cells whose any node is in the
1305  *         array \a begin are copied.
1306  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
1307  *         to delete this mesh using decrRef() as it is no more needed. 
1308  *  \throw If the coordinates array is not set.
1309  *  \throw If the nodal connectivity of cells is not defined.
1310  *  \throw If any node id in \a begin is not valid.
1311  *
1312  *  \if ENABLE_EXAMPLES
1313  *  \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
1314  *  \ref  py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
1315  *  \endif
1316  */
1317 MEDCouplingPointSet *MEDCouplingPointSet::buildPartOfMySelfNode(const mcIdType *begin, const mcIdType *end, bool fullyIn) const
1318 {
1319   DataArrayIdType *cellIdsKept=0;
1320   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1321   MCAuto<DataArrayIdType> cellIdsKept2(cellIdsKept);
1322   return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
1323 }
1324
1325 /*!
1326  * Removes duplicates of cells from \a this mesh and returns an array mapping between
1327  * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1328  * equal cells found.
1329  *  \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1330  *           to write this mesh to the MED file, its cells must be sorted using
1331  *           sortCellsInMEDFileFrmt().
1332  *  \param [in] compType - specifies a cell comparison technique. Meaning of its
1333  *          valid values [0,1,2] is as follows.
1334  *   - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1335  *         connectivity and type. This is the strongest policy.
1336  *   - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1337  *         are based on same nodes and have the same type and orientation.
1338  *   - 2 : "nodal". Two cells are considered equal \c iff they
1339  *         are based on same nodes and have the same type. This is the weakest
1340  *         policy, it can be used by users not sensitive to cell orientation.
1341  *  \param [in] startCellId - specifies the cell id at which search for equal cells
1342  *         starts. By default it is 0, which means that all cells in \a this will be
1343  *         scanned. 
1344  *  \return DataArrayIdType - a new instance of DataArrayIdType, of length \a
1345  *           this->getNumberOfCells() before call of this method. The caller is to
1346  *           delete this array using decrRef() as it is no more needed. 
1347  *  \throw If the coordinates array is not set.
1348  *  \throw If the nodal connectivity of cells is not defined.
1349  *  \throw If the nodal connectivity includes an invalid id.
1350  *
1351  *  \if ENABLE_EXAMPLES
1352  *  \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1353  *  \ref  py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1354  *  \endif
1355  */
1356 DataArrayIdType *MEDCouplingPointSet::zipConnectivityTraducer(int compType, mcIdType startCellId)
1357 {
1358   DataArrayIdType *commonCells(nullptr),*commonCellsI(nullptr);
1359   findCommonCells(compType,startCellId,commonCells,commonCellsI);
1360   MCAuto<DataArrayIdType> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1361   mcIdType newNbOfCells=-1;
1362   MCAuto<DataArrayIdType> ret=DataArrayIdType::ConvertIndexArrayToO2N(ToIdType(getNumberOfCells()),commonCells->begin(),commonCellsI->begin(),commonCellsI->end(),newNbOfCells);
1363   MCAuto<DataArrayIdType> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1364   MCAuto<MEDCouplingPointSet> self=buildPartOfMySelf(ret2->begin(),ret2->end(),true);
1365   shallowCopyConnectivityFrom(self);
1366   return ret.retn();
1367 }
1368
1369 /*!
1370  * This const method states if the nodal connectivity of this fetches all nodes in \a this.
1371  * In other words, this method looks is there are no orphan nodes in \a this.
1372  * \sa zipCoordsTraducer, getNodeIdsInUse, computeFetchedNodeIds.
1373  */
1374 bool MEDCouplingPointSet::areAllNodesFetched() const
1375 {
1376   checkFullyDefined();
1377   mcIdType nbNodes(getNumberOfNodes());
1378   std::vector<bool> fetchedNodes(nbNodes,false);
1379   computeNodeIdsAlg(fetchedNodes);
1380   return std::find(fetchedNodes.begin(),fetchedNodes.end(),false)==fetchedNodes.end();
1381 }
1382
1383 /*!
1384  * Checks if \a this and \a other meshes are geometrically equivalent, else an
1385  * exception is thrown. The meshes are
1386  * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
1387  * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
1388  * the \a other mesh (with use of a specified cell comparison technique). The mapping 
1389  * from \a other to \a this for nodes and cells is returned via out parameters.
1390  *
1391  * 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.
1392  *
1393  * 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.
1394  *
1395  * So null (or Py_None) returned in \a cellCor and/or \a nodeCor means identity array. This is for optimization reason to avoid building
1396  * useless arrays for some \a levOfCheck (for example 0).
1397  *
1398  *  \param [in] other - the mesh to compare with.
1399  *  \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
1400  *         each method in description of MEDCouplingPointSet::zipConnectivityTraducer().
1401  *  \param [in] prec - the precision used to compare nodes of the two meshes.
1402  *  \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
1403  *         to delete this array using decrRef() as it is no more needed.
1404  *  \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
1405  *         to delete this array using decrRef() as it is no more needed.
1406  *  \throw If the two meshes do not match.
1407  *
1408  *  \if ENABLE_EXAMPLES
1409  *  \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
1410  *  \ref  py_mcumesh_checkDeepEquivalWith "Here is a Python example".
1411  *  \endif
1412  */
1413 void MEDCouplingPointSet::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
1414                                                DataArrayIdType *&cellCor, DataArrayIdType *&nodeCor) const
1415 {
1416   if(!other)
1417     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalWith : input is null !");
1418   const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
1419   if(!otherC)
1420     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalWith : other is not a PointSet mesh !");
1421   MCAuto<MEDCouplingPointSet> m=dynamic_cast<MEDCouplingPointSet *>(mergeMyselfWith(otherC));
1422   bool areNodesMerged;
1423   mcIdType newNbOfNodes;
1424   mcIdType oldNbOfNodes=getNumberOfNodes();
1425   MCAuto<DataArrayIdType> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
1426   //mergeNodes
1427   if(!areNodesMerged && oldNbOfNodes != 0)
1428     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
1429   const mcIdType *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind(std::greater<mcIdType>(),std::placeholders::_1,oldNbOfNodes-1));
1430   if(pt!=da->getConstPointer()+da->getNbOfElems())
1431     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
1432   m->renumberNodes(da->getConstPointer(),newNbOfNodes);
1433   //
1434   MCAuto<DataArrayIdType> nodeCor2=da->subArray(oldNbOfNodes);
1435   da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
1436   //
1437   da=m->zipConnectivityTraducer(cellCompPol);
1438   mcIdType nbCells=ToIdType(getNumberOfCells());
1439   if (nbCells != ToIdType(other->getNumberOfCells()))
1440     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
1441   mcIdType dan(da->getNumberOfTuples());
1442   if (dan)
1443     {
1444       MCAuto<DataArrayIdType> da1(DataArrayIdType::New()),da2(DataArrayIdType::New());
1445       da1->alloc(dan/2,1); da2->alloc(dan/2,1);
1446       std::copy(da->getConstPointer(), da->getConstPointer()+dan/2, da1->getPointer());
1447       std::copy(da->getConstPointer()+dan/2, da->getConstPointer()+dan, da2->getPointer());
1448       da1->sort(); da2->sort();
1449       if (!da1->isEqualWithoutConsideringStr(*da2))
1450         throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
1451     }
1452   MCAuto<DataArrayIdType> cellCor2=da->selectByTupleIdSafeSlice(nbCells,ToIdType(da->getNbOfElems()),1);
1453   nodeCor=nodeCor2->isIota(nodeCor2->getNumberOfTuples())?0:nodeCor2.retn();
1454   cellCor=cellCor2->isIota(cellCor2->getNumberOfTuples())?0:cellCor2.retn();
1455 }
1456
1457 /*!
1458  * Checks if \a this and \a other meshes are geometrically equivalent, else an
1459  * exception is thrown. The meshes are considered equivalent if (1) they share one
1460  * node coordinates array and (2) they contain the same cells (with use of a specified
1461  * cell comparison technique). The mapping from cells of the \a other to ones of \a this 
1462  * is returned via an out parameter.
1463  *
1464  * 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.
1465  *
1466  *  \param [in] other - the mesh to compare with.
1467  *  \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
1468  *         each method in description of MEDCouplingPointSet::zipConnectivityTraducer().
1469  *  \param [in] prec - a not used parameter.
1470  *  \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
1471  *         to delete this array using decrRef() as it is no more needed.
1472  *  \throw If the two meshes do not match.
1473  *
1474  * \if ENABLE_EXAMPLES
1475  * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
1476  * \ref  py_mcumesh_checkDeepEquivalWith "Here is a Python example".
1477  * \endif
1478  */
1479 void MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
1480                                                        DataArrayIdType *&cellCor) const
1481 {
1482   if(!other)
1483     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith : input is null !");
1484   const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
1485   if(!otherC)
1486     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkDeepEquivalOnSameNodesWith : other is not a PointSet mesh !");
1487   if(_coords!=otherC->_coords)
1488     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
1489   MCAuto<MEDCouplingPointSet> m=mergeMyselfWithOnSameCoords(otherC);
1490   MCAuto<DataArrayIdType> da=m->zipConnectivityTraducer(cellCompPol);
1491   mcIdType maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
1492   const mcIdType *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind(std::greater<mcIdType>(),std::placeholders::_1,maxId));
1493   if(pt!=da->getConstPointer()+da->getNbOfElems())
1494     {
1495       throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
1496     }
1497   MCAuto<DataArrayIdType> cellCor2=da->selectByTupleIdSafeSlice(ToIdType(getNumberOfCells()),ToIdType(da->getNbOfElems()),1);
1498   cellCor=cellCor2->isIota(cellCor2->getNumberOfTuples())?0:cellCor2.retn();
1499 }
1500
1501 void MEDCouplingPointSet::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
1502 {
1503   MEDCouplingMesh::checkFastEquivalWith(other,prec);
1504   //other not null checked by the line before
1505   const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
1506   if(!otherC)
1507     throw INTERP_KERNEL::Exception("MEDCouplingPointSet::checkFastEquivalWith : fails because other is not a pointset mesh !");
1508   mcIdType nbOfCells=ToIdType(getNumberOfCells());
1509   if(nbOfCells<1)
1510     return ;
1511   bool status=true;
1512   status&=areCellsFrom2MeshEqual(otherC,0,prec);
1513   status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
1514   status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
1515   if(!status)
1516     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
1517 }
1518
1519 /*!
1520  * Finds cells whose all or some nodes are in a given array of node ids.
1521  *  \param [in] begin - the array of node ids.
1522  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
1523  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
1524  *         array \a begin are returned only, else cells whose any node is in the
1525  *         array \a begin are returned.
1526  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of found
1527  *         cells. The caller is to delete this array using decrRef() as it is no more
1528  *         needed. 
1529  *  \throw If the coordinates array is not set.
1530  *  \throw If the nodal connectivity of cells is not defined.
1531  *  \throw If any cell id in \a begin is not valid.
1532  *
1533  * \sa MEDCouplingPointSet::getCellIdsFullyIncludedInNodeIds
1534  *
1535  *  \if ENABLE_EXAMPLES
1536  *  \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
1537  *  \ref  py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
1538  *  \endif
1539  */
1540 DataArrayIdType *MEDCouplingPointSet::getCellIdsLyingOnNodes(const mcIdType *begin, const mcIdType *end, bool fullyIn) const
1541 {
1542   DataArrayIdType *cellIdsKept=0;
1543   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1544   cellIdsKept->setName(getName());
1545   return cellIdsKept;
1546 }
1547
1548 /*!
1549  * Finds cells whose all nodes are in a given array of node ids.
1550  * This method is a specialization of MEDCouplingPointSet::getCellIdsLyingOnNodes (true
1551  * as last input argument).
1552  *  \param [in] partBg - the array of node ids.
1553  *  \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
1554  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of found
1555  *          cells. The caller is to delete this array using decrRef() as it is no
1556  *          more needed.
1557  *  \throw If the coordinates array is not set.
1558  *  \throw If the nodal connectivity of cells is not defined.
1559  *  \throw If any cell id in \a partBg is not valid.
1560  * 
1561  * \sa MEDCouplingPointSet::getCellIdsLyingOnNodes
1562  *
1563  *  \if ENABLE_EXAMPLES
1564  *  \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
1565  *  \ref  py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
1566  *  \endif
1567  */
1568 DataArrayIdType *MEDCouplingPointSet::getCellIdsFullyIncludedInNodeIds(const mcIdType *partBg, const mcIdType *partEnd) const
1569 {
1570   return getCellIdsLyingOnNodes(partBg,partEnd,true);
1571 }
1572
1573 /*!
1574  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1575  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1576  * array mean that the corresponding old node is no more used. 
1577  *  \return DataArrayIdType * - a new instance of DataArrayIdType of length \a
1578  *           this->getNumberOfNodes() before call of this method. The caller is to
1579  *           delete this array using decrRef() as it is no more needed. 
1580  *  \throw If the coordinates array is not set.
1581  *  \throw If the nodal connectivity of cells is not defined.
1582  *  \throw If the nodal connectivity includes an invalid id.
1583  *
1584  *  \if ENABLE_EXAMPLES
1585  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1586  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1587  *  \endif
1588  */
1589 DataArrayIdType *MEDCouplingPointSet::zipCoordsTraducer()
1590 {
1591   mcIdType newNbOfNodes=-1;
1592   MCAuto<DataArrayIdType> traducer=getNodeIdsInUse(newNbOfNodes);
1593   renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1594   return traducer.retn();
1595 }
1596
1597 /*!
1598  * Merges nodes equal within \a precision and returns an array describing the 
1599  * permutation used to remove duplicate nodes.
1600  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1601  *              considered not coincident.
1602  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1603  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1604  *  \return DataArrayIdType * - the permutation array in "Old to New" mode. For more 
1605  *          info on "Old to New" mode see \ref numbering. The caller
1606  *          is to delete this array using decrRef() as it is no more needed.
1607  *  \throw If the coordinates array is not set.
1608  *  \throw If the nodal connectivity of cells is not defined.
1609  *
1610  *  \if ENABLE_EXAMPLES
1611  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1612  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1613  *  \endif
1614  */
1615 DataArrayIdType *MEDCouplingPointSet::mergeNodes(double precision, bool& areNodesMerged, mcIdType& newNbOfNodes)
1616 {
1617   MCAuto<DataArrayIdType> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1618   if(areNodesMerged)
1619     renumberNodes(ret->begin(),newNbOfNodes);
1620   return ret.retn();
1621 }
1622
1623 /*!
1624  * Merges nodes equal within \a precision and returns an array describing the 
1625  * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1626  *  of merged nodes is changed to be at their barycenter.
1627  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1628  *              considered not coincident.
1629  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1630  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1631  *  \return DataArrayIdType * - the permutation array in "Old to New" mode. For more 
1632  *          info on "Old to New" mode see \ref numbering. The caller
1633  *          is to delete this array using decrRef() as it is no more needed.
1634  *  \throw If the coordinates array is not set.
1635  *  \throw If the nodal connectivity of cells is not defined.
1636  *
1637  *  \if ENABLE_EXAMPLES
1638  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1639  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1640  *  \endif
1641  */
1642 DataArrayIdType *MEDCouplingPointSet::mergeNodesCenter(double precision, bool& areNodesMerged, mcIdType& newNbOfNodes)
1643 {
1644   DataArrayIdType *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1645   if(areNodesMerged)
1646     renumberNodesCenter(ret->getConstPointer(),newNbOfNodes);
1647   return ret;
1648 }