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