]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/MEDCoupling/MEDCouplingUMesh.cxx
Salome HOME
On the road of addition of optimized unstructured mesh with a single geometric type.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.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 "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingMemArray.txx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "CellModel.hxx"
25 #include "VolSurfUser.txx"
26 #include "InterpolationUtils.hxx"
27 #include "PointLocatorAlgos.txx"
28 #include "BBTree.txx"
29 #include "BBTreeDst.txx"
30 #include "SplitterTetra.hxx"
31 #include "DirectedBoundingBox.hxx"
32 #include "InterpKernelMeshQuality.hxx"
33 #include "InterpKernelCellSimplify.hxx"
34 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
35 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
36 #include "InterpKernelAutoPtr.hxx"
37 #include "InterpKernelGeo2DNode.hxx"
38 #include "InterpKernelGeo2DEdgeLin.hxx"
39 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
40 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
41
42 #include <sstream>
43 #include <fstream>
44 #include <numeric>
45 #include <cstring>
46 #include <limits>
47 #include <list>
48
49 using namespace ParaMEDMEM;
50
51 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
52
53 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
54
55 MEDCouplingUMesh *MEDCouplingUMesh::New()
56 {
57   return new MEDCouplingUMesh;
58 }
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
61 {
62   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
63   ret->setName(meshName);
64   ret->setMeshDimension(meshDim);
65   return ret;
66 }
67
68 /*!
69  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
70  * between \a this and the new mesh.
71  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
72  *          delete this mesh using decrRef() as it is no more needed. 
73  */
74 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
75 {
76   return clone(true);
77 }
78
79 /*!
80  * Returns a new MEDCouplingMesh which is a copy of \a this one.
81  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
82  * this mesh are shared by the new mesh.
83  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
84  *          delete this mesh using decrRef() as it is no more needed. 
85  */
86 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
87 {
88   return new MEDCouplingUMesh(*this,recDeepCpy);
89 }
90
91 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
92 {
93   std::size_t ret=0;
94   if(_nodal_connec)
95     ret+=_nodal_connec->getHeapMemorySize();
96   if(_nodal_connec_index)
97     ret+=_nodal_connec_index->getHeapMemorySize();
98   return MEDCouplingPointSet::getHeapMemorySize()+ret;
99 }
100
101 void MEDCouplingUMesh::updateTime() const
102 {
103   MEDCouplingPointSet::updateTime();
104   if(_nodal_connec)
105     {
106       updateTimeWith(*_nodal_connec);
107     }
108   if(_nodal_connec_index)
109     {
110       updateTimeWith(*_nodal_connec_index);
111     }
112 }
113
114 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
115 {
116 }
117
118 /*!
119  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
120  * then \a this mesh is most probably is writable, exchangeable and available for most
121  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
122  * this method to check that all is in order with \a this mesh.
123  *  \throw If the mesh dimension is not set.
124  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
125  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
126  *  \throw If the connectivity data array has more than one component.
127  *  \throw If the connectivity data array has a named component.
128  *  \throw If the connectivity index data array has more than one component.
129  *  \throw If the connectivity index data array has a named component.
130  */
131 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
132 {
133   if(_mesh_dim<-1)
134    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
135   if(_mesh_dim!=-1)
136     MEDCouplingPointSet::checkCoherency();
137   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
138     {
139       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
140         {
141           std::ostringstream message;
142           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
143           throw INTERP_KERNEL::Exception(message.str().c_str());
144         }
145     }
146   if(_nodal_connec)
147     {
148       if(_nodal_connec->getNumberOfComponents()!=1)
149         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
150       if(_nodal_connec->getInfoOnComponent(0)!="")
151         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
152     }
153   if(_nodal_connec_index)
154     {
155       if(_nodal_connec_index->getNumberOfComponents()!=1)
156         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
157       if(_nodal_connec_index->getInfoOnComponent(0)!="")
158         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
159     }
160 }
161
162 /*!
163  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
164  * then \a this mesh is most probably is writable, exchangeable and available for all
165  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
166  * method thoroughly checks the nodal connectivity.
167  *  \param [in] eps - a not used parameter.
168  *  \throw If the mesh dimension is not set.
169  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
170  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
171  *  \throw If the connectivity data array has more than one component.
172  *  \throw If the connectivity data array has a named component.
173  *  \throw If the connectivity index data array has more than one component.
174  *  \throw If the connectivity index data array has a named component.
175  *  \throw If number of nodes defining an element does not correspond to the type of element.
176  *  \throw If the nodal connectivity includes an invalid node id.
177  */
178 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
179 {
180   checkCoherency();
181   if(_mesh_dim==-1)
182     return ;
183   int meshDim=getMeshDimension();
184   int nbOfNodes=getNumberOfNodes();
185   int nbOfCells=getNumberOfCells();
186   const int *ptr=_nodal_connec->getConstPointer();
187   const int *ptrI=_nodal_connec_index->getConstPointer();
188   for(int i=0;i<nbOfCells;i++)
189     {
190       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
191       if((int)cm.getDimension()!=meshDim)
192         {
193           std::ostringstream oss;
194           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
195           throw INTERP_KERNEL::Exception(oss.str().c_str());
196         }
197       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
198       if(!cm.isDynamic())
199         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
200           {
201             std::ostringstream oss;
202             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
203             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
204             throw INTERP_KERNEL::Exception(oss.str().c_str());
205           }
206       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
207         {
208           int nodeId=*w;
209           if(nodeId>=0)
210             {
211               if(nodeId>=nbOfNodes)
212                 {
213                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
214                   throw INTERP_KERNEL::Exception(oss.str().c_str());
215                 }
216             }
217           else if(nodeId<-1)
218             {
219               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
220               throw INTERP_KERNEL::Exception(oss.str().c_str());
221             }
222           else
223             {
224               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
225                 {
226                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
227                   throw INTERP_KERNEL::Exception(oss.str().c_str());
228                 }
229             }
230         }
231     }
232 }
233
234
235 /*!
236  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
237  * then \a this mesh is most probably is writable, exchangeable and available for all
238  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
239  *  \param [in] eps - a not used parameter.
240  *  \throw If the mesh dimension is not set.
241  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
242  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
243  *  \throw If the connectivity data array has more than one component.
244  *  \throw If the connectivity data array has a named component.
245  *  \throw If the connectivity index data array has more than one component.
246  *  \throw If the connectivity index data array has a named component.
247  *  \throw If number of nodes defining an element does not correspond to the type of element.
248  *  \throw If the nodal connectivity includes an invalid node id.
249  */
250 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
251 {
252   checkCoherency1(eps);
253 }
254
255 /*!
256  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
257  * elements contained in the mesh. For more info on the mesh dimension see
258  * \ref MEDCouplingUMeshPage.
259  *  \param [in] meshDim - a new mesh dimension.
260  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
261  */
262 void MEDCouplingUMesh::setMeshDimension(int meshDim)
263 {
264   if(meshDim<-1 || meshDim>3)
265     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
266   _mesh_dim=meshDim;
267   declareAsNew();
268 }
269
270 /*!
271  * Allocates memory to store given number of cells.
272  *  \param [in] nbOfCells - number of cell \a this mesh will contain.
273  *
274  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
275  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
276  */
277 void MEDCouplingUMesh::allocateCells(int nbOfCells)
278 {
279   if(_nodal_connec_index)
280     {
281       _nodal_connec_index->decrRef();
282     }
283   if(_nodal_connec)
284     {
285       _nodal_connec->decrRef();
286     }
287   _nodal_connec_index=DataArrayInt::New();
288   _nodal_connec_index->reserve(nbOfCells+1);
289   _nodal_connec_index->pushBackSilent(0);
290   _nodal_connec=DataArrayInt::New();
291   _nodal_connec->reserve(2*nbOfCells);
292   _types.clear();
293   declareAsNew();
294 }
295
296 /*!
297  * Appends a cell to the connectivity array. For deeper understanding what is
298  * happening see \ref MEDCouplingUMeshNodalConnectivity.
299  *  \param [in] type - type of cell to add.
300  *  \param [in] size - number of nodes constituting this cell.
301  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
302  * 
303  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
304  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
305  */
306 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
307 {
308   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
309   if(_nodal_connec_index==0)
310     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
311   if((int)cm.getDimension()==_mesh_dim)
312     {
313       if(!cm.isDynamic())
314         if(size!=(int)cm.getNumberOfNodes())
315           {
316             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
317             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
318             throw INTERP_KERNEL::Exception(oss.str().c_str());
319           }
320       int idx=_nodal_connec_index->back();
321       int val=idx+size+1;
322       _nodal_connec_index->pushBackSilent(val);
323       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
324       _types.insert(type);
325     }
326   else
327     {
328       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
329       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
330       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
331       throw INTERP_KERNEL::Exception(oss.str().c_str());
332     }
333 }
334
335 /*!
336  * Compacts data arrays to release unused memory. This method is to be called after
337  * finishing cell insertion using \a this->insertNextCell().
338  * 
339  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
340  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
341  */
342 void MEDCouplingUMesh::finishInsertingCells()
343 {
344   _nodal_connec->pack();
345   _nodal_connec_index->pack();
346   _nodal_connec->declareAsNew();
347   _nodal_connec_index->declareAsNew();
348   updateTime();
349 }
350
351 /*!
352  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
353  * Useful for python users.
354  */
355 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
356 {
357   return new MEDCouplingUMeshCellIterator(this);
358 }
359
360 /*!
361  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
362  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
363  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
364  * Useful for python users.
365  */
366 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
367 {
368   if(!checkConsecutiveCellTypes())
369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
370   return new MEDCouplingUMeshCellByTypeEntry(this);
371 }
372
373 /*!
374  * Returns a set of all cell types available in \a this mesh.
375  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
376  * \warning this method does not throw any exception even if \a this is not defined.
377  */
378 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
379 {
380   return _types;
381 }
382
383 /*!
384  * This method is a method that compares \a this and \a other.
385  * This method compares \b all attributes, even names and component names.
386  */
387 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
388 {
389   if(!other)
390     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
391   std::ostringstream oss; oss.precision(15);
392   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
393   if(!otherC)
394     {
395       reason="mesh given in input is not castable in MEDCouplingUMesh !";
396       return false;
397     }
398   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
399     return false;
400   if(_mesh_dim!=otherC->_mesh_dim)
401     {
402       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
403       reason=oss.str();
404       return false;
405     }
406   if(_types!=otherC->_types)
407     {
408       oss << "umesh geometric type mismatch :\nThis geometric types are :";
409       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
410         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
411       oss << "\nOther geometric types are :";
412       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
413         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
414       reason=oss.str();
415       return false;
416     }
417   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
418     if(_nodal_connec==0 || otherC->_nodal_connec==0)
419       {
420         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
421         return false;
422       }
423   if(_nodal_connec!=otherC->_nodal_connec)
424     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
425       {
426         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
427         return false;
428       }
429   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
430     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
431       {
432         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
433         return false;
434       }
435   if(_nodal_connec_index!=otherC->_nodal_connec_index)
436     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
437       {
438         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
439         return false;
440       }
441   return true;
442 }
443
444 /*!
445  * Checks if data arrays of this mesh (node coordinates, nodal
446  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
447  * not considered.
448  *  \param [in] other - the mesh to compare with.
449  *  \param [in] prec - precision value used to compare node coordinates.
450  *  \return bool - \a true if the two meshes are same.
451  */
452 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
453 {
454   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
455   if(!otherC)
456     return false;
457   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
458     return false;
459   if(_mesh_dim!=otherC->_mesh_dim)
460     return false;
461   if(_types!=otherC->_types)
462     return false;
463   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
464     if(_nodal_connec==0 || otherC->_nodal_connec==0)
465       return false;
466   if(_nodal_connec!=otherC->_nodal_connec)
467     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
468       return false;
469   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
470     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
471       return false;
472   if(_nodal_connec_index!=otherC->_nodal_connec_index)
473     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
474       return false;
475   return true;
476 }
477
478 /*!
479  * Checks if \a this and \a other meshes are geometrically equivalent, else an
480  * exception is thrown. The meshes are
481  * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
482  * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
483  * the \a other mesh (with use of a specified cell comparison technique). The mapping 
484  * from \a other to \a this for nodes and cells is returned via out parameters.
485  *  \param [in] other - the mesh to compare with.
486  *  \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
487  *         each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
488  *  \param [in] prec - the precision used to compare nodes of the two meshes.
489  *  \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
490  *         to delete this array using decrRef() as it is no more needed.
491  *  \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
492  *         to delete this array using decrRef() as it is no more needed.
493  *  \throw If the two meshes do not match.
494  *
495  *  \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
496  *  \ref  py_mcumesh_checkDeepEquivalWith "Here is a Python example".
497  */
498 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
499                                             DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
500 {
501   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
502   if(!otherC)
503     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
504   MEDCouplingMesh::checkFastEquivalWith(other,prec);
505   if(_types!=otherC->_types)
506     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
507   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
508   bool areNodesMerged;
509   int newNbOfNodes;
510   int oldNbOfNodes=getNumberOfNodes();
511   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
512   //mergeNodes
513   if(!areNodesMerged)
514     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
515   const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
516   if(pt!=da->getConstPointer()+da->getNbOfElems())
517     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
518   m->renumberNodes(da->getConstPointer(),newNbOfNodes);
519   //
520   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
521   da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
522   
523   //
524   da=m->zipConnectivityTraducer(cellCompPol);
525   int nbCells=getNumberOfCells();
526   int maxId=-1;
527   if(nbCells!=0)
528     maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells);
529   pt=std::find_if(da->getConstPointer()+nbCells,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
530   if(pt!=da->getConstPointer()+da->getNbOfElems())
531     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(nbCells,da->getNbOfElems(),1);
533   nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
534   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
535 }
536
537 /*!
538  * Checks if \a this and \a other meshes are geometrically equivalent, else an
539  * exception is thrown. The meshes are considered equivalent if (1) they share one
540  * node coordinates array and (2) they contain the same cells (with use of a specified
541  * cell comparison technique). The mapping from cells of the \a other to ones of \a this 
542  * is returned via an out parameter.
543  *  \param [in] other - the mesh to compare with.
544  *  \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
545  *         each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
546  *  \param [in] prec - a not used parameter.
547  *  \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
548  *         to delete this array using decrRef() as it is no more needed.
549  *  \throw If the two meshes do not match.
550  *
551  * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
552  * \ref  py_mcumesh_checkDeepEquivalWith "Here is a Python example".
553  */
554 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
555                                                        DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
556 {
557   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
558   if(!otherC)
559     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
560   MEDCouplingMesh::checkFastEquivalWith(other,prec);
561   if(_types!=otherC->_types)
562     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
563   if(_coords!=otherC->_coords)
564     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
565   std::vector<const MEDCouplingUMesh *> ms(2);
566   ms[0]=this;
567   ms[1]=otherC;
568   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
570   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
571   const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
572   if(pt!=da->getConstPointer()+da->getNbOfElems())
573     {
574       throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
575     }
576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
577   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
578 }
579
580 /*!
581  * Checks if \a this and \a other meshes are geometrically equivalent with high
582  * probability, else an exception is thrown. The meshes are considered equivalent if
583  * (1) meshes contain the same number of nodes and the same number of elements of the
584  * same types (2) three cells of the two meshes (first, last and middle) are based
585  * on coincident nodes (with a specified precision).
586  *  \param [in] other - the mesh to compare with.
587  *  \param [in] prec - the precision used to compare nodes of the two meshes.
588  *  \throw If the two meshes do not match.
589  */
590 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
591 {
592   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
593   if(!otherC)
594     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
595   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
596   int nbOfCells=getNumberOfCells();
597   if(nbOfCells<1)
598     return ;
599   bool status=true;
600   status&=areCellsFrom2MeshEqual(otherC,0,prec);
601   status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
602   status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
603   if(!status)
604     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
605 }
606
607 /*!
608  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
609  * cells each node belongs to.
610  * \warning For speed reasons, this method does not check if node ids in the nodal
611  *          connectivity correspond to the size of node coordinates array.
612  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
613  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
614  *        dividing cell ids in \a revNodal into groups each referring to one
615  *        node. Its every element (except the last one) is an index pointing to the
616  *         first id of a group of cells. For example cells sharing the node #1 are 
617  *        described by following range of indices: 
618  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
619  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
620  *        Number of cells sharing the *i*-th node is
621  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
622  * \throw If the coordinates array is not set.
623  * \throw If the nodal connectivity of cells is not defined.
624  * 
625  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
626  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
627  */
628 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
629 {
630   checkFullyDefined();
631   int nbOfNodes=getNumberOfNodes();
632   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
633   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
634   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
635   const int *conn=_nodal_connec->getConstPointer();
636   const int *connIndex=_nodal_connec_index->getConstPointer();
637   int nbOfCells=getNumberOfCells();
638   int nbOfEltsInRevNodal=0;
639   for(int eltId=0;eltId<nbOfCells;eltId++)
640     {
641       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
642       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
643       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
644         if(*iter>=0)//for polyhedrons
645           {
646             nbOfEltsInRevNodal++;
647             revNodalIndxPtr[(*iter)+1]++;
648           }
649     }
650   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
651   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
652   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
653   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
654   for(int eltId=0;eltId<nbOfCells;eltId++)
655     {
656       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
657       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
658       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
659         if(*iter>=0)//for polyhedrons
660           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
661     }
662 }
663
664 /// @cond INTERNAL
665
666 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
667 {
668   return id;
669 }
670
671 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
672 {
673   if(!compute)
674     return id+1;
675   else
676     {
677       if(cm.getOrientationStatus(nb,conn1,conn2))
678         return id+1;
679       else
680         return -(id+1);
681     }
682 }
683
684 class MinusOneSonsGenerator
685 {
686 public:
687   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
688   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
689   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
690   static const int DELTA=1;
691 private:
692   const INTERP_KERNEL::CellModel& _cm;
693 };
694
695 class MinusOneSonsGeneratorBiQuadratic
696 {
697 public:
698   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
699   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
700   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
701   static const int DELTA=1;
702 private:
703   const INTERP_KERNEL::CellModel& _cm;
704 };
705
706 class MinusTwoSonsGenerator
707 {
708 public:
709   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
710   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
711   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
712   static const int DELTA=2;
713 private:
714   const INTERP_KERNEL::CellModel& _cm;
715 };
716
717 /// @endcond
718
719 /*!
720  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
721  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
722  * describing correspondence between cells of \a this and the result meshes are
723  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
724  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
725  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
726  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
727  * \warning For speed reasons, this method does not check if node ids in the nodal
728  *          connectivity correspond to the size of node coordinates array.
729  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
730  *          to write this mesh to the MED file, its cells must be sorted using
731  *          sortCellsInMEDFileFrmt().
732  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
733  *         each cell of \a this mesh.
734  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
735  *        dividing cell ids in \a desc into groups each referring to one
736  *        cell of \a this mesh. Its every element (except the last one) is an index
737  *        pointing to the first id of a group of cells. For example cells of the
738  *        result mesh bounding the cell #1 of \a this mesh are described by following
739  *        range of indices:
740  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
741  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
742  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
743  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
744  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
745  *         by each cell of the result mesh.
746  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
747  *        in the result mesh,
748  *        dividing cell ids in \a revDesc into groups each referring to one
749  *        cell of the result mesh the same way as \a descIndx divides \a desc.
750  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
751  *        delete this mesh using decrRef() as it is no more needed.
752  *  \throw If the coordinates array is not set.
753  *  \throw If the nodal connectivity of cells is node defined.
754  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
755  *         revDescIndx == NULL.
756  * 
757  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
758  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
759  * \sa buildDescendingConnectivity2()
760  */
761 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
762 {
763   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
764 }
765
766 /*!
767  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
768  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
769  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
770  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
771  * \sa MEDCouplingUMesh::buildDescendingConnectivity
772  */
773 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
774 {
775   checkFullyDefined();
776   if(getMeshDimension()!=3)
777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
778   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
779 }
780
781 /*!
782  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
783  * this->getMeshDimension(), that bound cells of \a this mesh. In
784  * addition arrays describing correspondence between cells of \a this and the result
785  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
786  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
787  *  mesh. This method differs from buildDescendingConnectivity() in that apart
788  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
789  * result meshes. So a positive id means that order of nodes in corresponding cells
790  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
791  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
792  * i.e. cell ids are one-based.
793  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
794  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
795  * \warning For speed reasons, this method does not check if node ids in the nodal
796  *          connectivity correspond to the size of node coordinates array.
797  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
798  *          to write this mesh to the MED file, its cells must be sorted using
799  *          sortCellsInMEDFileFrmt().
800  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
801  *         each cell of \a this mesh.
802  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
803  *        dividing cell ids in \a desc into groups each referring to one
804  *        cell of \a this mesh. Its every element (except the last one) is an index
805  *        pointing to the first id of a group of cells. For example cells of the
806  *        result mesh bounding the cell #1 of \a this mesh are described by following
807  *        range of indices:
808  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
809  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
810  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
811  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
812  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
813  *         by each cell of the result mesh.
814  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
815  *        in the result mesh,
816  *        dividing cell ids in \a revDesc into groups each referring to one
817  *        cell of the result mesh the same way as \a descIndx divides \a desc.
818  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
819  *        shares the node coordinates array with \a this mesh. The caller is to
820  *        delete this mesh using decrRef() as it is no more needed.
821  *  \throw If the coordinates array is not set.
822  *  \throw If the nodal connectivity of cells is node defined.
823  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
824  *         revDescIndx == NULL.
825  * 
826  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
827  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
828  * \sa buildDescendingConnectivity()
829  */
830 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
831 {
832   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
833 }
834
835 /*!
836  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
837  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
838  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
839  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
840  *
841  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
842  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
844  */
845 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
846 {
847   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
851   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
852   meshDM1=0;
853   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
854 }
855
856 /*!
857  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
858  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
859  * excluding a set of meshdim-1 cells in input descending connectivity.
860  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
861  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
862  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
863  *
864  * \param [in] desc descending connectivity array.
865  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
866  * \param [in] revDesc reverse descending connectivity array.
867  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
868  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
869  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
870  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
871  */
872 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
873                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
874 {
875   if(!desc || !descIndx || !revDesc || !revDescIndx)
876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
877   const int *descPtr=desc->getConstPointer();
878   const int *descIPtr=descIndx->getConstPointer();
879   const int *revDescPtr=revDesc->getConstPointer();
880   const int *revDescIPtr=revDescIndx->getConstPointer();
881   //
882   int nbCells=descIndx->getNumberOfTuples()-1;
883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
885   int *out1Ptr=out1->getPointer();
886   *out1Ptr++=0;
887   out0->reserve(desc->getNumberOfTuples());
888   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
889     {
890       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
891         {
892           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
893           s.erase(i);
894           out0->insertAtTheEnd(s.begin(),s.end());
895         }
896       *out1Ptr=out0->getNumberOfTuples();
897     }
898   neighbors=out0.retn();
899   neighborsIndx=out1.retn();
900 }
901
902 /// @cond INTERNAL
903
904 /*!
905  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
906  * For speed reasons no check of this will be done.
907  */
908 template<class SonsGenerator>
909 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
910 {
911   if(!desc || !descIndx || !revDesc || !revDescIndx)
912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
913   checkConnectivityFullyDefined();
914   int nbOfCells=getNumberOfCells();
915   int nbOfNodes=getNumberOfNodes();
916   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
917   int *revNodalIndxPtr=revNodalIndx->getPointer();
918   const int *conn=_nodal_connec->getConstPointer();
919   const int *connIndex=_nodal_connec_index->getConstPointer();
920   std::string name="Mesh constituent of "; name+=getName();
921   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
922   ret->setCoords(getCoords());
923   ret->allocateCells(2*nbOfCells);
924   descIndx->alloc(nbOfCells+1,1);
925   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
926   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
927   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
928     {
929       int pos=connIndex[eltId];
930       int posP1=connIndex[eltId+1];
931       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
932       SonsGenerator sg(cm);
933       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
934       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
935       for(unsigned i=0;i<nbOfSons;i++)
936         {
937           INTERP_KERNEL::NormalizedCellType cmsId;
938           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
939           for(unsigned k=0;k<nbOfNodesSon;k++)
940             if(tmp[k]>=0)
941               revNodalIndxPtr[tmp[k]+1]++;
942           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
943           revDesc2->pushBackSilent(eltId);
944         }
945       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
946     }
947   int nbOfCellsM1=ret->getNumberOfCells();
948   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
949   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
950   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
951   int *revNodalPtr=revNodal->getPointer();
952   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
953   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
954   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
955     {
956       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
957       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
958       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
959         if(*iter>=0)//for polyhedrons
960           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
961     }
962   //
963   DataArrayInt *commonCells=0,*commonCellsI=0;
964   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
965   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
966   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
967   int newNbOfCellsM1=-1;
968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
969                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
970   std::vector<bool> isImpacted(nbOfCellsM1,false);
971   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
972     for(int work2=work[0];work2!=work[1];work2++)
973       isImpacted[commonCellsPtr[work2]]=true;
974   const int *o2nM1Ptr=o2nM1->getConstPointer();
975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
976   const int *n2oM1Ptr=n2oM1->getConstPointer();
977   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
978   ret2->copyTinyInfoFrom(this);
979   desc->alloc(descIndx->back(),1);
980   int *descPtr=desc->getPointer();
981   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
982   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
983     {
984       if(!isImpacted[i])
985         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
986       else
987         {
988           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
989             {
990               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
991               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
992             }
993           else
994             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
995         }
996     }
997   revDesc->reserve(newNbOfCellsM1);
998   revDescIndx->alloc(newNbOfCellsM1+1,1);
999   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1000   const int *revDesc2Ptr=revDesc2->getConstPointer();
1001   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1002     {
1003       int oldCellIdM1=n2oM1Ptr[i];
1004       if(!isImpacted[oldCellIdM1])
1005         {
1006           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1007           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1008         }
1009       else
1010         {
1011           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1012             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1013           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1014           commonCellsIPtr++;
1015         }
1016     }
1017   //
1018   return ret2.retn();
1019 }
1020
1021 struct MEDCouplingAccVisit
1022 {
1023   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1024   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1025   int _new_nb_of_nodes;
1026 };
1027
1028 /// @endcond
1029
1030 /*!
1031  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1032  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1033  * array of cell ids. Pay attention that after conversion all algorithms work slower
1034  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1035  * conversion due presence of invalid ids in the array of cells to convert, as a
1036  * result \a this mesh contains some already converted elements. In this case the 2D
1037  * mesh remains valid but 3D mesh becomes \b inconsistent!
1038  *  \warning This method can significantly modify the order of geometric types in \a this,
1039  *          hence, to write this mesh to the MED file, its cells must be sorted using
1040  *          sortCellsInMEDFileFrmt().
1041  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1042  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1043  *         cellIdsToConvertBg.
1044  *  \throw If the coordinates array is not set.
1045  *  \throw If the nodal connectivity of cells is node defined.
1046  *  \throw If dimension of \a this mesh is not either 2 or 3.
1047  *
1048  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1049  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1050  */
1051 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1052 {
1053   checkFullyDefined();
1054   int dim=getMeshDimension();
1055   if(dim<2 || dim>3)
1056     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1057   int nbOfCells=getNumberOfCells();
1058   if(dim==2)
1059     {
1060       const int *connIndex=_nodal_connec_index->getConstPointer();
1061       int *conn=_nodal_connec->getPointer();
1062       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1063         {
1064           if(*iter>=0 && *iter<nbOfCells)
1065             {
1066               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1067               if(!cm.isQuadratic())
1068                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1069               else
1070                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1071             }
1072           else
1073             {
1074               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1075               oss << " in range [0," << nbOfCells << ") !";
1076               throw INTERP_KERNEL::Exception(oss.str().c_str());
1077             }
1078         }
1079     }
1080   else
1081     {
1082       int *connIndex=_nodal_connec_index->getPointer();
1083       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1084       const int *connOld=_nodal_connec->getConstPointer();
1085       int connOldLgth=_nodal_connec->getNbOfElems();
1086       std::vector<int> connNew(connOld,connOld+connOldLgth);
1087       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1088         {
1089           if(*iter>=0 && *iter<nbOfCells)
1090             {
1091               int pos=connIndex[*iter];
1092               int posP1=connIndex[(*iter)+1];
1093               int lgthOld=posP1-pos-1;
1094               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1095               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1096               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1097               int *tmp=new int[nbOfFaces*lgthOld];
1098               int *work=tmp;
1099               for(int j=0;j<(int)nbOfFaces;j++)
1100                 {
1101                   INTERP_KERNEL::NormalizedCellType type;
1102                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1103                   work+=offset;
1104                   *work++=-1;
1105                 }
1106               std::size_t newLgth=std::distance(tmp,work)-1;
1107               std::size_t delta=newLgth-lgthOld;
1108               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1109               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1110               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1111               delete [] tmp;
1112             }
1113           else
1114             {
1115               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1116               oss << " in range [0," << nbOfCells << ") !";
1117               throw INTERP_KERNEL::Exception(oss.str().c_str());
1118             }
1119         }
1120       _nodal_connec->alloc((int)connNew.size(),1);
1121       int *newConnPtr=_nodal_connec->getPointer();
1122       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1123     }
1124   computeTypes();
1125 }
1126
1127 /*!
1128  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1129  * polyhedrons (if \a this is a 3D mesh).
1130  *  \warning As this method is purely for user-friendliness and no optimization is
1131  *          done to avoid construction of a useless vector, this method can be costly
1132  *          in memory.
1133  *  \throw If the coordinates array is not set.
1134  *  \throw If the nodal connectivity of cells is node defined.
1135  *  \throw If dimension of \a this mesh is not either 2 or 3.
1136  */
1137 void MEDCouplingUMesh::convertAllToPoly()
1138 {
1139   int nbOfCells=getNumberOfCells();
1140   std::vector<int> cellIds(nbOfCells);
1141   for(int i=0;i<nbOfCells;i++)
1142     cellIds[i]=i;
1143   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1144 }
1145
1146 /*!
1147  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1148  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1149  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1150  * base facet of the volume and the second half of nodes describes an opposite facet
1151  * having the same number of nodes as the base one. This method converts such
1152  * connectivity to a valid polyhedral format where connectivity of each facet is
1153  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1154  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1155  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1156  * a correct orientation of the first facet of a polyhedron, else orientation of a
1157  * corrected cell is reverse.<br>
1158  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1159  * it releases the user from boring description of polyhedra connectivity in the valid
1160  * format.
1161  *  \throw If \a this->getMeshDimension() != 3.
1162  *  \throw If \a this->getSpaceDimension() != 3.
1163  *  \throw If the nodal connectivity of cells is not defined.
1164  *  \throw If the coordinates array is not set.
1165  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1166  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1167  *
1168  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1169  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1170  */
1171 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1172 {
1173   checkFullyDefined();
1174   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1175     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1176   int nbOfCells=getNumberOfCells();
1177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1178   newCi->alloc(nbOfCells+1,1);
1179   int *newci=newCi->getPointer();
1180   const int *ci=_nodal_connec_index->getConstPointer();
1181   const int *c=_nodal_connec->getConstPointer();
1182   newci[0]=0;
1183   for(int i=0;i<nbOfCells;i++)
1184     {
1185       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1186       if(type==INTERP_KERNEL::NORM_POLYHED)
1187         {
1188           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1189             {
1190               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1191               throw INTERP_KERNEL::Exception(oss.str().c_str());
1192             }
1193           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1194           if(n2%2!=0)
1195             {
1196               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1197               throw INTERP_KERNEL::Exception(oss.str().c_str());
1198             }
1199           int n1=(int)(n2/2);
1200           newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1201         }
1202       else
1203         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1204     }
1205   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1206   newC->alloc(newci[nbOfCells],1);
1207   int *newc=newC->getPointer();
1208   for(int i=0;i<nbOfCells;i++)
1209     {
1210       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1211       if(type==INTERP_KERNEL::NORM_POLYHED)
1212         {
1213           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1214           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1215           *newc++=-1;
1216           for(std::size_t j=0;j<n1;j++)
1217             {
1218               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1219               newc[n1+5*j]=-1;
1220               newc[n1+5*j+1]=c[ci[i]+1+j];
1221               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1222               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1223               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1224             }
1225           newc+=n1*6;
1226         }
1227       else
1228         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1229     }
1230   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1231   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1232 }
1233
1234
1235 /*!
1236  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1237  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1238  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1239  *          to write this mesh to the MED file, its cells must be sorted using
1240  *          sortCellsInMEDFileFrmt().
1241  * \return \c true if at least one cell has been converted, \c false else. In the
1242  *         last case the nodal connectivity remains unchanged.
1243  * \throw If the coordinates array is not set.
1244  * \throw If the nodal connectivity of cells is not defined.
1245  * \throw If \a this->getMeshDimension() < 0.
1246  */
1247 bool MEDCouplingUMesh::unPolyze()
1248 {
1249   checkFullyDefined();
1250   int mdim=getMeshDimension();
1251   if(mdim<0)
1252     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1253   if(mdim<=1)
1254     return false;
1255   int nbOfCells=getNumberOfCells();
1256   if(nbOfCells<1)
1257     return false;
1258   int initMeshLgth=getMeshLength();
1259   int *conn=_nodal_connec->getPointer();
1260   int *index=_nodal_connec_index->getPointer();
1261   int posOfCurCell=0;
1262   int newPos=0;
1263   int lgthOfCurCell;
1264   bool ret=false;
1265   for(int i=0;i<nbOfCells;i++)
1266     {
1267       lgthOfCurCell=index[i+1]-posOfCurCell;
1268       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1269       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1270       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1271       int newLgth;
1272       if(cm.isDynamic())
1273         {
1274           switch(cm.getDimension())
1275             {
1276             case 2:
1277               {
1278                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1279                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1280                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1281                 break;
1282               }
1283             case 3:
1284               {
1285                 int nbOfFaces,lgthOfPolyhConn;
1286                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1287                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1288                 break;
1289               }
1290             case 1:
1291               {
1292                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1293                 break;
1294               }
1295             }
1296           ret=ret || (newType!=type);
1297           conn[newPos]=newType;
1298           newPos+=newLgth+1;
1299           posOfCurCell=index[i+1];
1300           index[i+1]=newPos;
1301         }
1302       else
1303         {
1304           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1305           newPos+=lgthOfCurCell;
1306           posOfCurCell+=lgthOfCurCell;
1307           index[i+1]=newPos;
1308         }
1309     }
1310   if(newPos!=initMeshLgth)
1311     _nodal_connec->reAlloc(newPos);
1312   if(ret)
1313     computeTypes();
1314   return ret;
1315 }
1316
1317 /*!
1318  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1319  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1320  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1321  *
1322  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal 
1323  *             precision.
1324  */
1325 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1326 {
1327   checkFullyDefined();
1328   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1329     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1330   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1331   coords->recenterForMaxPrecision(eps);
1332   //
1333   int nbOfCells=getNumberOfCells();
1334   const int *conn=_nodal_connec->getConstPointer();
1335   const int *index=_nodal_connec_index->getConstPointer();
1336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1337   connINew->alloc(nbOfCells+1,1);
1338   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1340   bool changed=false;
1341   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1342     {
1343       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1344         {
1345           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1346           changed=true;
1347         }
1348       else
1349         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1350       *connINewPtr=connNew->getNumberOfTuples();
1351     }
1352   if(changed)
1353     setConnectivity(connNew,connINew,false);
1354 }
1355
1356 /*!
1357  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1358  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1359  * the format of returned DataArrayInt instance.
1360  * 
1361  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1362  * \sa MEDCouplingUMesh::getNodeIdsInUse
1363  */
1364 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1365 {
1366   checkConnectivityFullyDefined();
1367   int nbOfCells=getNumberOfCells();
1368   const int *connIndex=_nodal_connec_index->getConstPointer();
1369   const int *conn=_nodal_connec->getConstPointer();
1370   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1371   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1372   std::vector<bool> retS(maxElt,false);
1373   for(int i=0;i<nbOfCells;i++)
1374     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1375       if(conn[j]>=0)
1376         retS[conn[j]]=true;
1377   int sz=0;
1378   for(int i=0;i<maxElt;i++)
1379     if(retS[i])
1380       sz++;
1381   DataArrayInt *ret=DataArrayInt::New();
1382   ret->alloc(sz,1);
1383   int *retPtr=ret->getPointer();
1384   for(int i=0;i<maxElt;i++)
1385     if(retS[i])
1386       *retPtr++=i;
1387   return ret;
1388 }
1389
1390 /*!
1391  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1392  * \sa MEDCouplingUMesh::getNodeIdsInUse
1393  */
1394 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1395 {
1396   int nbOfNodes=(int)nodeIdsInUse.size();
1397   int nbOfCells=getNumberOfCells();
1398   const int *connIndex=_nodal_connec_index->getConstPointer();
1399   const int *conn=_nodal_connec->getConstPointer();
1400   for(int i=0;i<nbOfCells;i++)
1401     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1402       if(conn[j]>=0)
1403         {
1404           if(conn[j]<nbOfNodes)
1405             nodeIdsInUse[conn[j]]=true;
1406           else
1407             {
1408               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1409               throw INTERP_KERNEL::Exception(oss.str().c_str());
1410             }
1411         }
1412 }
1413
1414 /*!
1415  * Finds nodes not used in any cell and returns an array giving a new id to every node
1416  * by excluding the unused nodes, for which the array holds -1. The result array is
1417  * a mapping in "Old to New" mode. 
1418  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1419  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1420  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1421  *          if the node is unused or a new id else. The caller is to delete this
1422  *          array using decrRef() as it is no more needed.  
1423  *  \throw If the coordinates array is not set.
1424  *  \throw If the nodal connectivity of cells is not defined.
1425  *  \throw If the nodal connectivity includes an invalid id.
1426  *
1427  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1428  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1429  * \sa computeNodeIdsAlg()
1430  */
1431 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1432 {
1433   nbrOfNodesInUse=-1;
1434   int nbOfNodes=getNumberOfNodes();
1435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1436   ret->alloc(nbOfNodes,1);
1437   int *traducer=ret->getPointer();
1438   std::fill(traducer,traducer+nbOfNodes,-1);
1439   int nbOfCells=getNumberOfCells();
1440   const int *connIndex=_nodal_connec_index->getConstPointer();
1441   const int *conn=_nodal_connec->getConstPointer();
1442   for(int i=0;i<nbOfCells;i++)
1443     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1444       if(conn[j]>=0)
1445         {
1446           if(conn[j]<nbOfNodes)
1447             traducer[conn[j]]=1;
1448           else
1449             {
1450               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1451               throw INTERP_KERNEL::Exception(oss.str().c_str());
1452             }
1453         }
1454   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1455   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1456   return ret.retn();
1457 }
1458
1459 /*!
1460  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1461  * For each cell in \b this the number of nodes constituting cell is computed.
1462  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1463  * So for pohyhedrons some nodes can be counted several times in the returned result.
1464  * 
1465  * \return a newly allocated array
1466  */
1467 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1468 {
1469   checkConnectivityFullyDefined();
1470   int nbOfCells=getNumberOfCells();
1471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1472   ret->alloc(nbOfCells,1);
1473   int *retPtr=ret->getPointer();
1474   const int *conn=getNodalConnectivity()->getConstPointer();
1475   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1476   for(int i=0;i<nbOfCells;i++,retPtr++)
1477     {
1478       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1479         *retPtr=connI[i+1]-connI[i]-1;
1480       else
1481         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1482     }
1483   return ret.retn();
1484 }
1485
1486 /*!
1487  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1488  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1489  * 
1490  * \return a newly allocated array
1491  */
1492 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1493 {
1494   checkConnectivityFullyDefined();
1495   int nbOfCells=getNumberOfCells();
1496   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1497   ret->alloc(nbOfCells,1);
1498   int *retPtr=ret->getPointer();
1499   const int *conn=getNodalConnectivity()->getConstPointer();
1500   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1501   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1502     {
1503       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1504       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1505     }
1506   return ret.retn();
1507 }
1508
1509 /*!
1510  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1511  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1512  * array mean that the corresponding old node is no more used. 
1513  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1514  *           this->getNumberOfNodes() before call of this method. The caller is to
1515  *           delete this array using decrRef() as it is no more needed. 
1516  *  \throw If the coordinates array is not set.
1517  *  \throw If the nodal connectivity of cells is not defined.
1518  *  \throw If the nodal connectivity includes an invalid id.
1519  *
1520  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1521  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1522  */
1523 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1524 {
1525   int newNbOfNodes=-1;
1526   DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1527   renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1528   return traducer;
1529 }
1530
1531 /*!
1532  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1533  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1534  */
1535 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1536 {
1537   switch(compType)
1538     {
1539     case 0:
1540       return AreCellsEqual0(conn,connI,cell1,cell2);
1541     case 1:
1542       return AreCellsEqual1(conn,connI,cell1,cell2);
1543     case 2:
1544       return AreCellsEqual2(conn,connI,cell1,cell2);
1545     case 3:
1546       return AreCellsEqual3(conn,connI,cell1,cell2);
1547     case 7:
1548       return AreCellsEqual7(conn,connI,cell1,cell2);
1549     }
1550   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1551 }
1552
1553 /*!
1554  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1555  */
1556 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1557 {
1558   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1559     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1560   return 0;
1561 }
1562
1563 /*!
1564  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1565  */
1566 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1567 {
1568   int sz=connI[cell1+1]-connI[cell1];
1569   if(sz==connI[cell2+1]-connI[cell2])
1570     {
1571       if(conn[connI[cell1]]==conn[connI[cell2]])
1572         {
1573           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1574           unsigned dim=cm.getDimension();
1575           if(dim!=3)
1576             {
1577               if(dim!=1)
1578                 {
1579                   int sz1=2*(sz-1);
1580                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1581                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1582                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1583                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1584                   return work!=tmp+sz1?1:0;
1585                 }
1586               else
1587                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1588             }
1589           else
1590             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1591         }
1592     }
1593   return 0;
1594 }
1595
1596 /*!
1597  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1598  */
1599 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1600 {
1601   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1602     {
1603       if(conn[connI[cell1]]==conn[connI[cell2]])
1604         {
1605           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1606           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1607           return s1==s2?1:0;
1608         }
1609     }
1610   return 0;
1611 }
1612
1613 /*!
1614  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1615  */
1616 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1617 {
1618   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1619     {
1620       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1621       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1622       return s1==s2?1:0;
1623     }
1624   return 0;
1625 }
1626
1627 /*!
1628  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1629  */
1630 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1631 {
1632   int sz=connI[cell1+1]-connI[cell1];
1633   if(sz==connI[cell2+1]-connI[cell2])
1634     {
1635       if(conn[connI[cell1]]==conn[connI[cell2]])
1636         {
1637           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1638           unsigned dim=cm.getDimension();
1639           if(dim!=3)
1640             {
1641               if(dim!=1)
1642                 {
1643                   int sz1=2*(sz-1);
1644                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1645                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1646                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1647                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1648                   if(work!=tmp+sz1)
1649                     return 1;
1650                   else
1651                     {
1652                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1653                       std::reverse_iterator<int *> it2((int *)tmp);
1654                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1655                         return 2;
1656                       else
1657                         return 0;
1658                     }
1659                   
1660                   return work!=tmp+sz1?1:0;
1661                 }
1662               else
1663                 {//case of SEG2 and SEG3
1664                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1665                     return 1;
1666                   if(!cm.isQuadratic())
1667                     {
1668                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1669                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1670                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1671                         return 2;
1672                       return 0;
1673                     }
1674                   else
1675                     {
1676                       if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1677                         return 2;
1678                       return 0;
1679                     }
1680                 }
1681             }
1682           else
1683             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1684         }
1685     }
1686   return 0;
1687 }
1688
1689
1690 /*!
1691  * This method compares 2 cells coming from two unstructured meshes : \a this and \a other.
1692  * This method compares 2 cells having the same id 'cellId' in \a this and \a other.
1693  */
1694 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1695 {
1696   if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1697     return false;
1698   std::vector<int> c1,c2;
1699   getNodeIdsOfCell(cellId,c1);
1700   other->getNodeIdsOfCell(cellId,c2);
1701   std::size_t sz=c1.size();
1702   if(sz!=c2.size())
1703     return false;
1704   for(std::size_t i=0;i<sz;i++)
1705     {
1706       std::vector<double> n1,n2;
1707       getCoordinatesOfNode(c1[0],n1);
1708       other->getCoordinatesOfNode(c2[0],n2);
1709       std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1710       std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1711       if(*std::max_element(n1.begin(),n1.end())>prec)
1712         return false;
1713     }
1714   return true;
1715 }
1716
1717 /*!
1718  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1719  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1720  * and result remains unchanged.
1721  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1722  * If in 'candidates' pool -1 value is considered as an empty value.
1723  * WARNING this method returns only ONE set of result !
1724  */
1725 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1726 {
1727   if(candidates.size()<1)
1728     return false;
1729   bool ret=false;
1730   std::vector<int>::const_iterator iter=candidates.begin();
1731   int start=(*iter++);
1732   for(;iter!=candidates.end();iter++)
1733     {
1734       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1735       if(status!=0)
1736         {
1737           if(!ret)
1738             {
1739               result->pushBackSilent(start);
1740               ret=true;
1741             }
1742           if(status==1)
1743             result->pushBackSilent(*iter);
1744           else
1745             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1746         }
1747     }
1748   return ret;
1749 }
1750
1751 /*!
1752  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1753  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1754  *
1755  * \param [in] compType input specifying the technique used to compare cells each other.
1756  *   - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1757  *   - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1758  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1759  *   - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1760  * can be used for users not sensitive to orientation of cell
1761  * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1762  * \param [out] commonCells
1763  * \param [out] commonCellsI
1764  * \return the correspondance array old to new in a newly allocated array.
1765  * 
1766  */
1767 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1768 {
1769   checkConnectivityFullyDefined();
1770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1771   getReverseNodalConnectivity(revNodal,revNodalI);
1772   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1773 }
1774
1775 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1776                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1777 {
1778   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1779   int nbOfCells=nodalI->getNumberOfTuples()-1;
1780   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1781   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1782   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1783   std::vector<bool> isFetched(nbOfCells,false);
1784   if(startCellId==0)
1785     {
1786       for(int i=0;i<nbOfCells;i++)
1787         {
1788           if(!isFetched[i])
1789             {
1790               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1791               std::vector<int> v,v2;
1792               if(connOfNode!=connPtr+connIPtr[i+1])
1793                 {
1794                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1795                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1796                   connOfNode++;
1797                 }
1798               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1799                 if(*connOfNode>=0)
1800                   {
1801                     v=v2;
1802                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1803                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1804                     v2.resize(std::distance(v2.begin(),it));
1805                   }
1806               if(v2.size()>1)
1807                 {
1808                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1809                     {
1810                       int pos=commonCellsI->back();
1811                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1812                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1813                         isFetched[*it]=true;
1814                     }
1815                 }
1816             }
1817         }
1818     }
1819   else
1820     {
1821       for(int i=startCellId;i<nbOfCells;i++)
1822         {
1823           if(!isFetched[i])
1824             {
1825               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1826               std::vector<int> v,v2;
1827               if(connOfNode!=connPtr+connIPtr[i+1])
1828                 {
1829                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1830                   connOfNode++;
1831                 }
1832               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1833                 if(*connOfNode>=0)
1834                   {
1835                     v=v2;
1836                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1837                     v2.resize(std::distance(v2.begin(),it));
1838                   }
1839               if(v2.size()>1)
1840                 {
1841                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1842                     {
1843                       int pos=commonCellsI->back();
1844                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1845                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1846                         isFetched[*it]=true;
1847                     }
1848                 }
1849             }
1850         }
1851     }
1852   commonCellsArr=commonCells.retn();
1853   commonCellsIArr=commonCellsI.retn();
1854 }
1855
1856 /*!
1857  * Removes duplicates of cells from \a this mesh and returns an array mapping between
1858  * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1859  * equal cells found.
1860  *  \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1861  *           to write this mesh to the MED file, its cells must be sorted using
1862  *           sortCellsInMEDFileFrmt().
1863  *  \param [in] compType - specifies a cell comparison technique. Meaning of its
1864  *          valid values [0,1,2] is as follows.
1865  *   - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1866  *         connectivity and type. This is the strongest policy.
1867  *   - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1868  *         are based on same nodes and have the same type and orientation.
1869  *   - 2 : "nodal". Two cells are considered equal \c iff they
1870  *         are based on same nodes and have the same type. This is the weakest
1871  *         policy, it can be used by users not sensitive to cell orientation.
1872  *  \param [in] startCellId - specifies the cell id at which search for equal cells
1873  *         starts. By default it is 0, which means that all cells in \a this will be
1874  *         scanned. 
1875  *  \return DataArrayInt - a new instance of DataArrayInt, of length \a
1876  *           this->getNumberOfCells() before call of this method. The caller is to
1877  *           delete this array using decrRef() as it is no more needed. 
1878  *  \throw If the coordinates array is not set.
1879  *  \throw If the nodal connectivity of cells is not defined.
1880  *  \throw If the nodal connectivity includes an invalid id.
1881  *
1882  *  \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1883  *  \ref  py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1884  */
1885 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1886 {
1887   DataArrayInt *commonCells=0,*commonCellsI=0;
1888   findCommonCells(compType,startCellId,commonCells,commonCellsI);
1889   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1890   int newNbOfCells=-1;
1891   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1892                                                                                                           commonCellsI->end(),newNbOfCells);
1893   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1894   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1895   setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1896   return ret.retn();
1897 }
1898
1899 /*!
1900  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1901  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1902  * than \a other->getNumberOfCells() in the returned array means that there is no
1903  * corresponding cell in \a this mesh.
1904  * It is expected that \a this and \a other meshes share the same node coordinates
1905  * array, if it is not so an exception is thrown. 
1906  *  \param [in] other - the mesh to compare with.
1907  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1908  *         valid values [0,1,2], see zipConnectivityTraducer().
1909  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1910  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1911  *         values. The caller is to delete this array using
1912  *         decrRef() as it is no more needed.
1913  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1914  *         mesh.
1915  *
1916  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1917  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1918  *  \sa checkDeepEquivalOnSameNodesWith()
1919  *  \sa checkGeoEquivalWith()
1920  */
1921 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1922 {
1923   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1924   int nbOfCells=getNumberOfCells();
1925   static const int possibleCompType[]={0,1,2};
1926   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1927     {
1928       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1929       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1930       oss << " !";
1931       throw INTERP_KERNEL::Exception(oss.str().c_str());
1932     }
1933   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1934   arr=o2n->substr(nbOfCells);
1935   arr->setName(other->getName());
1936   int tmp;
1937   if(other->getNumberOfCells()==0)
1938     return true;
1939   return arr->getMaxValue(tmp)<nbOfCells;
1940 }
1941
1942 /*!
1943  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1944  * This method tries to determine if \b other is fully included in \b this.
1945  * The main difference is that this method is not expected to throw exception.
1946  * This method has two outputs :
1947  *
1948  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1949  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1950  */
1951 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1952 {
1953   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1954   DataArrayInt *commonCells=0,*commonCellsI=0;
1955   int thisNbCells=getNumberOfCells();
1956   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1957   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1958   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1959   int otherNbCells=other->getNumberOfCells();
1960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1961   arr2->alloc(otherNbCells,1);
1962   arr2->fillWithZero();
1963   int *arr2Ptr=arr2->getPointer();
1964   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1965   for(int i=0;i<nbOfCommon;i++)
1966     {
1967       int start=commonCellsPtr[commonCellsIPtr[i]];
1968       if(start<thisNbCells)
1969         {
1970           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1971             {
1972               int sig=commonCellsPtr[j]>0?1:-1;
1973               int val=std::abs(commonCellsPtr[j])-1;
1974               if(val>=thisNbCells)
1975                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1976             }
1977         }
1978     }
1979   arr2->setName(other->getName());
1980   if(arr2->presenceOfValue(0))
1981     return false;
1982   arr=arr2.retn();
1983   return true;
1984 }
1985
1986 /*!
1987  * Merges nodes equal within \a precision and returns an array describing the 
1988  * permutation used to remove duplicate nodes.
1989  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1990  *              considered not coincident.
1991  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1992  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1993  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1994  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1995  *          is to delete this array using decrRef() as it is no more needed.
1996  *  \throw If the coordinates array is not set.
1997  *  \throw If the nodal connectivity of cells is not defined.
1998  *
1999  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
2000  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
2001  */
2002 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
2003 {
2004   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2005   if(areNodesMerged)
2006     renumberNodes(ret->getConstPointer(),newNbOfNodes);
2007   return ret;
2008 }
2009
2010
2011 /*!
2012  * Merges nodes equal within \a precision and returns an array describing the 
2013  * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
2014  *  of merged nodes is changed to be at their barycenter.
2015  *  \param [in] precision - minimal absolute distance between two nodes at which they are
2016  *              considered not coincident.
2017  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
2018  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
2019  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
2020  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
2021  *          is to delete this array using decrRef() as it is no more needed.
2022  *  \throw If the coordinates array is not set.
2023  *  \throw If the nodal connectivity of cells is not defined.
2024  *
2025  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
2026  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
2027  */
2028 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
2029 {
2030   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2031   if(areNodesMerged)
2032     renumberNodes2(ret->getConstPointer(),newNbOfNodes);
2033   return ret;
2034 }
2035
2036 /*!
2037  * Substitutes node coordinates array of \a this mesh with that of \a other mesh
2038  * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
2039  * meshes match with a specified precision, else an exception is thrown and \a this
2040  * remains unchanged. In case of success the nodal connectivity of \a this mesh
2041  * is permuted according to new order of nodes.
2042  * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
2043  * coordinates (and so more expensive) than simple equality.
2044  *  \param [in] other - the other mesh whose node coordinates array will be used by
2045  *         \a this mesh in case of their equality.
2046  *  \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
2047  *  \throw If the coordinates array of \a this is not set.
2048  *  \throw If the coordinates array of \a other is not set.
2049  *  \throw If the coordinates of \a this and \a other do not match.
2050  */
2051 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
2052 {
2053   const DataArrayDouble *coords=other.getCoords();
2054   if(!coords)
2055     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
2056   if(!_coords)
2057     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
2058   int otherNbOfNodes=other.getNumberOfNodes();
2059   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
2060   _coords->incrRef();
2061   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
2062   setCoords(newCoords);
2063   bool areNodesMerged;
2064   int newNbOfNodes;
2065   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
2066   if(!areNodesMerged)
2067     {
2068       setCoords(oldCoords);
2069       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
2070     }
2071   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
2072   const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
2073   if(pt!=da->getConstPointer()+da->getNbOfElems())
2074     {
2075       setCoords(oldCoords);
2076       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
2077     }
2078   setCoords(oldCoords);
2079   renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
2080   setCoords(coords);
2081 }
2082
2083 /*!
2084  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2085  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2086  * cellIds is not given explicitely but by a range python like.
2087  * 
2088  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2089  * \return a newly allocated
2090  * 
2091  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2092  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2093  */
2094 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
2095 {
2096   if(getMeshDimension()!=-1)
2097     {
2098       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
2099       if(!keepCoords)
2100         ret->zipCoords();
2101       return ret;
2102     }
2103   else
2104     {
2105       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2106       if(newNbOfCells!=1)
2107         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2108       if(start!=0)
2109         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2110       incrRef();
2111       return const_cast<MEDCouplingUMesh *>(this);
2112     }
2113 }
2114
2115 /*!
2116  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2117  * The result mesh shares or not the node coordinates array with \a this mesh depending
2118  * on \a keepCoords parameter.
2119  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2120  *           to write this mesh to the MED file, its cells must be sorted using
2121  *           sortCellsInMEDFileFrmt().
2122  *  \param [in] begin - an array of cell ids to include to the new mesh.
2123  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2124  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2125  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2126  *         by calling zipCoords().
2127  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2128  *         to delete this mesh using decrRef() as it is no more needed. 
2129  *  \throw If the coordinates array is not set.
2130  *  \throw If the nodal connectivity of cells is not defined.
2131  *  \throw If any cell id in the array \a begin is not valid.
2132  *
2133  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2134  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2135  */
2136 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2137 {
2138   if(getMeshDimension()!=-1)
2139     {
2140       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
2141       if(!keepCoords)
2142         ret->zipCoords();
2143       return ret;
2144     }
2145   else
2146     {
2147       if(end-begin!=1)
2148         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2149       if(begin[0]!=0)
2150         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2151       incrRef();
2152       return const_cast<MEDCouplingUMesh *>(this);
2153     }
2154 }
2155
2156 /*!
2157  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2158  *
2159  * This method allows to partially modify some cells in \b this (whose list is specified by [\b cellIdsBg, \b cellIdsEnd) ) with cells coming in \b otherOnSameCoordsThanThis.
2160  * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2161  * The number of cells of \b this will remain the same with this method.
2162  *
2163  * \param [in] begin begin of cell ids (included) of cells in this to assign
2164  * \param [in] end end of cell ids (excluded) of cells in this to assign
2165  * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd).
2166  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2167  */
2168 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2169 {
2170   checkConnectivityFullyDefined();
2171   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2172   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2173     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2174   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2175     {
2176       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2177       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2178       throw INTERP_KERNEL::Exception(oss.str().c_str());
2179     }
2180   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2181   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2182     {
2183       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2184       throw INTERP_KERNEL::Exception(oss.str().c_str());
2185     }
2186   int nbOfCells=getNumberOfCells();
2187   bool easyAssign=true;
2188   const int *connI=_nodal_connec_index->getConstPointer();
2189   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2190   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2191     {
2192       if(*it>=0 && *it<nbOfCells)
2193         {
2194           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2195         }
2196       else
2197         {
2198           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2199           throw INTERP_KERNEL::Exception(oss.str().c_str());
2200         }
2201     }
2202   if(easyAssign)
2203     {
2204       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2205       computeTypes();
2206     }
2207   else
2208     {
2209       DataArrayInt *arrOut=0,*arrIOut=0;
2210       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2211                                                arrOut,arrIOut);
2212       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2213       setConnectivity(arrOut,arrIOut,true);
2214     }
2215 }
2216
2217 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2218 {
2219   checkConnectivityFullyDefined();
2220   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2221   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2222     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2223   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2224     {
2225       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2226       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2227       throw INTERP_KERNEL::Exception(oss.str().c_str());
2228     }
2229   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2230   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2231     {
2232       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2233       throw INTERP_KERNEL::Exception(oss.str().c_str());
2234     }
2235   int nbOfCells=getNumberOfCells();
2236   bool easyAssign=true;
2237   const int *connI=_nodal_connec_index->getConstPointer();
2238   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2239   int it=start;
2240   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2241     {
2242       if(it>=0 && it<nbOfCells)
2243         {
2244           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2245         }
2246       else
2247         {
2248           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2249           throw INTERP_KERNEL::Exception(oss.str().c_str());
2250         }
2251     }
2252   if(easyAssign)
2253     {
2254       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2255       computeTypes();
2256     }
2257   else
2258     {
2259       DataArrayInt *arrOut=0,*arrIOut=0;
2260       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2261                                                 arrOut,arrIOut);
2262       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2263       setConnectivity(arrOut,arrIOut,true);
2264     }
2265 }                      
2266
2267 /*!
2268  * Finds cells whose all nodes are in a given array of node ids.
2269  *  \param [in] partBg - the array of node ids.
2270  *  \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2271  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2272  *          cells. The caller is to delete this array using decrRef() as it is no
2273  *          more needed.
2274  *  \throw If the coordinates array is not set.
2275  *  \throw If the nodal connectivity of cells is not defined.
2276  *  \throw If any cell id in \a partBg is not valid.
2277  *
2278  *  \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2279  *  \ref  py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2280  */
2281 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2282 {
2283   DataArrayInt *cellIdsKept=0;
2284   fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2285   cellIdsKept->setName(getName());
2286   return cellIdsKept;
2287 }
2288
2289 /*!
2290  * Keeps from \a this only cells which constituing point id are in the ids specified by ['begin','end').
2291  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2292  * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2293  * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2294  *
2295  * \param [in] begin input start of array of node ids.
2296  * \param [in] end input end of array of node ids.
2297  * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
2298  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2299  */
2300 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2301 {
2302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2303   checkConnectivityFullyDefined();
2304   int tmp=-1;
2305   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2306   std::vector<bool> fastFinder(sz,false);
2307   for(const int *work=begin;work!=end;work++)
2308     if(*work>=0 && *work<sz)
2309       fastFinder[*work]=true;
2310   int nbOfCells=getNumberOfCells();
2311   const int *conn=getNodalConnectivity()->getConstPointer();
2312   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2313   for(int i=0;i<nbOfCells;i++)
2314     {
2315       int ref=0,nbOfHit=0;
2316       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2317         if(*work2>=0)
2318           {
2319             ref++;
2320             if(fastFinder[*work2])
2321               nbOfHit++;
2322           }
2323       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2324         cellIdsKept->pushBackSilent(i);
2325     }
2326   cellIdsKeptArr=cellIdsKept.retn();
2327 }
2328
2329 /*!
2330  * Finds cells whose all or some nodes are in a given array of node ids.
2331  *  \param [in] begin - the array of node ids.
2332  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2333  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2334  *         array \a begin are returned only, else cells whose any node is in the
2335  *         array \a begin are returned.
2336  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2337  *         cells. The caller is to delete this array using decrRef() as it is no more
2338  *         needed. 
2339  *  \throw If the coordinates array is not set.
2340  *  \throw If the nodal connectivity of cells is not defined.
2341  *  \throw If any cell id in \a begin is not valid.
2342  *
2343  *  \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2344  *  \ref  py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2345  */
2346 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2347 {
2348   DataArrayInt *cellIdsKept=0;
2349   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2350   cellIdsKept->setName(getName());
2351   return cellIdsKept;
2352 }
2353
2354 /*!
2355  Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
2356  copy are selected basing on specified node ids and the value of \a fullyIn
2357  parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the 
2358  array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
2359  node is in the array of node ids. The created mesh shares the node coordinates array
2360  with \a this mesh.
2361  *  \param [in] begin - the array of node ids.
2362  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2363  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2364  *         array \a begin are copied, else cells whose any node is in the
2365  *         array \a begin are copied.
2366  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2367  *         to delete this mesh using decrRef() as it is no more needed. 
2368  *  \throw If the coordinates array is not set.
2369  *  \throw If the nodal connectivity of cells is not defined.
2370  *  \throw If any node id in \a begin is not valid.
2371  *
2372  *  \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
2373  *  \ref  py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
2374  */
2375 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2376 {
2377   DataArrayInt *cellIdsKept=0;
2378   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2380   return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2381 }
2382
2383 /*!
2384  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2385  * this->getMeshDimension(), that bound some cells of \a this mesh.
2386  * The cells of lower dimension to include to the result mesh are selected basing on
2387  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2388  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2389  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2390  * created mesh shares the node coordinates array with \a this mesh. 
2391  *  \param [in] begin - the array of node ids.
2392  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2393  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2394  *         array \a begin are added, else cells whose any node is in the
2395  *         array \a begin are added.
2396  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2397  *         to delete this mesh using decrRef() as it is no more needed. 
2398  *  \throw If the coordinates array is not set.
2399  *  \throw If the nodal connectivity of cells is not defined.
2400  *  \throw If any node id in \a begin is not valid.
2401  *
2402  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2403  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2404  */
2405 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2406 {
2407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2408   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2409   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2410   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2411   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2412 }
2413
2414 /*!
2415  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2416  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2417  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2418  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2419  *         by calling zipCoords().
2420  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2421  *         to delete this mesh using decrRef() as it is no more needed. 
2422  *  \throw If the coordinates array is not set.
2423  *  \throw If the nodal connectivity of cells is not defined.
2424  *
2425  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2426  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2427  */
2428 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2429 {
2430   DataArrayInt *desc=DataArrayInt::New();
2431   DataArrayInt *descIndx=DataArrayInt::New();
2432   DataArrayInt *revDesc=DataArrayInt::New();
2433   DataArrayInt *revDescIndx=DataArrayInt::New();
2434   //
2435   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2436   revDesc->decrRef();
2437   desc->decrRef();
2438   descIndx->decrRef();
2439   int nbOfCells=meshDM1->getNumberOfCells();
2440   const int *revDescIndxC=revDescIndx->getConstPointer();
2441   std::vector<int> boundaryCells;
2442   for(int i=0;i<nbOfCells;i++)
2443     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2444       boundaryCells.push_back(i);
2445   revDescIndx->decrRef();
2446   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2447   return ret;
2448 }
2449
2450 /*!
2451  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2452  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2453  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2454  */
2455 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2456 {
2457   checkFullyDefined();
2458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2462   //
2463   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2464   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2465   //
2466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2467   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2468   const int *revDescPtr=revDesc->getConstPointer();
2469   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2470   int nbOfCells=getNumberOfCells();
2471   std::vector<bool> ret1(nbOfCells,false);
2472   int sz=0;
2473   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2474     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2475       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2476   //
2477   DataArrayInt *ret2=DataArrayInt::New();
2478   ret2->alloc(sz,1);
2479   int *ret2Ptr=ret2->getPointer();
2480   sz=0;
2481   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2482     if(*it)
2483       *ret2Ptr++=sz;
2484   ret2->setName("BoundaryCells");
2485   return ret2;
2486 }
2487
2488 /*!
2489  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2490  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2491  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2492  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2493  *
2494  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2495  * This method method returns cells ids set s = s1 + s2 where :
2496  * 
2497  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2498  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2499  *
2500  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2501  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2502  *
2503  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2504  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2505  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2506  */
2507 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2508 {
2509   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2510     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2511   checkConnectivityFullyDefined();
2512   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2513   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2514     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2516   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2517   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2519   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2520   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2521   DataArrayInt *idsOtherInConsti=0;
2522   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2524   if(!b)
2525     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2526   std::set<int> s1;
2527   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2528     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2529   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2530   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2531   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2532   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2533   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2534   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2535   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2536   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2537   neighThisPartAuto=0;
2538   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2539   const int li[2]={0,1};
2540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2541   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2542   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2543   s_renum1->sort();
2544   //
2545   cellIdsRk0=s0arr.retn();
2546   cellIdsRk1=s_renum1.retn();
2547 }
2548
2549 /*!
2550  * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2551  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2552  * 
2553  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2554  */
2555 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2556 {
2557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2561   //
2562   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2563   revDesc=0; desc=0; descIndx=0;
2564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2565   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2566   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2567 }
2568
2569 /*!
2570  * Finds nodes lying on the boundary of \a this mesh.
2571  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2572  *          nodes. The caller is to delete this array using decrRef() as it is no
2573  *          more needed.
2574  *  \throw If the coordinates array is not set.
2575  *  \throw If the nodal connectivity of cells is node defined.
2576  *
2577  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2578  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2579  */
2580 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2581 {
2582   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2583   return skin->computeFetchedNodeIds();
2584 }
2585
2586 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2587 {
2588   incrRef();
2589   return const_cast<MEDCouplingUMesh *>(this);
2590 }
2591
2592 /*!
2593  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2594  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
2595  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2596  * array is modified accordingly.
2597  *  \param [in] newNodeNumbers - a permutation array, of length \a
2598  *         this->getNumberOfNodes(), in "Old to New" mode. 
2599  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2600  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering.
2601  *  \throw If the coordinates array is not set.
2602  *  \throw If the nodal connectivity of cells is not defined.
2603  *
2604  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2605  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
2606  */
2607 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2608 {
2609   MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2610   renumberNodesInConn(newNodeNumbers);
2611 }
2612
2613 /*!
2614  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2615  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
2616  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2617  * array is modified accordingly. In contrast to renumberNodes(), location
2618  * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
2619  *  \param [in] newNodeNumbers - a permutation array, of length \a
2620  *         this->getNumberOfNodes(), in "Old to New" mode. 
2621  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2622  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
2623  *         actually one more than the maximal id in \a newNodeNumbers.
2624  *  \throw If the coordinates array is not set.
2625  *  \throw If the nodal connectivity of cells is not defined.
2626  *
2627  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2628  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
2629  */
2630 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2631 {
2632   MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2633   renumberNodesInConn(newNodeNumbers);
2634 }
2635
2636 /*!
2637  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2638  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2639  * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2640  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2641  * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2642  *
2643  * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2644  *             parameter is altered during the call.
2645  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2646  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2647  * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2648  *
2649  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2650  */
2651 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2652                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2653 {
2654   checkFullyDefined();
2655   otherDimM1OnSameCoords.checkFullyDefined();
2656   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2657     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2658   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2659     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2660   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2661   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2662   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2664   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2665   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2669   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2670   //
2671   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2672   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2673   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2674   DataArrayInt *idsTmp=0;
2675   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2676   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2677   if(!b)
2678     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2679   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2680   DataArrayInt *tmp0=0,*tmp1=0;
2681   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2682   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2683   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2686   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2687   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2688   //
2689   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2690   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2691   nodeIdsToDuplicate=s3.retn();
2692 }
2693
2694 /*!
2695  * This method operates a modification of the connectivity and coords in \b this.
2696  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2697  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2698  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2699  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2700  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2701  * 
2702  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2703  * 
2704  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2705  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2706  */
2707 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2708 {
2709   int nbOfNodes=getNumberOfNodes();
2710   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2711   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2712 }
2713
2714 /*!
2715  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2716  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2717  * This method is a generalization of shiftNodeNumbersInConn().
2718  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2719  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2720  *         this->getNumberOfNodes(), in "Old to New" mode. 
2721  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2722  *  \throw If the nodal connectivity of cells is not defined.
2723  *
2724  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2725  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2726  */
2727 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2728 {
2729   checkConnectivityFullyDefined();
2730   int *conn=getNodalConnectivity()->getPointer();
2731   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2732   int nbOfCells=getNumberOfCells();
2733   for(int i=0;i<nbOfCells;i++)
2734     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2735       {
2736         int& node=conn[iconn];
2737         if(node>=0)//avoid polyhedron separator
2738           {
2739             node=newNodeNumbersO2N[node];
2740           }
2741       }
2742   _nodal_connec->declareAsNew();
2743   updateTime();
2744 }
2745
2746 /*!
2747  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2748  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2749  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2750  * 
2751  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2752  */
2753 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2754 {
2755   checkConnectivityFullyDefined();
2756   int *conn=getNodalConnectivity()->getPointer();
2757   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2758   int nbOfCells=getNumberOfCells();
2759   for(int i=0;i<nbOfCells;i++)
2760     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2761       {
2762         int& node=conn[iconn];
2763         if(node>=0)//avoid polyhedron separator
2764           {
2765             node+=delta;
2766           }
2767       }
2768   _nodal_connec->declareAsNew();
2769   updateTime();
2770 }
2771
2772 /*!
2773  * This method operates a modification of the connectivity in \b this.
2774  * Coordinates are \b NOT considered here and will remain unchanged by this method. this->_coords can ever been null for the needs of this method.
2775  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2776  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2777  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2778  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2779  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2780  * 
2781  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2782  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2783  * 
2784  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2785  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2786  * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd). 
2787  */
2788 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2789 {
2790   checkConnectivityFullyDefined();
2791   std::map<int,int> m;
2792   int val=offset;
2793   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2794     m[*work]=val;
2795   int *conn=getNodalConnectivity()->getPointer();
2796   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2797   int nbOfCells=getNumberOfCells();
2798   for(int i=0;i<nbOfCells;i++)
2799     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2800       {
2801         int& node=conn[iconn];
2802         if(node>=0)//avoid polyhedron separator
2803           {
2804             std::map<int,int>::iterator it=m.find(node);
2805             if(it!=m.end())
2806               node=(*it).second;
2807           }
2808       }
2809   updateTime();
2810 }
2811
2812 /*!
2813  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2814  *
2815  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2816  * After the call of this method the number of cells remains the same as before.
2817  *
2818  * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2819  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2820  * be strictly in [0;this->getNumberOfCells()).
2821  *
2822  * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2823  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2824  * should be contained in[0;this->getNumberOfCells()).
2825  * 
2826  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2827  */
2828 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2829 {
2830   checkConnectivityFullyDefined();
2831   int nbCells=getNumberOfCells();
2832   const int *array=old2NewBg;
2833   if(check)
2834     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2835   //
2836   const int *conn=_nodal_connec->getConstPointer();
2837   const int *connI=_nodal_connec_index->getConstPointer();
2838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2840   const int *n2oPtr=n2o->begin();
2841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2842   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2843   newConn->copyStringInfoFrom(*_nodal_connec);
2844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2845   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2846   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2847   //
2848   int *newC=newConn->getPointer();
2849   int *newCI=newConnI->getPointer();
2850   int loc=0;
2851   newCI[0]=loc;
2852   for(int i=0;i<nbCells;i++)
2853     {
2854       int pos=n2oPtr[i];
2855       int nbOfElts=connI[pos+1]-connI[pos];
2856       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2857       loc+=nbOfElts;
2858       newCI[i+1]=loc;
2859     }
2860   //
2861   setConnectivity(newConn,newConnI);
2862   if(check)
2863     free(const_cast<int *>(array));
2864 }
2865
2866 /*!
2867  * Finds cells whose bounding boxes intersect a given bounding box.
2868  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2869  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2870  *         zMax (if in 3D). 
2871  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2872  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2873  *         extent of the bounding box of cell to produce an addition to this bounding box.
2874  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2875  *         cells. The caller is to delete this array using decrRef() as it is no more
2876  *         needed. 
2877  *  \throw If the coordinates array is not set.
2878  *  \throw If the nodal connectivity of cells is not defined.
2879  *
2880  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2881  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2882  */
2883 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2884 {
2885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2886   if(getMeshDimension()==-1)
2887     {
2888       elems->pushBackSilent(0);
2889       return elems.retn();
2890     }
2891   int dim=getSpaceDimension();
2892   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2893   const int* conn      = getNodalConnectivity()->getConstPointer();
2894   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2895   const double* coords = getCoords()->getConstPointer();
2896   int nbOfCells=getNumberOfCells();
2897   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2898     {
2899       for (int i=0; i<dim; i++)
2900         {
2901           elem_bb[i*2]=std::numeric_limits<double>::max();
2902           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2903         }
2904
2905       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2906         {
2907           int node= conn[inode];
2908           if(node>=0)//avoid polyhedron separator
2909             {
2910               for (int idim=0; idim<dim; idim++)
2911                 {
2912                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2913                     {
2914                       elem_bb[idim*2] = coords[node*dim+idim] ;
2915                     }
2916                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2917                     {
2918                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2919                     }
2920                 }
2921             }
2922         }
2923       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2924         elems->pushBackSilent(ielem);
2925     }
2926   return elems.retn();
2927 }
2928
2929 /*!
2930  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2931  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2932  * added in 'elems' parameter.
2933  */
2934 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2935 {
2936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2937   if(getMeshDimension()==-1)
2938     {
2939       elems->pushBackSilent(0);
2940       return elems.retn();
2941     }
2942   int dim=getSpaceDimension();
2943   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2944   const int* conn      = getNodalConnectivity()->getConstPointer();
2945   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2946   const double* coords = getCoords()->getConstPointer();
2947   int nbOfCells=getNumberOfCells();
2948   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2949     {
2950       for (int i=0; i<dim; i++)
2951         {
2952           elem_bb[i*2]=std::numeric_limits<double>::max();
2953           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2954         }
2955
2956       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2957         {
2958           int node= conn[inode];
2959           if(node>=0)//avoid polyhedron separator
2960             {
2961               for (int idim=0; idim<dim; idim++)
2962                 {
2963                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2964                     {
2965                       elem_bb[idim*2] = coords[node*dim+idim] ;
2966                     }
2967                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2968                     {
2969                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2970                     }
2971                 }
2972             }
2973         }
2974       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2975         elems->pushBackSilent(ielem);
2976     }
2977   return elems.retn();
2978 }
2979
2980 /*!
2981  * Returns a type of a cell by its id.
2982  *  \param [in] cellId - the id of the cell of interest.
2983  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2984  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2985  */
2986 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2987 {
2988   const int *ptI=_nodal_connec_index->getConstPointer();
2989   const int *pt=_nodal_connec->getConstPointer();
2990   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2991     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2992   else
2993     {
2994       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2995       throw INTERP_KERNEL::Exception(oss.str().c_str());
2996     }
2997 }
2998
2999 /*!
3000  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
3001  * This method does not throw exception if geometric type \a type is not in \a this.
3002  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
3003  * The coordinates array is not considered here.
3004  *
3005  * \param [in] type the geometric type
3006  * \return cell ids in this having geometric type \a type.
3007  */
3008 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
3009 {
3010   
3011   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
3012   ret->alloc(0,1);
3013   checkConnectivityFullyDefined();
3014   int nbCells=getNumberOfCells();
3015   int mdim=getMeshDimension();
3016   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
3017   if(mdim!=(int)cm.getDimension())
3018     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
3019   const int *ptI=_nodal_connec_index->getConstPointer();
3020   const int *pt=_nodal_connec->getConstPointer();
3021   for(int i=0;i<nbCells;i++)
3022     {
3023       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
3024         ret->pushBackSilent(i);
3025     }
3026   return ret.retn();
3027 }
3028
3029 /*!
3030  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
3031  */
3032 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
3033 {
3034   const int *ptI=_nodal_connec_index->getConstPointer();
3035   const int *pt=_nodal_connec->getConstPointer();
3036   int nbOfCells=getNumberOfCells();
3037   int ret=0;
3038   for(int i=0;i<nbOfCells;i++)
3039     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3040       ret++;
3041   return ret;
3042 }
3043
3044 /*!
3045  * Returns the nodal connectivity of a given cell.
3046  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3047  * all returned node ids can be used in getCoordinatesOfNode().
3048  *  \param [in] cellId - an id of the cell of interest.
3049  *  \param [in,out] conn - a vector where the node ids are appended. It is not
3050  *         cleared before the appending.
3051  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3052  */
3053 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3054 {
3055   const int *ptI=_nodal_connec_index->getConstPointer();
3056   const int *pt=_nodal_connec->getConstPointer();
3057   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3058     if(*w>=0)
3059       conn.push_back(*w);
3060 }
3061
3062 std::string MEDCouplingUMesh::simpleRepr() const
3063 {
3064   static const char msg0[]="No coordinates specified !";
3065   std::ostringstream ret;
3066   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3067   ret << "Description of mesh : \"" << getDescription() << "\"\n";
3068   int tmpp1,tmpp2;
3069   double tt=getTime(tmpp1,tmpp2);
3070   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3071   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
3072   if(_mesh_dim>=-1)
3073     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3074   else
3075     { ret << " Mesh dimension has not been set or is invalid !"; }
3076   if(_coords!=0)
3077     {
3078       const int spaceDim=getSpaceDimension();
3079       ret << spaceDim << "\nInfo attached on space dimension : ";
3080       for(int i=0;i<spaceDim;i++)
3081         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3082       ret << "\n";
3083     }
3084   else
3085     ret << msg0 << "\n";
3086   ret << "Number of nodes : ";
3087   if(_coords!=0)
3088     ret << getNumberOfNodes() << "\n";
3089   else
3090     ret << msg0 << "\n";
3091   ret << "Number of cells : ";
3092   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3093     ret << getNumberOfCells() << "\n";
3094   else
3095     ret << "No connectivity specified !" << "\n";
3096   ret << "Cell types present : ";
3097   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3098     {
3099       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3100       ret << cm.getRepr() << " ";
3101     }
3102   ret << "\n";
3103   return ret.str();
3104 }
3105
3106 std::string MEDCouplingUMesh::advancedRepr() const
3107 {
3108   std::ostringstream ret;
3109   ret << simpleRepr();
3110   ret << "\nCoordinates array : \n___________________\n\n";
3111   if(_coords)
3112     _coords->reprWithoutNameStream(ret);
3113   else
3114     ret << "No array set !\n";
3115   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3116   reprConnectivityOfThisLL(ret);
3117   return ret.str();
3118 }
3119
3120 /*!
3121  * This method returns a C++ code that is a dump of \a this.
3122  * This method will throw if this is not fully defined.
3123  */
3124 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
3125 {
3126   static const char coordsName[]="coords";
3127   static const char connName[]="conn";
3128   static const char connIName[]="connI";
3129   checkFullyDefined();
3130   std::ostringstream ret; ret << "// coordinates" << std::endl;
3131   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3132   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3133   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3134   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3135   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3136   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3137   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3138   return ret.str();
3139 }
3140
3141 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3142 {
3143   std::ostringstream ret;
3144   reprConnectivityOfThisLL(ret);
3145   return ret.str();
3146 }
3147
3148 /*!
3149  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3150  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3151  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3152  * some algos).
3153  * 
3154  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3155  * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
3156  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3157  */
3158 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
3159 {
3160   int mdim=getMeshDimension();
3161   if(mdim<0)
3162     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3163   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3164   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3165   bool needToCpyCT=true;
3166   if(!_nodal_connec)
3167     {
3168       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3169       needToCpyCT=false;
3170     }
3171   else
3172     {
3173       tmp1=_nodal_connec;
3174       tmp1->incrRef();
3175     }
3176   if(!_nodal_connec_index)
3177     {
3178       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3179       needToCpyCT=false;
3180     }
3181   else
3182     {
3183       tmp2=_nodal_connec_index;
3184       tmp2->incrRef();
3185     }
3186   ret->setConnectivity(tmp1,tmp2,false);
3187   if(needToCpyCT)
3188     ret->_types=_types;
3189   if(!_coords)
3190     {
3191       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3192       ret->setCoords(coords);
3193     }
3194   else
3195     ret->setCoords(_coords);
3196   return ret.retn();
3197 }
3198
3199 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3200 {
3201   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3202     {
3203       int nbOfCells=getNumberOfCells();
3204       const int *c=_nodal_connec->getConstPointer();
3205       const int *ci=_nodal_connec_index->getConstPointer();
3206       for(int i=0;i<nbOfCells;i++)
3207         {
3208           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3209           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3210           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3211           stream << "\n";
3212         }
3213     }
3214   else
3215     stream << "Connectivity not defined !\n";
3216 }
3217
3218 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3219 {
3220   const int *ptI=_nodal_connec_index->getConstPointer();
3221   const int *pt=_nodal_connec->getConstPointer();
3222   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3223     return ptI[cellId+1]-ptI[cellId]-1;
3224   else
3225     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3226 }
3227
3228 /*!
3229  * Returns types of cells of the specified part of \a this mesh.
3230  * This method avoids computing sub-mesh explicitely to get its types.
3231  *  \param [in] begin - an array of cell ids of interest.
3232  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3233  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3234  *         describing the cell types. 
3235  *  \throw If the coordinates array is not set.
3236  *  \throw If the nodal connectivity of cells is not defined.
3237  *  \sa getAllTypes()
3238  */
3239 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
3240 {
3241   checkFullyDefined();
3242   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3243   const int *conn=_nodal_connec->getConstPointer();
3244   const int *connIndex=_nodal_connec_index->getConstPointer();
3245   for(const int *w=begin;w!=end;w++)
3246     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3247   return ret;
3248 }
3249
3250 /*!
3251  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3252  * a set of types of cells constituting \a this mesh. 
3253  * This method is for advanced users having prepared their connectivity before. For
3254  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3255  *  \param [in] conn - the nodal connectivity array. 
3256  *  \param [in] connIndex - the nodal connectivity index array.
3257  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3258  *         mesh is updated.
3259  */
3260 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3261 {
3262   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3263   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3264   if(isComputingTypes)
3265     computeTypes();
3266   declareAsNew();
3267 }
3268
3269 /*!
3270  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3271  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3272  */
3273 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3274                                                                                  _nodal_connec(0),_nodal_connec_index(0),
3275                                                                                 _types(other._types)
3276 {
3277   if(other._nodal_connec)
3278     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3279   if(other._nodal_connec_index)
3280     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3281 }
3282
3283 MEDCouplingUMesh::~MEDCouplingUMesh()
3284 {
3285   if(_nodal_connec)
3286     _nodal_connec->decrRef();
3287   if(_nodal_connec_index)
3288     _nodal_connec_index->decrRef();
3289 }
3290
3291 /*!
3292  * Recomputes a set of cell types of \a this mesh. For more info see
3293  * \ref MEDCouplingUMeshNodalConnectivity.
3294  */
3295 void MEDCouplingUMesh::computeTypes()
3296 {
3297   if(_nodal_connec && _nodal_connec_index)
3298     {
3299       _types.clear();
3300       const int *conn=_nodal_connec->getConstPointer();
3301       const int *connIndex=_nodal_connec_index->getConstPointer();
3302       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3303       if (nbOfElem > 0)
3304         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3305           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3306     }
3307 }
3308
3309 /*!
3310  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3311  */
3312 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3313 {
3314   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3315     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3316 }
3317
3318 /*!
3319  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3320  */
3321 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3322 {
3323   if(!_nodal_connec_index || !_nodal_connec)
3324     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3325 }
3326
3327 /*!
3328  * Returns a number of cells constituting \a this mesh. 
3329  *  \return int - the number of cells in \a this mesh.
3330  *  \throw If the nodal connectivity of cells is not defined.
3331  */
3332 int MEDCouplingUMesh::getNumberOfCells() const
3333
3334   if(_nodal_connec_index)
3335     return _nodal_connec_index->getNumberOfTuples()-1;
3336   else
3337     if(_mesh_dim==-1)
3338       return 1;
3339     else
3340       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3341 }
3342
3343 /*!
3344  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3345  * mesh. For more info see \ref MEDCouplingMeshesPage.
3346  *  \return int - the dimension of \a this mesh.
3347  *  \throw If the mesh dimension is not defined using setMeshDimension().
3348  */
3349 int MEDCouplingUMesh::getMeshDimension() const
3350 {
3351   if(_mesh_dim<-1)
3352     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3353   return _mesh_dim;
3354 }
3355
3356 /*!
3357  * Returns a length of the nodal connectivity array.
3358  * This method is for test reason. Normally the integer returned is not useable by
3359  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3360  *  \return int - the length of the nodal connectivity array.
3361  */
3362 int MEDCouplingUMesh::getMeshLength() const
3363 {
3364   return _nodal_connec->getNbOfElems();
3365 }
3366
3367 /*!
3368  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3369  */
3370 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3371 {
3372   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3373   tinyInfo.push_back(getMeshDimension());
3374   tinyInfo.push_back(getNumberOfCells());
3375   if(_nodal_connec)
3376     tinyInfo.push_back(getMeshLength());
3377   else
3378     tinyInfo.push_back(-1);
3379 }
3380
3381 /*!
3382  * First step of unserialization process.
3383  */
3384 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3385 {
3386   return tinyInfo[6]<=0;
3387 }
3388
3389 /*!
3390  * Second step of serialization process.
3391  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3392  */
3393 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3394 {
3395   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3396   if(tinyInfo[5]!=-1)
3397     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3398 }
3399
3400 /*!
3401  * Third and final step of serialization process.
3402  */
3403 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3404 {
3405   MEDCouplingPointSet::serialize(a1,a2);
3406   if(getMeshDimension()>-1)
3407     {
3408       a1=DataArrayInt::New();
3409       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3410       int *ptA1=a1->getPointer();
3411       const int *conn=getNodalConnectivity()->getConstPointer();
3412       const int *index=getNodalConnectivityIndex()->getConstPointer();
3413       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3414       std::copy(conn,conn+getMeshLength(),ptA1);
3415     }
3416   else
3417     a1=0;
3418 }
3419
3420 /*!
3421  * Second and final unserialization process.
3422  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3423  */
3424 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3425 {
3426   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3427   setMeshDimension(tinyInfo[5]);
3428   if(tinyInfo[7]!=-1)
3429     {
3430       // Connectivity
3431       const int *recvBuffer=a1->getConstPointer();
3432       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3433       myConnecIndex->alloc(tinyInfo[6]+1,1);
3434       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3435       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3436       myConnec->alloc(tinyInfo[7],1);
3437       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3438       setConnectivity(myConnec, myConnecIndex);
3439     }
3440 }
3441
3442 /*!
3443  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3444  * CellIds are given using range specified by a start an end and step.
3445  */
3446 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3447 {
3448   checkFullyDefined();
3449   int ncell=getNumberOfCells();
3450   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3451   ret->_mesh_dim=_mesh_dim;
3452   ret->setCoords(_coords);
3453   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3455   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3456   int work=start;
3457   const int *conn=_nodal_connec->getConstPointer();
3458   const int *connIndex=_nodal_connec_index->getConstPointer();
3459   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3460     {
3461       if(work>=0 && work<ncell)
3462         {
3463           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3464         }
3465       else
3466         {
3467           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3468           throw INTERP_KERNEL::Exception(oss.str().c_str());
3469         }
3470     }
3471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3472   int *newConnPtr=newConn->getPointer();
3473   std::set<INTERP_KERNEL::NormalizedCellType> types;
3474   work=start;
3475   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3476     {
3477       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3478       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3479     }
3480   ret->setConnectivity(newConn,newConnI,false);
3481   ret->_types=types;
3482   ret->copyTinyInfoFrom(this);
3483   return ret.retn();
3484 }
3485
3486 /*!
3487  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3488  * Keeps from \a this only cells which constituing point id are in the ids specified by ['begin','end').
3489  * The return newly allocated mesh will share the same coordinates as \a this.
3490  */
3491 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3492 {
3493   checkFullyDefined();
3494   int ncell=getNumberOfCells();
3495   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3496   ret->_mesh_dim=_mesh_dim;
3497   ret->setCoords(_coords);
3498   std::size_t nbOfElemsRet=std::distance(begin,end);
3499   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3500   connIndexRet[0]=0;
3501   const int *conn=_nodal_connec->getConstPointer();
3502   const int *connIndex=_nodal_connec_index->getConstPointer();
3503   int newNbring=0;
3504   for(const int *work=begin;work!=end;work++,newNbring++)
3505     {
3506       if(*work>=0 && *work<ncell)
3507         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3508       else
3509         {
3510           free(connIndexRet);
3511           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3512           throw INTERP_KERNEL::Exception(oss.str().c_str());
3513         }
3514     }
3515   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3516   int *connRetWork=connRet;
3517   std::set<INTERP_KERNEL::NormalizedCellType> types;
3518   for(const int *work=begin;work!=end;work++)
3519     {
3520       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3521       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3522     }
3523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3524   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3525   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3526   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3527   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3528   ret->_types=types;
3529   ret->copyTinyInfoFrom(this);
3530   return ret.retn();
3531 }
3532
3533 /*!
3534  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3535  * mesh.<br>
3536  * For 1D cells, the returned field contains lengths.<br>
3537  * For 2D cells, the returned field contains areas.<br>
3538  * For 3D cells, the returned field contains volumes.
3539  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3540  *         orientation, i.e. the volume is always positive.
3541  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3542  *         and one time . The caller is to delete this field using decrRef() as it is no
3543  *         more needed.
3544  */
3545 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3546 {
3547   std::string name="MeasureOfMesh_";
3548   name+=getName();
3549   int nbelem=getNumberOfCells();
3550   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3551   field->setName(name.c_str());
3552   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3553   array->alloc(nbelem,1);
3554   double *area_vol=array->getPointer();
3555   field->setArray(array) ; array=0;
3556   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3557   field->synchronizeTimeWithMesh();
3558   if(getMeshDimension()!=-1)
3559     {
3560       int ipt;
3561       INTERP_KERNEL::NormalizedCellType type;
3562       int dim_space=getSpaceDimension();
3563       const double *coords=getCoords()->getConstPointer();
3564       const int *connec=getNodalConnectivity()->getConstPointer();
3565       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3566       for(int iel=0;iel<nbelem;iel++)
3567         {
3568           ipt=connec_index[iel];
3569           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3570           area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3571         }
3572       if(isAbs)
3573         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3574     }
3575   else
3576     {
3577       area_vol[0]=std::numeric_limits<double>::max();
3578     }
3579   return field.retn();
3580 }
3581
3582 /*!
3583  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3584  * mesh.<br>
3585  * For 1D cells, the returned array contains lengths.<br>
3586  * For 2D cells, the returned array contains areas.<br>
3587  * For 3D cells, the returned array contains volumes.
3588  * This method avoids building explicitly a part of \a this mesh to perform the work.
3589  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3590  *         orientation, i.e. the volume is always positive.
3591  *  \param [in] begin - an array of cell ids of interest.
3592  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3593  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3594  *          delete this array using decrRef() as it is no more needed.
3595  * 
3596  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3597  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3598  *  \sa getMeasureField()
3599  */
3600 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3601 {
3602   std::string name="PartMeasureOfMesh_";
3603   name+=getName();
3604   int nbelem=(int)std::distance(begin,end);
3605   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3606   array->setName(name.c_str());
3607   array->alloc(nbelem,1);
3608   double *area_vol=array->getPointer();
3609   if(getMeshDimension()!=-1)
3610     {
3611       int ipt;
3612       INTERP_KERNEL::NormalizedCellType type;
3613       int dim_space=getSpaceDimension();
3614       const double *coords=getCoords()->getConstPointer();
3615       const int *connec=getNodalConnectivity()->getConstPointer();
3616       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3617       for(const int *iel=begin;iel!=end;iel++)
3618         {
3619           ipt=connec_index[*iel];
3620           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3621           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3622         }
3623       if(isAbs)
3624         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3625     }
3626   else
3627     {
3628       area_vol[0]=std::numeric_limits<double>::max();
3629     }
3630   return array.retn();
3631 }
3632
3633 /*!
3634  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3635  * \a this one. The returned field contains the dual cell volume for each corresponding
3636  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3637  *  the dual mesh in P1 sens of \a this.<br>
3638  * For 1D cells, the returned field contains lengths.<br>
3639  * For 2D cells, the returned field contains areas.<br>
3640  * For 3D cells, the returned field contains volumes.
3641  * This method is useful to check "P1*" conservative interpolators.
3642  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3643  *         orientation, i.e. the volume is always positive.
3644  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3645  *          nodes and one time. The caller is to delete this array using decrRef() as
3646  *          it is no more needed.
3647  */
3648 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3649 {
3650   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3651   std::string name="MeasureOnNodeOfMesh_";
3652   name+=getName();
3653   int nbNodes=getNumberOfNodes();
3654   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3655   double cst=1./((double)getMeshDimension()+1.);
3656   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3657   array->alloc(nbNodes,1);
3658   double *valsToFill=array->getPointer();
3659   std::fill(valsToFill,valsToFill+nbNodes,0.);
3660   const double *values=tmp->getArray()->getConstPointer();
3661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3662   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3663   getReverseNodalConnectivity(da,daInd);
3664   const int *daPtr=da->getConstPointer();
3665   const int *daIPtr=daInd->getConstPointer();
3666   for(int i=0;i<nbNodes;i++)
3667     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3668       valsToFill[i]+=cst*values[*cell];
3669   ret->setMesh(this);
3670   ret->setArray(array);
3671   return ret.retn();
3672 }
3673
3674 /*!
3675  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3676  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3677  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3678  * and are normalized.
3679  * <br> \a this can be either 
3680  * - a  2D mesh in 2D or 3D space or 
3681  * - an 1D mesh in 2D space.
3682  * 
3683  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3684  *          cells and one time. The caller is to delete this field using decrRef() as
3685  *          it is no more needed.
3686  *  \throw If the nodal connectivity of cells is not defined.
3687  *  \throw If the coordinates array is not set.
3688  *  \throw If the mesh dimension is not set.
3689  *  \throw If the mesh and space dimension is not as specified above.
3690  */
3691 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3692 {
3693   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3694     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3695   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3696   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3697   int nbOfCells=getNumberOfCells();
3698   int nbComp=getMeshDimension()+1;
3699   array->alloc(nbOfCells,nbComp);
3700   double *vals=array->getPointer();
3701   const int *connI=_nodal_connec_index->getConstPointer();
3702   const int *conn=_nodal_connec->getConstPointer();
3703   const double *coords=_coords->getConstPointer();
3704   if(getMeshDimension()==2)
3705     {
3706       if(getSpaceDimension()==3)
3707         {
3708           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3709           const double *locPtr=loc->getConstPointer();
3710           for(int i=0;i<nbOfCells;i++,vals+=3)
3711             {
3712               int offset=connI[i];
3713               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3714               double n=INTERP_KERNEL::norm<3>(vals);
3715               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3716             }
3717         }
3718       else
3719         {
3720           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3721           const double *isAbsPtr=isAbs->getArray()->begin();
3722           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3723             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3724         }
3725     }
3726   else//meshdimension==1
3727     {
3728       double tmp[2];
3729       for(int i=0;i<nbOfCells;i++)
3730         {
3731           int offset=connI[i];
3732           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3733           double n=INTERP_KERNEL::norm<2>(tmp);
3734           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3735           *vals++=-tmp[1];
3736           *vals++=tmp[0];
3737         }
3738     }
3739   ret->setArray(array);
3740   ret->setMesh(this);
3741   ret->synchronizeTimeWithSupport();
3742   return ret.retn();
3743 }
3744
3745 /*!
3746  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3747  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3748  * and are normalized.
3749  * <br> \a this can be either 
3750  * - a  2D mesh in 2D or 3D space or 
3751  * - an 1D mesh in 2D space.
3752  * 
3753  * This method avoids building explicitly a part of \a this mesh to perform the work.
3754  *  \param [in] begin - an array of cell ids of interest.
3755  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3756  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3757  *          cells and one time. The caller is to delete this field using decrRef() as
3758  *          it is no more needed.
3759  *  \throw If the nodal connectivity of cells is not defined.
3760  *  \throw If the coordinates array is not set.
3761  *  \throw If the mesh dimension is not set.
3762  *  \throw If the mesh and space dimension is not as specified above.
3763  *  \sa buildOrthogonalField()
3764  *
3765  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3766  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3767  */
3768 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3769 {
3770   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3771     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3772   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3773   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3774   std::size_t nbelems=std::distance(begin,end);
3775   int nbComp=getMeshDimension()+1;
3776   array->alloc((int)nbelems,nbComp);
3777   double *vals=array->getPointer();
3778   const int *connI=_nodal_connec_index->getConstPointer();
3779   const int *conn=_nodal_connec->getConstPointer();
3780   const double *coords=_coords->getConstPointer();
3781   if(getMeshDimension()==2)
3782     {
3783       if(getSpaceDimension()==3)
3784         {
3785           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3786           const double *locPtr=loc->getConstPointer();
3787           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3788             {
3789               int offset=connI[*i];
3790               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3791               double n=INTERP_KERNEL::norm<3>(vals);
3792               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3793             }
3794         }
3795       else
3796         {
3797           for(std::size_t i=0;i<nbelems;i++)
3798             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3799         }
3800     }
3801   else//meshdimension==1
3802     {
3803       double tmp[2];
3804       for(const int *i=begin;i!=end;i++)
3805         {
3806           int offset=connI[*i];
3807           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3808           double n=INTERP_KERNEL::norm<2>(tmp);
3809           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3810           *vals++=-tmp[1];
3811           *vals++=tmp[0];
3812         }
3813     }
3814   ret->setArray(array);
3815   ret->setMesh(this);
3816   ret->synchronizeTimeWithSupport();
3817   return ret.retn();
3818 }
3819
3820 /*!
3821  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3822  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3823  * and are \b not normalized.
3824  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3825  *          cells and one time. The caller is to delete this field using decrRef() as
3826  *          it is no more needed.
3827  *  \throw If the nodal connectivity of cells is not defined.
3828  *  \throw If the coordinates array is not set.
3829  *  \throw If \a this->getMeshDimension() != 1.
3830  *  \throw If \a this mesh includes cells of type other than SEG2.
3831  */
3832 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3833 {
3834    if(getMeshDimension()!=1)
3835     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3836    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3837      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3838    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3839    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3840    int nbOfCells=getNumberOfCells();
3841    int spaceDim=getSpaceDimension();
3842    array->alloc(nbOfCells,spaceDim);
3843    double *pt=array->getPointer();
3844    const double *coo=getCoords()->getConstPointer();
3845    std::vector<int> conn;
3846    conn.reserve(2);
3847    for(int i=0;i<nbOfCells;i++)
3848      {
3849        conn.resize(0);
3850        getNodeIdsOfCell(i,conn);
3851        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3852      }
3853    ret->setArray(array);
3854    ret->setMesh(this);
3855    ret->synchronizeTimeWithSupport();
3856    return ret.retn();   
3857 }
3858
3859 /*!
3860  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3861  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3862  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3863  * from. If a result face is shared by two 3D cells, then the face in included twice in
3864  * the result mesh.
3865  *  \param [in] origin - 3 components of a point defining location of the plane.
3866  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3867  *         must be greater than 1e-6.
3868  *  \param [in] eps - half-thickness of the plane.
3869  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3870  *         producing correspondent 2D cells. The caller is to delete this array
3871  *         using decrRef() as it is no more needed.
3872  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3873  *         not share the node coordinates array with \a this mesh. The caller is to
3874  *         delete this mesh using decrRef() as it is no more needed.  
3875  *  \throw If the coordinates array is not set.
3876  *  \throw If the nodal connectivity of cells is not defined.
3877  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3878  *  \throw If magnitude of \a vec is less than 1e-6.
3879  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3880  *  \throw If \a this includes quadratic cells.
3881  */
3882 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3883 {
3884   checkFullyDefined();
3885   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3886     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3888   if(candidates->empty())
3889     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3890   std::vector<int> nodes;
3891   DataArrayInt *cellIds1D=0;
3892   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3893   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3896   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3898   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3899   revDesc2=0; revDescIndx2=0;
3900   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3901   revDesc1=0; revDescIndx1=0;
3902   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3903   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3904   //
3905   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3906   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3907     cut3DCurve[*it]=-1;
3908   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3909   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3910   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3911                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3912                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3914   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3915   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3916   if(cellIds2->empty())
3917     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3918   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3919   ret->setCoords(mDesc1->getCoords());
3920   ret->setConnectivity(conn,connI,true);
3921   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3922   return ret.retn();
3923 }
3924
3925 /*!
3926  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3927 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3928 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3929 the result mesh.
3930  *  \param [in] origin - 3 components of a point defining location of the plane.
3931  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3932  *         must be greater than 1e-6.
3933  *  \param [in] eps - half-thickness of the plane.
3934  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3935  *         producing correspondent segments. The caller is to delete this array
3936  *         using decrRef() as it is no more needed.
3937  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3938  *         mesh in 3D space. This mesh does not share the node coordinates array with
3939  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3940  *         no more needed. 
3941  *  \throw If the coordinates array is not set.
3942  *  \throw If the nodal connectivity of cells is not defined.
3943  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3944  *  \throw If magnitude of \a vec is less than 1e-6.
3945  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3946  *  \throw If \a this includes quadratic cells.
3947  */
3948 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3949 {
3950   checkFullyDefined();
3951   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3952     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3953   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3954   if(candidates->empty())
3955     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3956   std::vector<int> nodes;
3957   DataArrayInt *cellIds1D=0;
3958   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3959   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3961   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3964   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3965   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3966   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3967   //
3968   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3969   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3970     cut3DCurve[*it]=-1;
3971   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3972   int ncellsSub=subMesh->getNumberOfCells();
3973   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3974   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3975                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3976                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3978   conn->alloc(0,1);
3979   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3980   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3981   for(int i=0;i<ncellsSub;i++)
3982     {
3983       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3984         {
3985           if(cut3DSurf[i].first!=-2)
3986             {
3987               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3988               connI->pushBackSilent(conn->getNumberOfTuples());
3989               cellIds2->pushBackSilent(i);
3990             }
3991           else
3992             {
3993               int cellId3DSurf=cut3DSurf[i].second;
3994               int offset=nodalI[cellId3DSurf]+1;
3995               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3996               for(int j=0;j<nbOfEdges;j++)
3997                 {
3998                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3999                   connI->pushBackSilent(conn->getNumberOfTuples());
4000                   cellIds2->pushBackSilent(cellId3DSurf);
4001                 }
4002             }
4003         }
4004     }
4005   if(cellIds2->empty())
4006     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
4007   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
4008   ret->setCoords(mDesc1->getCoords());
4009   ret->setConnectivity(conn,connI,true);
4010   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
4011   return ret.retn();
4012 }
4013
4014 /*!
4015  * Finds cells whose bounding boxes intersect a given plane.
4016  *  \param [in] origin - 3 components of a point defining location of the plane.
4017  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
4018  *         must be greater than 1e-6.
4019  *  \param [in] eps - half-thickness of the plane.
4020  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
4021  *         cells. The caller is to delete this array using decrRef() as it is no more
4022  *         needed.
4023  *  \throw If the coordinates array is not set.
4024  *  \throw If the nodal connectivity of cells is not defined.
4025  *  \throw If \a this->getSpaceDimension() != 3.
4026  *  \throw If magnitude of \a vec is less than 1e-6.
4027  *  \sa buildSlice3D()
4028  */
4029 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
4030 {
4031   checkFullyDefined();
4032   if(getSpaceDimension()!=3)
4033     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4034   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4035   if(normm<1e-6)
4036     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4037   double vec2[3];
4038   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4039   double angle=acos(vec[2]/normm);
4040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
4041   double bbox[6];
4042   if(angle>eps)
4043     {
4044       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
4045       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
4046       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4047       mw->setCoords(coo);
4048       mw->getBoundingBox(bbox);
4049       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4050       cellIds=mw->getCellsInBoundingBox(bbox,eps);
4051     }
4052   else
4053     {
4054       getBoundingBox(bbox);
4055       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4056       cellIds=getCellsInBoundingBox(bbox,eps);
4057     }
4058   return cellIds.retn();
4059 }
4060
4061 /*!
4062  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4063  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4064  * No consideration of coordinate is done by this method.
4065  * A 1D mesh is said contiguous if : a cell i with nodal connectivity (k,p) the cell i+1 the nodal connectivity should be (p,m)
4066  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
4067  */
4068 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
4069 {
4070   if(getMeshDimension()!=1)
4071     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4072   int nbCells=getNumberOfCells();
4073   if(nbCells<1)
4074     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4075   const int *connI=_nodal_connec_index->getConstPointer();
4076   const int *conn=_nodal_connec->getConstPointer();
4077   int ref=conn[connI[0]+2];
4078   for(int i=1;i<nbCells;i++)
4079     {
4080       if(conn[connI[i]+1]!=ref)
4081         return false;
4082       ref=conn[connI[i]+2];
4083     }
4084   return true;
4085 }
4086
4087 /*!
4088  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4089  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4090  * \param pt reference point of the line
4091  * \param v normalized director vector of the line
4092  * \param eps max precision before throwing an exception
4093  * \param res output of size this->getNumberOfCells
4094  */
4095 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4096 {
4097   if(getMeshDimension()!=1)
4098     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4099    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4100      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4101    if(getSpaceDimension()!=3)
4102      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4103    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4104    const double *fPtr=f->getArray()->getConstPointer();
4105    double tmp[3];
4106    for(int i=0;i<getNumberOfCells();i++)
4107      {
4108        const double *tmp1=fPtr+3*i;
4109        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4110        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4111        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4112        double n1=INTERP_KERNEL::norm<3>(tmp);
4113        n1/=INTERP_KERNEL::norm<3>(tmp1);
4114        if(n1>eps)
4115          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4116      }
4117    const double *coo=getCoords()->getConstPointer();
4118    for(int i=0;i<getNumberOfNodes();i++)
4119      {
4120        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4121        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4122        res[i]=std::accumulate(tmp,tmp+3,0.);
4123      }
4124 }
4125
4126 /*!
4127  * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. 
4128  * \a this is expected to be a mesh so that its space dimension is equal to its
4129  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4130  * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
4131  
4132  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
4133  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
4134  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4135  *
4136  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4137  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4138  *
4139  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4140  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4141  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4142  * \return the positive value of the distance.
4143  * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space
4144  * dimension - 1.
4145  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4146  */
4147 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
4148 {
4149   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4150   if(meshDim!=spaceDim-1)
4151     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4152   if(meshDim!=2 && meshDim!=1)
4153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4154   checkFullyDefined();
4155   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4156     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
4157   DataArrayInt *ret1=0;
4158   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4159   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4160   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4161   cellId=*ret1Safe->begin();
4162   return *ret0->begin();
4163 }
4164
4165 /*!
4166  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4167  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4168  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
4169  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
4170  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4171  * 
4172  * \a this is expected to be a mesh so that its space dimension is equal to its
4173  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4174  * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
4175  *
4176  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4177  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4178  *
4179  * \param [in] pts the list of points in which each tuple represents a point
4180  * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
4181  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4182  * \throw if number of components of \a pts is not equal to the space dimension.
4183  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4184  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4185  */
4186 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
4187 {
4188   if(!pts)
4189     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4190   pts->checkAllocated();
4191   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4192   if(meshDim!=spaceDim-1)
4193     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4194   if(meshDim!=2 && meshDim!=1)
4195     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4196   if(pts->getNumberOfComponents()!=spaceDim)
4197     {
4198       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4199       throw INTERP_KERNEL::Exception(oss.str().c_str());
4200     }
4201   checkFullyDefined();
4202   int nbCells=getNumberOfCells();
4203   if(nbCells==0)
4204     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4205   int nbOfPts=pts->getNumberOfTuples();
4206   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4208   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4209   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4210   std::vector<double> bbox;
4211   getBoundingBoxForBBTree(bbox);
4212   switch(spaceDim)
4213     {
4214     case 3:
4215       {
4216         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
4217         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4218           {
4219             double x=std::numeric_limits<double>::max();
4220             std::vector<int> elems;
4221             myTree.getMinDistanceOfMax(ptsPtr,x);
4222             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4223             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4224           }
4225         break;
4226       }
4227     case 2:
4228       {
4229         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
4230         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4231           {
4232             double x=std::numeric_limits<double>::max();
4233             std::vector<int> elems;
4234             myTree.getMinDistanceOfMax(ptsPtr,x);
4235             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4236             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4237           }
4238         break;
4239       }
4240     default:
4241       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4242     }
4243   cellIds=ret1.retn();
4244   return ret0.retn();
4245 }
4246
4247 /*!
4248  * \param [in] pt the start pointer (included) of the coordinates of the point
4249  * \param [in] cellIdsBg the start pointer (included) of cellIds
4250  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4251  * \param [in] nc nodal connectivity
4252  * \param [in] ncI nodal connectivity index
4253  * \param [in,out] ret0 the min distance between \a this and the external input point
4254  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4255  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4256  */
4257 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
4258 {
4259   cellId=-1;
4260   ret0=std::numeric_limits<double>::max();
4261   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4262     {
4263       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4264         {
4265         case INTERP_KERNEL::NORM_TRI3:
4266           {
4267             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4268             if(tmp<ret0)
4269               { ret0=tmp; cellId=*zeCell; }
4270             break;
4271           }
4272         case INTERP_KERNEL::NORM_QUAD4:
4273         case INTERP_KERNEL::NORM_POLYGON:
4274           {
4275             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4276             if(tmp<ret0)
4277               { ret0=tmp; cellId=*zeCell; }
4278             break;
4279           }
4280         default:
4281           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4282         }
4283     }
4284 }
4285
4286 /*!
4287  * \param [in] pt the start pointer (included) of the coordinates of the point
4288  * \param [in] cellIdsBg the start pointer (included) of cellIds
4289  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4290  * \param [in] nc nodal connectivity
4291  * \param [in] ncI nodal connectivity index
4292  * \param [in,out] ret0 the min distance between \a this and the external input point
4293  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4294  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4295  */
4296 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
4297 {
4298   cellId=-1;
4299   ret0=std::numeric_limits<double>::max();
4300   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4301     {
4302        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4303         {
4304         case INTERP_KERNEL::NORM_SEG2:
4305           {
4306             std::size_t uselessEntry=0;
4307             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4308             tmp=sqrt(tmp);
4309             if(tmp<ret0)
4310               { ret0=tmp; cellId=*zeCell; }
4311             break;
4312           }
4313         default:
4314           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4315         }
4316     }
4317 }
4318
4319 /*!
4320  * Finds cells in contact with a ball (i.e. a point with precision). 
4321  * \warning This method is suitable if the caller intends to evaluate only one
4322  *          point, for more points getCellsContainingPoints() is recommended as it is
4323  *          faster. 
4324  *  \param [in] pos - array of coordinates of the ball central point.
4325  *  \param [in] eps - ball radius.
4326  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4327  *         if there are no such cells.
4328  *  \throw If the coordinates array is not set.
4329  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4330  */
4331 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4332 {
4333   std::vector<int> elts;
4334   getCellsContainingPoint(pos,eps,elts);
4335   if(elts.empty())
4336     return -1;
4337   return elts.front();
4338 }
4339
4340 /*!
4341  * Finds cells in contact with a ball (i.e. a point with precision).
4342  * \warning This method is suitable if the caller intends to evaluate only one
4343  *          point, for more points getCellsContainingPoints() is recommended as it is
4344  *          faster. 
4345  *  \param [in] pos - array of coordinates of the ball central point.
4346  *  \param [in] eps - ball radius.
4347  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
4348  *         before inserting ids.
4349  *  \throw If the coordinates array is not set.
4350  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4351  *
4352  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4353  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4354  */
4355 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4356 {
4357   std::vector<int> eltsIndex;
4358   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4359 }
4360
4361 /// @cond INTERNAL
4362
4363 namespace ParaMEDMEM
4364 {
4365   template<const int SPACEDIMM>
4366   class DummyClsMCUG
4367   {
4368   public:
4369     static const int MY_SPACEDIM=SPACEDIMM;
4370     static const int MY_MESHDIM=8;
4371     typedef int MyConnType;
4372     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4373     // begin
4374     // useless, but for windows compilation ...
4375     const double* getCoordinatesPtr() const { return 0; }
4376     const int* getConnectivityPtr() const { return 0; }
4377     const int* getConnectivityIndexPtr() const { return 0; }
4378     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4379     // end
4380   };
4381
4382   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4383   {
4384     INTERP_KERNEL::Edge *ret=0;
4385     switch(typ)
4386       {
4387       case INTERP_KERNEL::NORM_SEG2:
4388         {
4389           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4390           break;
4391         }
4392       case INTERP_KERNEL::NORM_SEG3:
4393         {
4394           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4395           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4396           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4397           bool colinearity=inters.areColinears();
4398           delete e1; delete e2;
4399           if(colinearity)
4400             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4401           else
4402             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4403           mapp2[bg[2]].second=false;
4404           break;
4405         }
4406       default:
4407         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4408       }
4409     return ret;
4410   }
4411
4412   /*!
4413    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4414    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4415    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4416    */
4417   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4418   {
4419     mapp.clear();
4420     std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4421     const double *coo=mDesc->getCoords()->getConstPointer();
4422     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4423     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4424     std::set<int> s;
4425     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4426       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4427     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4428       {
4429         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4430         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4431       }
4432     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4433     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4434       {
4435         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4436         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4437       }
4438     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4439       {
4440         if((*it2).second.second)
4441           mapp[(*it2).second.first]=(*it2).first;
4442         ((*it2).second.first)->decrRef();
4443       }
4444     return ret;
4445   }
4446
4447   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4448   {
4449     if(nodeId>=offset2)
4450       {
4451         int locId=nodeId-offset2;
4452         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4453       }
4454     if(nodeId>=offset1)
4455       {
4456         int locId=nodeId-offset1;
4457         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4458       }
4459     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4460   }
4461
4462   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4463                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4464                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4465   {
4466     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4467       {
4468         int eltId1=abs(*desc1)-1;
4469         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4470           {
4471             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4472             if(it==mappRev.end())
4473               {
4474                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4475                 mapp[node]=*it1;
4476                 mappRev[*it1]=node;
4477               }
4478           }
4479       }
4480   }
4481 }
4482
4483 /// @endcond
4484
4485 template<int SPACEDIM>
4486 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4487                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4488 {
4489   std::vector<double> bbox;
4490   eltsIndex.resize(nbOfPoints+1);
4491   eltsIndex[0]=0;
4492   elts.clear();
4493   getBoundingBoxForBBTree(bbox);
4494   int nbOfCells=getNumberOfCells();
4495   const int *conn=_nodal_connec->getConstPointer();
4496   const int *connI=_nodal_connec_index->getConstPointer();
4497   double bb[2*SPACEDIM];
4498   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4499   for(int i=0;i<nbOfPoints;i++)
4500     {
4501       eltsIndex[i+1]=eltsIndex[i];
4502       for(int j=0;j<SPACEDIM;j++)
4503         {
4504           bb[2*j]=pos[SPACEDIM*i+j];
4505           bb[2*j+1]=pos[SPACEDIM*i+j];
4506         }
4507       std::vector<int> candidates;
4508       myTree.getIntersectingElems(bb,candidates);
4509       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4510         {
4511           int sz=connI[(*iter)+1]-connI[*iter]-1;
4512           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4513                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4514                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4515             {
4516               eltsIndex[i+1]++;
4517               elts.push_back(*iter);
4518             }
4519         }
4520     }
4521 }
4522 /*!
4523  * Finds cells in contact with several balls (i.e. points with precision).
4524  * This method is an extension of getCellContainingPoint() and
4525  * getCellsContainingPoint() for the case of multiple points.
4526  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4527  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4528  *         this->getSpaceDimension() * \a nbOfPoints 
4529  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4530  *  \param [in] eps - radius of balls (i.e. the precision).
4531  *  \param [in,out] elts - vector returning ids of found cells.
4532  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4533  *         dividing cell ids in \a elts into groups each referring to one
4534  *         point. Its every element (except the last one) is an index pointing to the
4535  *         first id of a group of cells. For example cells in contact with the *i*-th
4536  *         point are described by following range of indices:
4537  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4538  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4539  *         Number of cells in contact with the *i*-th point is
4540  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4541  *  \throw If the coordinates array is not set.
4542  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4543  *
4544  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4545  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4546  */
4547 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4548                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4549 {
4550   int spaceDim=getSpaceDimension();
4551   int mDim=getMeshDimension();
4552   if(spaceDim==3)
4553     {
4554       if(mDim==3)
4555         {
4556           const double *coords=_coords->getConstPointer();
4557           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4558         }
4559       /*else if(mDim==2)
4560         {
4561           
4562         }*/
4563       else
4564         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4565     }
4566   else if(spaceDim==2)
4567     {
4568       if(mDim==2)
4569         {
4570           const double *coords=_coords->getConstPointer();
4571           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4572         }
4573       else
4574         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4575     }
4576   else if(spaceDim==1)
4577     {
4578       if(mDim==1)
4579         {
4580           const double *coords=_coords->getConstPointer();
4581           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4582         }
4583       else
4584         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4585     }
4586   else
4587     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4588 }
4589
4590 /*!
4591  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4592  * least two its edges intersect each other anywhere except their extremities. An
4593  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4594  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4595  *         cleared before filling in.
4596  *  \param [in] eps - precision.
4597  *  \throw If \a this->getMeshDimension() != 2.
4598  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4599  */
4600 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4601 {
4602   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4603   if(getMeshDimension()!=2)
4604     throw INTERP_KERNEL::Exception(msg);
4605   int spaceDim=getSpaceDimension();
4606   if(spaceDim!=2 && spaceDim!=3)
4607     throw INTERP_KERNEL::Exception(msg);
4608   const int *conn=_nodal_connec->getConstPointer();
4609   const int *connI=_nodal_connec_index->getConstPointer();
4610   int nbOfCells=getNumberOfCells();
4611   std::vector<double> cell2DinS2;
4612   for(int i=0;i<nbOfCells;i++)
4613     {
4614       int offset=connI[i];
4615       int nbOfNodesForCell=connI[i+1]-offset-1;
4616       if(nbOfNodesForCell<=3)
4617         continue;
4618       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4619       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4620       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4621         cells.push_back(i);
4622       cell2DinS2.clear();
4623     }
4624 }
4625
4626 /*!
4627  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4628  *
4629  * This method expects that space dimension is equal to 2 and mesh dimension is equal to 2 too. If it is not the case an INTERP_KERNEL::Exception will be thrown.
4630  * This method works only for linear 2D cells. If there is any of non linear cells (INTERP_KERNEL::NORM_QUAD8 for example) an INTERP_KERNEL::Exception will be thrown too.
4631  * 
4632  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4633  * This convex envelop is computed using Jarvis march algorithm.
4634  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4635  * Only connectivity of some cells could be modified if those cells were not representing a convex envelop. If a cell already equals its convex envelop (regardless orientation)
4636  * its connectivity will remain unchanged. If the computation leads to a modification of nodal connectivity of a cell its geometric type will be modified to INTERP_KERNEL::NORM_POLYGON.
4637  *
4638  * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned.
4639  */
4640 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4641 {
4642   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4643     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4644   checkFullyDefined();
4645   const double *coords=getCoords()->getConstPointer();
4646   int nbOfCells=getNumberOfCells();
4647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4648   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4649   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4650   int *workIndexOut=nodalConnecIndexOut->getPointer();
4651   *workIndexOut=0;
4652   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4653   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4654   std::set<INTERP_KERNEL::NormalizedCellType> types;
4655   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4656   isChanged->alloc(0,1);
4657   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4658     {
4659       int pos=nodalConnecOut->getNumberOfTuples();
4660       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4661         isChanged->pushBackSilent(i);
4662       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4663       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4664     }
4665   if(isChanged->empty())
4666     return 0;
4667   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4668   _types=types;
4669   return isChanged.retn();
4670 }
4671
4672 /*!
4673  * This method is \b NOT const because it can modify \a this.
4674  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4675  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4676  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4677  * \b 1 for translation and rotation around point of 'mesh1D'.
4678  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4679  */
4680 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4681 {
4682   checkFullyDefined();
4683   mesh1D->checkFullyDefined();
4684   if(!mesh1D->isContiguous1D())
4685     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4686   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4687     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4688   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4689     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4690   if(mesh1D->getMeshDimension()!=1)
4691     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4692   bool isQuad=false;
4693   if(isPresenceOfQuadratic())
4694     {
4695       if(mesh1D->isFullyQuadratic())
4696         isQuad=true;
4697       else
4698         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4699     }
4700   zipCoords();
4701   int oldNbOfNodes=getNumberOfNodes();
4702   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4703   switch(policy)
4704     {
4705     case 0:
4706       {
4707         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4708         break;
4709       }
4710     case 1:
4711       {
4712         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4713         break;
4714       }
4715     default:
4716       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4717     }
4718   setCoords(newCoords);
4719   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4720   updateTime();
4721   return ret.retn();
4722 }
4723
4724 /*!
4725  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4726  * If it is not the case an exception will be thrown.
4727  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4728  * intersection of plane defined by ('origin','vec').
4729  * This method has one in/out parameter : 'cut3DCurve'.
4730  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4731  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4732  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4733  * This method will throw an exception if \a this contains a non linear segment.
4734  */
4735 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4736 {
4737   checkFullyDefined();
4738   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4740   int ncells=getNumberOfCells();
4741   int nnodes=getNumberOfNodes();
4742   double vec2[3],vec3[3],vec4[3];
4743   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4744   if(normm<1e-6)
4745     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4746   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4747   const int *conn=_nodal_connec->getConstPointer();
4748   const int *connI=_nodal_connec_index->getConstPointer();
4749   const double *coo=_coords->getConstPointer();
4750   std::vector<double> addCoo;
4751   for(int i=0;i<ncells;i++)
4752     {
4753       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4754         {
4755           if(cut3DCurve[i]==-2)
4756             {
4757               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4758               vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4759               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4760               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4761               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4762                 {
4763                   const double *st2=coo+3*st;
4764                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4765                   double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4766                   if(pos>eps && pos<1-eps)
4767                     {
4768                       int nNode=((int)addCoo.size())/3;
4769                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4770                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4771                       cut3DCurve[i]=nnodes+nNode;
4772                     }
4773                 }
4774             }
4775         }
4776       else
4777         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4778     }
4779   if(!addCoo.empty())
4780     {
4781       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4782       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4783       coo2->alloc(newNbOfNodes,3);
4784       double *tmp=coo2->getPointer();
4785       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4786       std::copy(addCoo.begin(),addCoo.end(),tmp);
4787       DataArrayDouble::SetArrayIn(coo2,_coords);
4788     }
4789 }
4790
4791 /*!
4792  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4793  * \param mesh1D is the input 1D mesh used for translation computation.
4794  * \return newCoords new coords filled by this method. 
4795  */
4796 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4797 {
4798   int oldNbOfNodes=getNumberOfNodes();
4799   int nbOf1DCells=mesh1D->getNumberOfCells();
4800   int spaceDim=getSpaceDimension();
4801   DataArrayDouble *ret=DataArrayDouble::New();
4802   std::vector<bool> isQuads;
4803   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4804   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4805   double *retPtr=ret->getPointer();
4806   const double *coords=getCoords()->getConstPointer();
4807   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4808   std::vector<int> v;
4809   std::vector<double> c;
4810   double vec[3];
4811   v.reserve(3);
4812   c.reserve(6);
4813   for(int i=0;i<nbOf1DCells;i++)
4814     {
4815       v.resize(0);
4816       mesh1D->getNodeIdsOfCell(i,v);
4817       c.resize(0);
4818       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4819       mesh1D->getCoordinatesOfNode(v[0],c);
4820       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4821       for(int j=0;j<oldNbOfNodes;j++)
4822         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4823       if(isQuad)
4824         {
4825           c.resize(0);
4826           mesh1D->getCoordinatesOfNode(v[1],c);
4827           mesh1D->getCoordinatesOfNode(v[0],c);
4828           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4829           for(int j=0;j<oldNbOfNodes;j++)
4830             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4831         }
4832     }
4833   ret->copyStringInfoFrom(*getCoords());
4834   return ret;
4835 }
4836
4837 /*!
4838  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4839  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4840  * \return newCoords new coords filled by this method. 
4841  */
4842 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4843 {
4844   if(mesh1D->getSpaceDimension()==2)
4845     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4846   if(mesh1D->getSpaceDimension()==3)
4847     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4848   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4849 }
4850
4851 /*!
4852  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4853  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4854  * \return newCoords new coords filled by this method. 
4855  */
4856 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4857 {
4858   if(isQuad)
4859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4860   int oldNbOfNodes=getNumberOfNodes();
4861   int nbOf1DCells=mesh1D->getNumberOfCells();
4862   if(nbOf1DCells<2)
4863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4864   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4865   int nbOfLevsInVec=nbOf1DCells+1;
4866   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4867   double *retPtr=ret->getPointer();
4868   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4869   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4870   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4871   tmp->setCoords(tmp2);
4872   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4873   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4874   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4875   for(int i=1;i<nbOfLevsInVec;i++)
4876     {
4877       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4878       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4879       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4880       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4881       tmp->translate(vec);
4882       double tmp3[2],radius,alpha,alpha0;
4883       const double *p0=i+1<nbOfLevsInVec?begin:third;
4884       const double *p1=i+1<nbOfLevsInVec?end:begin;
4885       const double *p2=i+1<nbOfLevsInVec?third:end;
4886       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4887       double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4888       double angle=acos(cosangle/(radius*radius));
4889       tmp->rotate(end,0,angle);
4890       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4891     }
4892   return ret.retn();
4893 }
4894
4895 /*!
4896  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4897  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4898  * \return newCoords new coords filled by this method. 
4899  */
4900 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4901 {
4902   if(isQuad)
4903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4904   int oldNbOfNodes=getNumberOfNodes();
4905   int nbOf1DCells=mesh1D->getNumberOfCells();
4906   if(nbOf1DCells<2)
4907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4908   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4909   int nbOfLevsInVec=nbOf1DCells+1;
4910   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4911   double *retPtr=ret->getPointer();
4912   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4913   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4914   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4915   tmp->setCoords(tmp2);
4916   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4917   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4918   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4919   for(int i=1;i<nbOfLevsInVec;i++)
4920     {
4921       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4922       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4923       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4924       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4925       tmp->translate(vec);
4926       double tmp3[2],radius,alpha,alpha0;
4927       const double *p0=i+1<nbOfLevsInVec?begin:third;
4928       const double *p1=i+1<nbOfLevsInVec?end:begin;
4929       const double *p2=i+1<nbOfLevsInVec?third:end;
4930       double vecPlane[3]={
4931         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4932         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4933         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4934       };
4935       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4936       if(norm>1.e-7)
4937         {
4938           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4939           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4940           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4941           double s2=norm2;
4942           double c2=cos(asin(s2));
4943           double m[3][3]={
4944             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4945             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4946             {-vec2[1]*s2, vec2[0]*s2, c2}
4947           };
4948           double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4949           double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4950           double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4951           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4952           double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4953           double angle=acos(cosangle/(radius*radius));
4954           tmp->rotate(end,vecPlane,angle);
4955           
4956         }
4957       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4958     }
4959   return ret.retn();
4960 }
4961
4962 /*!
4963  * This method is private because not easy to use for end user. This method is const contrary to
4964  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4965  * the coords sorted slice by slice.
4966  * \param isQuad specifies presence of quadratic cells.
4967  */
4968 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4969 {
4970   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4971   int nbOf2DCells=getNumberOfCells();
4972   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4973   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4974   const int *conn=_nodal_connec->getConstPointer();
4975   const int *connI=_nodal_connec_index->getConstPointer();
4976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4978   newConnI->alloc(nbOf3DCells+1,1);
4979   int *newConnIPtr=newConnI->getPointer();
4980   *newConnIPtr++=0;
4981   std::vector<int> newc;
4982   for(int j=0;j<nbOf2DCells;j++)
4983     {
4984       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4985       *newConnIPtr++=(int)newc.size();
4986     }
4987   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4988   int *newConnPtr=newConn->getPointer();
4989   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4990   newConnIPtr=newConnI->getPointer();
4991   for(int iz=0;iz<nbOf1DCells;iz++)
4992     {
4993       if(iz!=0)
4994         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4995       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4996         {
4997           int icell=(int)(iter-newc.begin());
4998           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4999             {
5000               if(*iter!=-1)
5001                 *newConnPtr=(*iter)+iz*deltaPerLev;
5002               else
5003                 *newConnPtr=-1;
5004             }
5005           else
5006             *newConnPtr=(*iter);
5007         }
5008     }
5009   ret->setConnectivity(newConn,newConnI,true);
5010   ret->setCoords(getCoords());
5011   return ret;
5012 }
5013
5014 /*!
5015  * Checks if \a this mesh is constituted by only quadratic cells.
5016  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5017  *  \throw If the coordinates array is not set.
5018  *  \throw If the nodal connectivity of cells is not defined.
5019  */
5020 bool MEDCouplingUMesh::isFullyQuadratic() const
5021 {
5022   checkFullyDefined();
5023   bool ret=true;
5024   int nbOfCells=getNumberOfCells();
5025   for(int i=0;i<nbOfCells && ret;i++)
5026     {
5027       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5028       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5029       ret=cm.isQuadratic();
5030     }
5031   return ret;
5032 }
5033
5034 /*!
5035  * Checks if \a this mesh includes any quadratic cell.
5036  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5037  *  \throw If the coordinates array is not set.
5038  *  \throw If the nodal connectivity of cells is not defined.
5039  */
5040 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5041 {
5042   checkFullyDefined();
5043   bool ret=false;
5044   int nbOfCells=getNumberOfCells();
5045   for(int i=0;i<nbOfCells && !ret;i++)
5046     {
5047       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5048       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5049       ret=cm.isQuadratic();
5050     }
5051   return ret;
5052 }
5053
5054 /*!
5055  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5056  * this mesh, it remains unchanged.
5057  *  \throw If the coordinates array is not set.
5058  *  \throw If the nodal connectivity of cells is not defined.
5059  */
5060 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
5061 {
5062   checkFullyDefined();
5063   int nbOfCells=getNumberOfCells();
5064   int delta=0;
5065   const int *iciptr=_nodal_connec_index->getConstPointer();
5066   for(int i=0;i<nbOfCells;i++)
5067     {
5068       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5069       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5070       if(cm.isQuadratic())
5071         {
5072           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5073           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5074           if(!cml.isDynamic())
5075             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5076           else
5077             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5078         }
5079     }
5080   if(delta==0)
5081     return ;
5082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5083   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5084   const int *icptr=_nodal_connec->getConstPointer();
5085   newConn->alloc(getMeshLength()-delta,1);
5086   newConnI->alloc(nbOfCells+1,1);
5087   int *ocptr=newConn->getPointer();
5088   int *ociptr=newConnI->getPointer();
5089   *ociptr=0;
5090   _types.clear();
5091   for(int i=0;i<nbOfCells;i++,ociptr++)
5092     {
5093       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5094       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5095       if(!cm.isQuadratic())
5096         {
5097           _types.insert(type);
5098           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5099           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5100         }
5101       else
5102         {
5103           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5104           _types.insert(typel);
5105           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5106           int newNbOfNodes=cml.getNumberOfNodes();
5107           if(cml.isDynamic())
5108             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5109           *ocptr++=(int)typel;
5110           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5111           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5112         }
5113     }
5114   setConnectivity(newConn,newConnI,false);
5115 }
5116
5117 /*!
5118  * This method converts all linear cell in \a this to quadratic one.
5119  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5120  * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
5121  * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
5122  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5123  * end of the existing coordinates.
5124  * 
5125  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5126  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5127  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5128  * 
5129  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5130  *
5131  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5132  */
5133 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
5134 {
5135   DataArrayInt *conn=0,*connI=0;
5136   DataArrayDouble *coords=0;
5137   std::set<INTERP_KERNEL::NormalizedCellType> types;
5138   checkFullyDefined();
5139   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5140   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5141   int meshDim=getMeshDimension();
5142   switch(conversionType)
5143     {
5144     case 0:
5145       switch(meshDim)
5146         {
5147         case 1:
5148           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5149           connSafe=conn; connISafe=connI; coordsSafe=coords;
5150           break;
5151         case 2:
5152           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5153           connSafe=conn; connISafe=connI; coordsSafe=coords;
5154           break;
5155         case 3:
5156           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5157           connSafe=conn; connISafe=connI; coordsSafe=coords;
5158           break;
5159         default:
5160           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5161         }
5162       break;
5163     case 1:
5164       {
5165         switch(meshDim)
5166         {
5167         case 1:
5168           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5169           connSafe=conn; connISafe=connI; coordsSafe=coords;
5170           break;
5171         case 2:
5172           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5173           connSafe=conn; connISafe=connI; coordsSafe=coords;
5174           break;
5175         case 3:
5176           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5177           connSafe=conn; connISafe=connI; coordsSafe=coords;
5178           break;
5179         default:
5180           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5181         }
5182         break;
5183       }
5184     default:
5185       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5186     }
5187   setConnectivity(connSafe,connISafe,false);
5188   _types=types;
5189   setCoords(coordsSafe);
5190   return ret.retn();
5191 }
5192
5193 /*!
5194  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5195  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5196  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5197  */
5198 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5199 {
5200   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5202   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5203   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5204   int nbOfCells=getNumberOfCells();
5205   int nbOfNodes=getNumberOfNodes();
5206   const int *cPtr=_nodal_connec->getConstPointer();
5207   const int *icPtr=_nodal_connec_index->getConstPointer();
5208   int lastVal=0,offset=nbOfNodes;
5209   for(int i=0;i<nbOfCells;i++,icPtr++)
5210     {
5211       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5212       if(type==INTERP_KERNEL::NORM_SEG2)
5213         {
5214           types.insert(INTERP_KERNEL::NORM_SEG3);
5215           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5216           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5217           newConn->pushBackSilent(offset++);
5218           lastVal+=4;
5219           newConnI->pushBackSilent(lastVal);
5220           ret->pushBackSilent(i);
5221         }
5222       else
5223         {
5224           types.insert(type);
5225           lastVal+=(icPtr[1]-icPtr[0]);
5226           newConnI->pushBackSilent(lastVal);
5227           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5228         }
5229     }
5230   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5231   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5232   return ret.retn();
5233 }
5234
5235 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5236 {
5237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5240   //
5241   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5242   DataArrayInt *conn1D=0,*conn1DI=0;
5243   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5244   DataArrayDouble *coordsTmp=0;
5245   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5246   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5248   const int *c1DPtr=conn1D->begin();
5249   const int *c1DIPtr=conn1DI->begin();
5250   int nbOfCells=getNumberOfCells();
5251   const int *cPtr=_nodal_connec->getConstPointer();
5252   const int *icPtr=_nodal_connec_index->getConstPointer();
5253   int lastVal=0;
5254   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5255     {
5256       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5257       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5258       if(!cm.isQuadratic())
5259         {
5260           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5261           types.insert(typ2); newConn->pushBackSilent(typ2);
5262           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5263           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5264             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5265           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5266           newConnI->pushBackSilent(lastVal);
5267           ret->pushBackSilent(i);
5268         }
5269       else
5270         {
5271           types.insert(typ);
5272           lastVal+=(icPtr[1]-icPtr[0]);
5273           newConnI->pushBackSilent(lastVal);
5274           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5275         }
5276     }
5277   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5278   return ret.retn();
5279 }
5280
5281 /*!
5282  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5283  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5284  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5285  */
5286 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5287 {
5288   
5289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5290   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5291   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5292 }
5293
5294 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5295 {
5296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5297   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5298   //
5299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5302   //
5303   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5304   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5305   DataArrayInt *conn1D=0,*conn1DI=0;
5306   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5307   DataArrayDouble *coordsTmp=0;
5308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5309   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5311   const int *c1DPtr=conn1D->begin();
5312   const int *c1DIPtr=conn1DI->begin();
5313   int nbOfCells=getNumberOfCells();
5314   const int *cPtr=_nodal_connec->getConstPointer();
5315   const int *icPtr=_nodal_connec_index->getConstPointer();
5316   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5317   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5318     {
5319       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5320       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5321       if(!cm.isQuadratic())
5322         {
5323           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5324           types.insert(typ2); newConn->pushBackSilent(typ2);
5325           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5326           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5327             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5328           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5329           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5330           newConnI->pushBackSilent(lastVal);
5331           ret->pushBackSilent(i);
5332         }
5333       else
5334         {
5335           types.insert(typ);
5336           lastVal+=(icPtr[1]-icPtr[0]);
5337           newConnI->pushBackSilent(lastVal);
5338           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5339         }
5340     }
5341   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5342   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5343   return ret.retn();
5344 }
5345
5346 /*!
5347  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5348  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5349  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5350  */
5351 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5352 {
5353   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5354   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5355   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5356 }
5357
5358 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5359 {
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5361   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5363   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5364   //
5365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5367   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5368   //
5369   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5370   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5371   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5372   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5373   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5376   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5378   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5380   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5381   int nbOfCells=getNumberOfCells();
5382   const int *cPtr=_nodal_connec->getConstPointer();
5383   const int *icPtr=_nodal_connec_index->getConstPointer();
5384   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5385   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5386     {
5387       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5388       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5389       if(!cm.isQuadratic())
5390         {
5391           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5392           if(typ2==INTERP_KERNEL::NORM_ERROR)
5393             {
5394               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5395               throw INTERP_KERNEL::Exception(oss.str().c_str());
5396             }
5397           types.insert(typ2); newConn->pushBackSilent(typ2);
5398           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5399           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5400             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5401           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5402             {
5403               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5404               int tmpPos=newConn->getNumberOfTuples();
5405               newConn->pushBackSilent(nodeId2);
5406               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5407             }
5408           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5409           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5410           newConnI->pushBackSilent(lastVal);
5411           ret->pushBackSilent(i);
5412         }
5413       else
5414         {
5415           types.insert(typ);
5416           lastVal+=(icPtr[1]-icPtr[0]);
5417           newConnI->pushBackSilent(lastVal);
5418           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5419         }
5420     }
5421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5422   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5423   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5424   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5425   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5426   int *c=newConn->getPointer();
5427   const int *cI(newConnI->begin());
5428   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5429     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5430   offset=coordsTmp2Safe->getNumberOfTuples();
5431   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5432     c[cI[(*elt)+1]-1]+=offset;
5433   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5434   return ret.retn();
5435 }
5436
5437 /*!
5438  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5439  * so that the number of cells remains the same. Quadratic faces are converted to
5440  * polygons. This method works only for 2D meshes in
5441  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5442  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5443  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5444  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5445  *         a polylinized edge constituting the input polygon.
5446  *  \throw If the coordinates array is not set.
5447  *  \throw If the nodal connectivity of cells is not defined.
5448  *  \throw If \a this->getMeshDimension() != 2.
5449  *  \throw If \a this->getSpaceDimension() != 2.
5450  */
5451 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5452 {
5453   checkFullyDefined();
5454   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5455     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5456   double epsa=fabs(eps);
5457   if(epsa<std::numeric_limits<double>::min())
5458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5463   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5464   revDesc1=0; revDescIndx1=0;
5465   mDesc->tessellate2DCurve(eps);
5466   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5467   setCoords(mDesc->getCoords());
5468 }
5469
5470 /*!
5471  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5472  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5473  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5474  *         a sub-divided edge.
5475  *  \throw If the coordinates array is not set.
5476  *  \throw If the nodal connectivity of cells is not defined.
5477  *  \throw If \a this->getMeshDimension() != 1.
5478  *  \throw If \a this->getSpaceDimension() != 2.
5479  */
5480 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5481 {
5482   checkFullyDefined();
5483   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5484     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5485   double epsa=fabs(eps);
5486   if(epsa<std::numeric_limits<double>::min())
5487     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5488   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5489   int nbCells=getNumberOfCells();
5490   int nbNodes=getNumberOfNodes();
5491   const int *conn=_nodal_connec->getConstPointer();
5492   const int *connI=_nodal_connec_index->getConstPointer();
5493   const double *coords=_coords->getConstPointer();
5494   std::vector<double> addCoo;
5495   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5496   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5497   newConnI->alloc(nbCells+1,1);
5498   int *newConnIPtr=newConnI->getPointer();
5499   *newConnIPtr=0;
5500   int tmp1[3];
5501   INTERP_KERNEL::Node *tmp2[3];
5502   std::set<INTERP_KERNEL::NormalizedCellType> types;
5503   for(int i=0;i<nbCells;i++,newConnIPtr++)
5504     {
5505       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5506       if(cm.isQuadratic())
5507         {//assert(connI[i+1]-connI[i]-1==3)
5508           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5509           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5510           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5511           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5512           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5513           if(eac)
5514             {
5515               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5516               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5517               delete eac;
5518               newConnIPtr[1]=(int)newConn.size();
5519             }
5520           else
5521             {
5522               types.insert(INTERP_KERNEL::NORM_SEG2);
5523               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5524               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5525               newConnIPtr[1]=newConnIPtr[0]+3;
5526             }
5527         }
5528       else
5529         {
5530           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5531           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5532           newConnIPtr[1]=newConnIPtr[0]+3;
5533         }
5534     }
5535   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5536     return ;
5537   _types=types;
5538   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5539   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5540   newConnArr->alloc((int)newConn.size(),1);
5541   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5542   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5543   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5544   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5545   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5546   std::copy(addCoo.begin(),addCoo.end(),work);
5547   DataArrayDouble::SetArrayIn(newCoords,_coords);
5548   updateTime();
5549 }
5550
5551 /*!
5552  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5553  * In addition, returns an array mapping new cells to old ones. <br>
5554  * This method typically increases the number of cells in \a this mesh
5555  * but the number of nodes remains \b unchanged.
5556  * That's why the 3D splitting policies
5557  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5558  *  \param [in] policy - specifies a pattern used for splitting.
5559  * The semantic of \a policy is:
5560  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5561  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5562  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5563  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5564  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5565  *          an id of old cell producing it. The caller is to delete this array using
5566  *         decrRef() as it is no more needed. 
5567  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5568  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5569  *          and \a this->getMeshDimension() != 3. 
5570  *  \throw If \a policy is not one of the four discussed above.
5571  *  \throw If the nodal connectivity of cells is not defined.
5572  */
5573 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5574 {
5575   switch(policy)
5576     {
5577     case 0:
5578       return simplexizePol0();
5579     case 1:
5580       return simplexizePol1();
5581     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5582       return simplexizePlanarFace5();
5583     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5584       return simplexizePlanarFace6();
5585     default:
5586       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n  - 0 or 1 (only available for meshdim=2) \n  - PLANAR_FACE_5, PLANAR_FACE_6  (only for meshdim=3)");
5587     }
5588 }
5589
5590 /*!
5591  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5592  * - 1D: INTERP_KERNEL::NORM_SEG2
5593  * - 2D: INTERP_KERNEL::NORM_TRI3
5594  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5595  *
5596  * This method is useful for users that need to use P1 field services as
5597  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5598  * All these methods need mesh support containing only simplex cells.
5599  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5600  *  \throw If the coordinates array is not set.
5601  *  \throw If the nodal connectivity of cells is not defined.
5602  *  \throw If \a this->getMeshDimension() < 1.
5603  */
5604 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5605 {
5606   checkFullyDefined();
5607   int mdim=getMeshDimension();
5608   if(mdim<1 || mdim>3)
5609     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5610   int nbCells=getNumberOfCells();
5611   const int *conn=_nodal_connec->getConstPointer();
5612   const int *connI=_nodal_connec_index->getConstPointer();
5613   for(int i=0;i<nbCells;i++)
5614     {
5615       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5616       if(!cm.isSimplex())
5617         return false;
5618     }
5619   return true;
5620 }
5621
5622 /*!
5623  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5624  */
5625 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5626 {
5627   checkConnectivityFullyDefined();
5628   if(getMeshDimension()!=2)
5629     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5630   int nbOfCells=getNumberOfCells();
5631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5632   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5633   ret->alloc(nbOfCells+nbOfCutCells,1);
5634   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5635   int *retPt=ret->getPointer();
5636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5638   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5639   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5640   int *pt=newConn->getPointer();
5641   int *ptI=newConnI->getPointer();
5642   ptI[0]=0;
5643   const int *oldc=_nodal_connec->getConstPointer();
5644   const int *ci=_nodal_connec_index->getConstPointer();
5645   for(int i=0;i<nbOfCells;i++,ci++)
5646     {
5647       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5648         {
5649           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5650                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5651           pt=std::copy(tmp,tmp+8,pt);
5652           ptI[1]=ptI[0]+4;
5653           ptI[2]=ptI[0]+8;
5654           *retPt++=i;
5655           *retPt++=i;
5656           ptI+=2;
5657         }
5658       else
5659         {
5660           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5661           ptI[1]=ptI[0]+ci[1]-ci[0];
5662           ptI++;
5663           *retPt++=i;
5664         }
5665     }
5666   _nodal_connec->decrRef();
5667   _nodal_connec=newConn.retn();
5668   _nodal_connec_index->decrRef();
5669   _nodal_connec_index=newConnI.retn();
5670   computeTypes();
5671   updateTime();
5672   return ret.retn();
5673 }
5674
5675 /*!
5676  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5677  */
5678 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5679 {
5680   checkConnectivityFullyDefined();
5681   if(getMeshDimension()!=2)
5682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5683   int nbOfCells=getNumberOfCells();
5684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5685   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5686   ret->alloc(nbOfCells+nbOfCutCells,1);
5687   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5688   int *retPt=ret->getPointer();
5689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5691   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5692   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5693   int *pt=newConn->getPointer();
5694   int *ptI=newConnI->getPointer();
5695   ptI[0]=0;
5696   const int *oldc=_nodal_connec->getConstPointer();
5697   const int *ci=_nodal_connec_index->getConstPointer();
5698   for(int i=0;i<nbOfCells;i++,ci++)
5699     {
5700       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5701         {
5702           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5703                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5704           pt=std::copy(tmp,tmp+8,pt);
5705           ptI[1]=ptI[0]+4;
5706           ptI[2]=ptI[0]+8;
5707           *retPt++=i;
5708           *retPt++=i;
5709           ptI+=2;
5710         }
5711       else
5712         {
5713           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5714           ptI[1]=ptI[0]+ci[1]-ci[0];
5715           ptI++;
5716           *retPt++=i;
5717         }
5718     }
5719   _nodal_connec->decrRef();
5720   _nodal_connec=newConn.retn();
5721   _nodal_connec_index->decrRef();
5722   _nodal_connec_index=newConnI.retn();
5723   computeTypes();
5724   updateTime();
5725   return ret.retn();
5726 }
5727
5728 /*!
5729  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5730  */
5731 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5732 {
5733   checkConnectivityFullyDefined();
5734   if(getMeshDimension()!=3)
5735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5736   int nbOfCells=getNumberOfCells();
5737   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5738   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5739   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5740   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5741   int *retPt=ret->getPointer();
5742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5744   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5745   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5746   int *pt=newConn->getPointer();
5747   int *ptI=newConnI->getPointer();
5748   ptI[0]=0;
5749   const int *oldc=_nodal_connec->getConstPointer();
5750   const int *ci=_nodal_connec_index->getConstPointer();
5751   for(int i=0;i<nbOfCells;i++,ci++)
5752     {
5753       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5754         {
5755           for(int j=0;j<5;j++,pt+=5,ptI++)
5756             {
5757               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5758               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5759               *retPt++=i;
5760               ptI[1]=ptI[0]+5;
5761             }
5762         }
5763       else
5764         {
5765           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5766           ptI[1]=ptI[0]+ci[1]-ci[0];
5767           ptI++;
5768           *retPt++=i;
5769         }
5770     }
5771   _nodal_connec->decrRef();
5772   _nodal_connec=newConn.retn();
5773   _nodal_connec_index->decrRef();
5774   _nodal_connec_index=newConnI.retn();
5775   computeTypes();
5776   updateTime();
5777   return ret.retn();
5778 }
5779
5780 /*!
5781  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5782  */
5783 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5784 {
5785   checkConnectivityFullyDefined();
5786   if(getMeshDimension()!=3)
5787     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5788   int nbOfCells=getNumberOfCells();
5789   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5790   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5791   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5792   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5793   int *retPt=ret->getPointer();
5794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5796   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5797   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5798   int *pt=newConn->getPointer();
5799   int *ptI=newConnI->getPointer();
5800   ptI[0]=0;
5801   const int *oldc=_nodal_connec->getConstPointer();
5802   const int *ci=_nodal_connec_index->getConstPointer();
5803   for(int i=0;i<nbOfCells;i++,ci++)
5804     {
5805       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5806         {
5807           for(int j=0;j<6;j++,pt+=5,ptI++)
5808             {
5809               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5810               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5811               *retPt++=i;
5812               ptI[1]=ptI[0]+5;
5813             }
5814         }
5815       else
5816         {
5817           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5818           ptI[1]=ptI[0]+ci[1]-ci[0];
5819           ptI++;
5820           *retPt++=i;
5821         }
5822     }
5823   _nodal_connec->decrRef();
5824   _nodal_connec=newConn.retn();
5825   _nodal_connec_index->decrRef();
5826   _nodal_connec_index=newConnI.retn();
5827   computeTypes();
5828   updateTime();
5829   return ret.retn();
5830 }
5831
5832 /*!
5833  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5834  * This method completly ignore coordinates.
5835  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5836  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5837  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5838  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5839  */
5840 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5841 {
5842   checkFullyDefined();
5843   if(getMeshDimension()!=2)
5844     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5845   int nbOfCells=getNumberOfCells();
5846   int *connI=_nodal_connec_index->getPointer();
5847   int newConnLgth=0;
5848   for(int i=0;i<nbOfCells;i++,connI++)
5849     {
5850       int offset=descIndex[i];
5851       int nbOfEdges=descIndex[i+1]-offset;
5852       //
5853       bool ddirect=desc[offset+nbOfEdges-1]>0;
5854       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5855       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5856       for(int j=0;j<nbOfEdges;j++)
5857         {
5858           bool direct=desc[offset+j]>0;
5859           int edgeId=std::abs(desc[offset+j])-1;
5860           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5861             {
5862               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5863               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5864               int ref2=direct?id1:id2;
5865               if(ref==ref2)
5866                 {
5867                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5868                   newConnLgth+=nbOfSubNodes-1;
5869                   ref=direct?id2:id1;
5870                 }
5871               else
5872                 {
5873                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5874                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5875                 }
5876             }
5877           else
5878             {
5879               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5880             }
5881         }
5882       newConnLgth++;//+1 is for cell type
5883       connI[1]=newConnLgth;
5884     }
5885   //
5886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5887   newConn->alloc(newConnLgth,1);
5888   int *work=newConn->getPointer();
5889   for(int i=0;i<nbOfCells;i++)
5890     {
5891       *work++=INTERP_KERNEL::NORM_POLYGON;
5892       int offset=descIndex[i];
5893       int nbOfEdges=descIndex[i+1]-offset;
5894       for(int j=0;j<nbOfEdges;j++)
5895         {
5896           bool direct=desc[offset+j]>0;
5897           int edgeId=std::abs(desc[offset+j])-1;
5898           if(direct)
5899             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5900           else
5901             {
5902               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5903               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5904               work=std::copy(it,it+nbOfSubNodes-1,work);
5905             }
5906         }
5907     }
5908   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5909   _types.clear();
5910   if(nbOfCells>0)
5911     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5912 }
5913
5914 /*!
5915  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5916  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5917  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5918  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5919  * so it can be useful to call mergeNodes() before calling this method.
5920  *  \throw If \a this->getMeshDimension() <= 1.
5921  *  \throw If the coordinates array is not set.
5922  *  \throw If the nodal connectivity of cells is not defined.
5923  */
5924 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5925 {
5926   checkFullyDefined();
5927   if(getMeshDimension()<=1)
5928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5929   int nbOfCells=getNumberOfCells();
5930   if(nbOfCells<1)
5931     return ;
5932   int initMeshLgth=getMeshLength();
5933   int *conn=_nodal_connec->getPointer();
5934   int *index=_nodal_connec_index->getPointer();
5935   int posOfCurCell=0;
5936   int newPos=0;
5937   int lgthOfCurCell;
5938   for(int i=0;i<nbOfCells;i++)
5939     {
5940       lgthOfCurCell=index[i+1]-posOfCurCell;
5941       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5942       int newLgth;
5943       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5944                                                                                                      conn+newPos+1,newLgth);
5945       conn[newPos]=newType;
5946       newPos+=newLgth+1;
5947       posOfCurCell=index[i+1];
5948       index[i+1]=newPos;
5949     }
5950   if(newPos!=initMeshLgth)
5951     _nodal_connec->reAlloc(newPos);
5952   computeTypes();
5953 }
5954
5955 /*!
5956  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5957  * A cell is considered to be oriented correctly if an angle between its
5958  * normal vector and a given vector is less than \c PI / \c 2.
5959  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5960  *         cells. 
5961  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5962  *         checked.
5963  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5964  *         is not cleared before filling in.
5965  *  \throw If \a this->getMeshDimension() != 2.
5966  *  \throw If \a this->getSpaceDimension() != 3.
5967  *
5968  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5969  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5970  */
5971 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5972 {
5973   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5974     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5975   int nbOfCells=getNumberOfCells();
5976   const int *conn=_nodal_connec->getConstPointer();
5977   const int *connI=_nodal_connec_index->getConstPointer();
5978   const double *coordsPtr=_coords->getConstPointer();
5979   for(int i=0;i<nbOfCells;i++)
5980     {
5981       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5982       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5983         {
5984           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5985           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5986             cells.push_back(i);
5987         }
5988     }
5989 }
5990
5991 /*!
5992  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5993  * considered to be oriented correctly if an angle between its normal vector and a
5994  * given vector is less than \c PI / \c 2. 
5995  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5996  *         cells. 
5997  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5998  *         checked.
5999  *  \throw If \a this->getMeshDimension() != 2.
6000  *  \throw If \a this->getSpaceDimension() != 3.
6001  *
6002  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6003  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6004  */
6005 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
6006 {
6007   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6008     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6009   int nbOfCells=getNumberOfCells();
6010   int *conn=_nodal_connec->getPointer();
6011   const int *connI=_nodal_connec_index->getConstPointer();
6012   const double *coordsPtr=_coords->getConstPointer();
6013   bool isModified=false;
6014   for(int i=0;i<nbOfCells;i++)
6015     {
6016       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6017       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6018         {
6019           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6020           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6021             {
6022               isModified=true;
6023               std::vector<int> tmp(connI[i+1]-connI[i]-2);
6024               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
6025               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
6026             }
6027         }
6028     }
6029   if(isModified)
6030     _nodal_connec->declareAsNew();
6031   updateTime();
6032 }
6033
6034 /*!
6035  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6036  * oriented facets. The normal vector of the facet should point out of the cell.
6037  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6038  *         is not cleared before filling in.
6039  *  \throw If \a this->getMeshDimension() != 3.
6040  *  \throw If \a this->getSpaceDimension() != 3.
6041  *  \throw If the coordinates array is not set.
6042  *  \throw If the nodal connectivity of cells is not defined.
6043  *
6044  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6045  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6046  */
6047 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
6048 {
6049   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6050     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6051   int nbOfCells=getNumberOfCells();
6052   const int *conn=_nodal_connec->getConstPointer();
6053   const int *connI=_nodal_connec_index->getConstPointer();
6054   const double *coordsPtr=_coords->getConstPointer();
6055   for(int i=0;i<nbOfCells;i++)
6056     {
6057       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6058       if(type==INTERP_KERNEL::NORM_POLYHED)
6059         {
6060           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6061             cells.push_back(i);
6062         }
6063     }
6064 }
6065
6066 /*!
6067  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6068  * out of the cell. 
6069  *  \throw If \a this->getMeshDimension() != 3.
6070  *  \throw If \a this->getSpaceDimension() != 3.
6071  *  \throw If the coordinates array is not set.
6072  *  \throw If the nodal connectivity of cells is not defined.
6073  *  \throw If the reparation fails.
6074  *
6075  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6076  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6077  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6078  */
6079 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
6080 {
6081   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6082     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6083   int nbOfCells=getNumberOfCells();
6084   int *conn=_nodal_connec->getPointer();
6085   const int *connI=_nodal_connec_index->getConstPointer();
6086   const double *coordsPtr=_coords->getConstPointer();
6087   for(int i=0;i<nbOfCells;i++)
6088     {
6089       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6090       if(type==INTERP_KERNEL::NORM_POLYHED)
6091         {
6092           try
6093             {
6094               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6095                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6096             }
6097           catch(INTERP_KERNEL::Exception& e)
6098             {
6099               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6100               throw INTERP_KERNEL::Exception(oss.str().c_str());
6101             }
6102         }
6103     }
6104   updateTime();
6105 }
6106
6107 /*!
6108  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6109  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6110  * according to which the first facet of the cell should be oriented to have the normal vector
6111  * pointing out of cell.
6112  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6113  *         cells. The caller is to delete this array using decrRef() as it is no more
6114  *         needed. 
6115  *  \throw If \a this->getMeshDimension() != 3.
6116  *  \throw If \a this->getSpaceDimension() != 3.
6117  *  \throw If the coordinates array is not set.
6118  *  \throw If the nodal connectivity of cells is not defined.
6119  *
6120  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6121  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6122  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6123  */
6124 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
6125 {
6126   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6127   if(getMeshDimension()!=3)
6128     throw INTERP_KERNEL::Exception(msg);
6129   int spaceDim=getSpaceDimension();
6130   if(spaceDim!=3)
6131     throw INTERP_KERNEL::Exception(msg);
6132   //
6133   int nbOfCells=getNumberOfCells();
6134   int *conn=_nodal_connec->getPointer();
6135   const int *connI=_nodal_connec_index->getConstPointer();
6136   const double *coo=getCoords()->getConstPointer();
6137   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6138   for(int i=0;i<nbOfCells;i++)
6139     {
6140       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6141       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6142         {
6143           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6144             {
6145               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6146               cells->pushBackSilent(i);
6147             }
6148         }
6149     }
6150   return cells.retn();
6151 }
6152
6153 /*!
6154  * This method is a faster method to correct orientation of all 3D cells in \a this.
6155  * This method works only if \a this is a 3D mesh, that is to say a mesh with mesh dimension 3 and a space dimension 3.
6156  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6157  * 
6158  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6159  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6160  */
6161 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
6162 {
6163   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6164     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6165   int nbOfCells=getNumberOfCells();
6166   int *conn=_nodal_connec->getPointer();
6167   const int *connI=_nodal_connec_index->getConstPointer();
6168   const double *coordsPtr=_coords->getConstPointer();
6169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6170   for(int i=0;i<nbOfCells;i++)
6171     {
6172       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6173       switch(type)
6174         {
6175         case INTERP_KERNEL::NORM_TETRA4:
6176           {
6177             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6178               {
6179                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6180                 ret->pushBackSilent(i);
6181               }
6182             break;
6183           }
6184         case INTERP_KERNEL::NORM_PYRA5:
6185           {
6186             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6187               {
6188                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6189                 ret->pushBackSilent(i);
6190               }
6191             break;
6192           }
6193         case INTERP_KERNEL::NORM_PENTA6:
6194         case INTERP_KERNEL::NORM_HEXA8:
6195         case INTERP_KERNEL::NORM_HEXGP12:
6196           {
6197             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6198               {
6199                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6200                 ret->pushBackSilent(i);
6201               }
6202             break;
6203           }
6204         case INTERP_KERNEL::NORM_POLYHED:
6205           {
6206             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6207               {
6208                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6209                 ret->pushBackSilent(i);
6210               }
6211             break;
6212           }
6213         default:
6214           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !");
6215         }
6216     }
6217   updateTime();
6218   return ret.retn();
6219 }
6220
6221 /*!
6222  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6223  * If it is not the case an exception will be thrown.
6224  * This method is fast because the first cell of \a this is used to compute the plane.
6225  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6226  * \param pos output of size at least 3 used to store a point owned of searched plane.
6227  */
6228 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
6229 {
6230   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6231     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6232   const int *conn=_nodal_connec->getConstPointer();
6233   const int *connI=_nodal_connec_index->getConstPointer();
6234   const double *coordsPtr=_coords->getConstPointer();
6235   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6236   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6237 }
6238
6239 /*!
6240  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6241  * cells. Currently cells of the following types are treated:
6242  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6243  * For a cell of other type an exception is thrown.
6244  * Space dimension of a 2D mesh can be either 2 or 3.
6245  * The Edge Ratio of a cell \f$t\f$ is: 
6246  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6247  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6248  *  the smallest edge lengths of \f$t\f$.
6249  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6250  *          cells and one time, lying on \a this mesh. The caller is to delete this
6251  *          field using decrRef() as it is no more needed. 
6252  *  \throw If the coordinates array is not set.
6253  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6254  *  \throw If the connectivity data array has more than one component.
6255  *  \throw If the connectivity data array has a named component.
6256  *  \throw If the connectivity index data array has more than one component.
6257  *  \throw If the connectivity index data array has a named component.
6258  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6259  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6260  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6261  */
6262 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
6263 {
6264   checkCoherency();
6265   int spaceDim=getSpaceDimension();
6266   int meshDim=getMeshDimension();
6267   if(spaceDim!=2 && spaceDim!=3)
6268     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6269   if(meshDim!=2 && meshDim!=3)
6270     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6271   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6272   ret->setMesh(this);
6273   int nbOfCells=getNumberOfCells();
6274   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6275   arr->alloc(nbOfCells,1);
6276   double *pt=arr->getPointer();
6277   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6278   const int *conn=_nodal_connec->getConstPointer();
6279   const int *connI=_nodal_connec_index->getConstPointer();
6280   const double *coo=_coords->getConstPointer();
6281   double tmp[12];
6282   for(int i=0;i<nbOfCells;i++,pt++)
6283     {
6284       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6285       switch(t)
6286         {
6287           case INTERP_KERNEL::NORM_TRI3:
6288             {
6289               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6290               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6291               break;
6292             }
6293           case INTERP_KERNEL::NORM_QUAD4:
6294             {
6295               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6296               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6297               break;
6298             }
6299           case INTERP_KERNEL::NORM_TETRA4:
6300             {
6301               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6302               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6303               break;
6304             }
6305         default:
6306           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6307         }
6308       conn+=connI[i+1]-connI[i];
6309     }
6310   ret->setName("EdgeRatio");
6311   ret->synchronizeTimeWithSupport();
6312   return ret.retn();
6313 }
6314
6315 /*!
6316  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6317  * cells. Currently cells of the following types are treated:
6318  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6319  * For a cell of other type an exception is thrown.
6320  * Space dimension of a 2D mesh can be either 2 or 3.
6321  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6322  *          cells and one time, lying on \a this mesh. The caller is to delete this
6323  *          field using decrRef() as it is no more needed. 
6324  *  \throw If the coordinates array is not set.
6325  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6326  *  \throw If the connectivity data array has more than one component.
6327  *  \throw If the connectivity data array has a named component.
6328  *  \throw If the connectivity index data array has more than one component.
6329  *  \throw If the connectivity index data array has a named component.
6330  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6331  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6332  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6333  */
6334 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6335 {
6336   checkCoherency();
6337   int spaceDim=getSpaceDimension();
6338   int meshDim=getMeshDimension();
6339   if(spaceDim!=2 && spaceDim!=3)
6340     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6341   if(meshDim!=2 && meshDim!=3)
6342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6343   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6344   ret->setMesh(this);
6345   int nbOfCells=getNumberOfCells();
6346   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6347   arr->alloc(nbOfCells,1);
6348   double *pt=arr->getPointer();
6349   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6350   const int *conn=_nodal_connec->getConstPointer();
6351   const int *connI=_nodal_connec_index->getConstPointer();
6352   const double *coo=_coords->getConstPointer();
6353   double tmp[12];
6354   for(int i=0;i<nbOfCells;i++,pt++)
6355     {
6356       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6357       switch(t)
6358         {
6359           case INTERP_KERNEL::NORM_TRI3:
6360             {
6361               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6362               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6363               break;
6364             }
6365           case INTERP_KERNEL::NORM_QUAD4:
6366             {
6367               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6368               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6369               break;
6370             }
6371           case INTERP_KERNEL::NORM_TETRA4:
6372             {
6373               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6374               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6375               break;
6376             }
6377         default:
6378           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6379         }
6380       conn+=connI[i+1]-connI[i];
6381     }
6382   ret->setName("AspectRatio");
6383   ret->synchronizeTimeWithSupport();
6384   return ret.retn();
6385 }
6386
6387 /*!
6388  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6389  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6390  * treated: INTERP_KERNEL::NORM_QUAD4.
6391  * For a cell of other type an exception is thrown.
6392  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6393  *          cells and one time, lying on \a this mesh. The caller is to delete this
6394  *          field using decrRef() as it is no more needed. 
6395  *  \throw If the coordinates array is not set.
6396  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6397  *  \throw If the connectivity data array has more than one component.
6398  *  \throw If the connectivity data array has a named component.
6399  *  \throw If the connectivity index data array has more than one component.
6400  *  \throw If the connectivity index data array has a named component.
6401  *  \throw If \a this->getMeshDimension() != 2.
6402  *  \throw If \a this->getSpaceDimension() != 3.
6403  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6404  */
6405 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6406 {
6407   checkCoherency();
6408   int spaceDim=getSpaceDimension();
6409   int meshDim=getMeshDimension();
6410   if(spaceDim!=3)
6411     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6412   if(meshDim!=2)
6413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6414   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6415   ret->setMesh(this);
6416   int nbOfCells=getNumberOfCells();
6417   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6418   arr->alloc(nbOfCells,1);
6419   double *pt=arr->getPointer();
6420   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6421   const int *conn=_nodal_connec->getConstPointer();
6422   const int *connI=_nodal_connec_index->getConstPointer();
6423   const double *coo=_coords->getConstPointer();
6424   double tmp[12];
6425   for(int i=0;i<nbOfCells;i++,pt++)
6426     {
6427       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6428       switch(t)
6429         {
6430           case INTERP_KERNEL::NORM_QUAD4:
6431             {
6432               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6433               *pt=INTERP_KERNEL::quadWarp(tmp);
6434               break;
6435             }
6436         default:
6437           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6438         }
6439       conn+=connI[i+1]-connI[i];
6440     }
6441   ret->setName("Warp");
6442   ret->synchronizeTimeWithSupport();
6443   return ret.retn();
6444 }
6445
6446
6447 /*!
6448  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6449  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6450  * treated: INTERP_KERNEL::NORM_QUAD4.
6451  * For a cell of other type an exception is thrown.
6452  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6453  *          cells and one time, lying on \a this mesh. The caller is to delete this
6454  *          field using decrRef() as it is no more needed. 
6455  *  \throw If the coordinates array is not set.
6456  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6457  *  \throw If the connectivity data array has more than one component.
6458  *  \throw If the connectivity data array has a named component.
6459  *  \throw If the connectivity index data array has more than one component.
6460  *  \throw If the connectivity index data array has a named component.
6461  *  \throw If \a this->getMeshDimension() != 2.
6462  *  \throw If \a this->getSpaceDimension() != 3.
6463  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6464  */
6465 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6466 {
6467   checkCoherency();
6468   int spaceDim=getSpaceDimension();
6469   int meshDim=getMeshDimension();
6470   if(spaceDim!=3)
6471     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6472   if(meshDim!=2)
6473     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6474   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6475   ret->setMesh(this);
6476   int nbOfCells=getNumberOfCells();
6477   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6478   arr->alloc(nbOfCells,1);
6479   double *pt=arr->getPointer();
6480   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6481   const int *conn=_nodal_connec->getConstPointer();
6482   const int *connI=_nodal_connec_index->getConstPointer();
6483   const double *coo=_coords->getConstPointer();
6484   double tmp[12];
6485   for(int i=0;i<nbOfCells;i++,pt++)
6486     {
6487       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6488       switch(t)
6489         {
6490           case INTERP_KERNEL::NORM_QUAD4:
6491             {
6492               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6493               *pt=INTERP_KERNEL::quadSkew(tmp);
6494               break;
6495             }
6496         default:
6497           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6498         }
6499       conn+=connI[i+1]-connI[i];
6500     }
6501   ret->setName("Skew");
6502   ret->synchronizeTimeWithSupport();
6503   return ret.retn();
6504 }
6505
6506 /*!
6507  * This method aggregate the bbox of each cell and put it into bbox parameter.
6508  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6509  */
6510 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6511 {
6512   int spaceDim=getSpaceDimension();
6513   int nbOfCells=getNumberOfCells();
6514   bbox.resize(2*nbOfCells*spaceDim);
6515   for(int i=0;i<nbOfCells*spaceDim;i++)
6516     {
6517       bbox[2*i]=std::numeric_limits<double>::max();
6518       bbox[2*i+1]=-std::numeric_limits<double>::max();
6519     }
6520   const double *coordsPtr=_coords->getConstPointer();
6521   const int *conn=_nodal_connec->getConstPointer();
6522   const int *connI=_nodal_connec_index->getConstPointer();
6523   for(int i=0;i<nbOfCells;i++)
6524     {
6525       int offset=connI[i]+1;
6526       int nbOfNodesForCell=connI[i+1]-offset;
6527       for(int j=0;j<nbOfNodesForCell;j++)
6528         {
6529           int nodeId=conn[offset+j];
6530           if(nodeId>=0)
6531             for(int k=0;k<spaceDim;k++)
6532               {
6533                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6534                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6535               }
6536         }
6537     }
6538 }
6539
6540 /// @cond INTERNAL
6541
6542 namespace ParaMEDMEMImpl
6543 {
6544   class ConnReader
6545   {
6546   public:
6547     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6548     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6549   private:
6550     const int *_conn;
6551     int _val;
6552   };
6553
6554   class ConnReader2
6555   {
6556   public:
6557     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6558     bool operator() (const int& pos) { return _conn[pos]==_val; }
6559   private:
6560     const int *_conn;
6561     int _val;
6562   };
6563 }
6564
6565 /// @endcond
6566
6567 /*!
6568  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6569  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6570  * \a this is composed in cell types.
6571  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6572  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6573  * This parameter is kept only for compatibility with other methode listed above.
6574  */
6575 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6576 {
6577   checkConnectivityFullyDefined();
6578   const int *conn=_nodal_connec->getConstPointer();
6579   const int *connI=_nodal_connec_index->getConstPointer();
6580   const int *work=connI;
6581   int nbOfCells=getNumberOfCells();
6582   std::size_t n=getAllTypes().size();
6583   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6584   std::set<INTERP_KERNEL::NormalizedCellType> types;
6585   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6586     {
6587       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6588       if(types.find(typ)!=types.end())
6589         {
6590           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6591           oss << " is not contiguous !";
6592           throw INTERP_KERNEL::Exception(oss.str().c_str());
6593         }
6594       types.insert(typ);
6595       ret[3*i]=typ;
6596       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6597       ret[3*i+1]=(int)std::distance(work,work2);
6598       work=work2;
6599     }
6600   return ret;
6601 }
6602
6603 /*!
6604  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6605  * only for types cell, type node is not managed.
6606  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6607  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6608  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6609  * If 2 or more same geometric type is in \a code and exception is thrown too.
6610  *
6611  * This method firstly checks
6612  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6613  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6614  * an exception is thrown too.
6615  * 
6616  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6617  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6618  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6619  */
6620 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6621 {
6622   if(code.empty())
6623     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6624   std::size_t sz=code.size();
6625   std::size_t n=sz/3;
6626   if(sz%3!=0)
6627     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6628   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6629   int nb=0;
6630   for(std::size_t i=0;i<n;i++)
6631     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6632       {
6633         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6634         nb+=code[3*i+1];
6635         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6636           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6637       }
6638   if(types.size()!=n)
6639     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6640   if(idsPerType.empty())
6641     {
6642       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6643         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6644       if(types.size()==_types.size())
6645         return 0;
6646     }
6647   DataArrayInt *ret=DataArrayInt::New();
6648   ret->alloc(nb,1);
6649   int *retPtr=ret->getPointer();
6650   const int *connI=_nodal_connec_index->getConstPointer();
6651   const int *conn=_nodal_connec->getConstPointer();
6652   int nbOfCells=getNumberOfCells();
6653   const int *i=connI;
6654   int kk=0;
6655   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6656     {
6657       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6658       int offset=(int)std::distance(connI,i);
6659       if(code[3*kk+2]==-1)
6660         {
6661           const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6662           std::size_t pos2=std::distance(i,j);
6663           for(std::size_t k=0;k<pos2;k++)
6664             *retPtr++=(int)k+offset;
6665           i=j;
6666         }
6667       else
6668         {
6669           retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6670                                 retPtr,std::bind2nd(std::plus<int>(),offset));
6671         }
6672     }
6673   return ret;
6674 }
6675
6676 /*!
6677  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6678  * This method is the opposite of MEDCouplingUMesh::checkTypeConsistencyAndContig method. Given a list of cells in \a profile it returns a list of sub-profiles sorted by geo type.
6679  * The result is put in the array \a idsPerType. In the returned parameter \a code, foreach i \a code[3*i+2] refers (if different from -1) to a location into the \a idsPerType.
6680  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6681  * 
6682  * \param [out] code is a vector of size 3*n where n is the number of different geometric type in \a this \b reduced to the profile \a profile. \a code has exactly the same semantic than in MEDCouplingUMesh::checkTypeConsistencyAndContig method.
6683  * \param [out] idsInPflPerType is a vector of size of different geometric type in the subpart defined by \a profile of \a this ( equal to \a code.size()/3). For each i,
6684  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6685  * \param [out] idsPerType is a vector of size of different sub profiles needed to be defined to represent the profile \a profile for a given geometric type.
6686  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6687  * \throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if \a this is not fully defined
6688  */
6689 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6690 {
6691   if(!profile)
6692     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6693   if(profile->getNumberOfComponents()!=1)
6694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6695   checkConnectivityFullyDefined();
6696   const int *conn=_nodal_connec->getConstPointer();
6697   const int *connI=_nodal_connec_index->getConstPointer();
6698   int nbOfCells=getNumberOfCells();
6699   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6700   std::vector<int> typeRangeVals(1);
6701   for(const int *i=connI;i!=connI+nbOfCells;)
6702     {
6703       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6704       if(std::find(types.begin(),types.end(),curType)!=types.end())
6705         {
6706           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6707         }
6708       types.push_back(curType);
6709       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6710       typeRangeVals.push_back((int)std::distance(connI,i));
6711     }
6712   //
6713   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6714   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6715   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6716   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6717   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6718   //
6719   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6720   code.resize(3*nbOfCastsFinal);
6721   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6722   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6723   for(int i=0;i<nbOfCastsFinal;i++)
6724     {
6725       int castId=castsPresent->getIJ(i,0);
6726       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6727       idsInPflPerType2.push_back(tmp3);
6728       code[3*i]=(int)types[castId];
6729       code[3*i+1]=tmp3->getNumberOfTuples();
6730       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6731       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6732         {
6733           tmp4->copyStringInfoFrom(*profile);
6734           idsPerType2.push_back(tmp4);
6735           code[3*i+2]=(int)idsPerType2.size()-1;
6736         }
6737       else
6738         {
6739           code[3*i+2]=-1;
6740         }
6741     }
6742   std::size_t sz2=idsInPflPerType2.size();
6743   idsInPflPerType.resize(sz2);
6744   for(std::size_t i=0;i<sz2;i++)
6745     {
6746       DataArrayInt *locDa=idsInPflPerType2[i];
6747       locDa->incrRef();
6748       idsInPflPerType[i]=locDa;
6749     }
6750   std::size_t sz=idsPerType2.size();
6751   idsPerType.resize(sz);
6752   for(std::size_t i=0;i<sz;i++)
6753     {
6754       DataArrayInt *locDa=idsPerType2[i];
6755       locDa->incrRef();
6756       idsPerType[i]=locDa;
6757     }
6758 }
6759
6760 /*!
6761  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6762  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6763  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6764  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
6765  */
6766 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6767 {
6768   checkFullyDefined();
6769   nM1LevMesh->checkFullyDefined();
6770   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6772   if(_coords!=nM1LevMesh->getCoords())
6773     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6774   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6776   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6777   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6778   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6779   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6780   tmp->setConnectivity(tmp0,tmp1);
6781   tmp->renumberCells(ret0->getConstPointer(),false);
6782   revDesc=tmp->getNodalConnectivity();
6783   revDescIndx=tmp->getNodalConnectivityIndex();
6784   DataArrayInt *ret=0;
6785   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6786     {
6787       int tmp2;
6788       ret->getMaxValue(tmp2);
6789       ret->decrRef();
6790       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6791       throw INTERP_KERNEL::Exception(oss.str().c_str());
6792     }
6793   nM1LevMeshIds=ret;
6794   //
6795   revDesc->incrRef();
6796   revDescIndx->incrRef();
6797   ret1->incrRef();
6798   ret0->incrRef();
6799   meshnM1Old2New=ret0;
6800   return ret1;
6801 }
6802
6803 /*!
6804  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6805  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6806  * in "Old to New" mode.
6807  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6808  *          this array using decrRef() as it is no more needed.
6809  *  \throw If the nodal connectivity of cells is not defined.
6810  */
6811 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6812 {
6813   checkConnectivityFullyDefined();
6814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6815   renumberCells(ret->getConstPointer(),false);
6816   return ret.retn();
6817 }
6818
6819 /*!
6820  * This methods checks that cells are sorted by their types.
6821  * This method makes asumption (no check) that connectivity is correctly set before calling.
6822  */
6823 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6824 {
6825   checkFullyDefined();
6826   const int *conn=_nodal_connec->getConstPointer();
6827   const int *connI=_nodal_connec_index->getConstPointer();
6828   int nbOfCells=getNumberOfCells();
6829   std::set<INTERP_KERNEL::NormalizedCellType> types;
6830   for(const int *i=connI;i!=connI+nbOfCells;)
6831     {
6832       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6833       if(types.find(curType)!=types.end())
6834         return false;
6835       types.insert(curType);
6836       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6837     }
6838   return true;
6839 }
6840
6841 /*!
6842  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6843  * The geometric type order is specified by MED file.
6844  * 
6845  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6846  */
6847 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6848 {
6849   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6850 }
6851
6852 /*!
6853  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6854  * that the order is specified in array defined by [orderBg,orderEnd).
6855  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6856  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6857  */
6858 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6859 {
6860   checkFullyDefined();
6861   const int *conn=_nodal_connec->getConstPointer();
6862   const int *connI=_nodal_connec_index->getConstPointer();
6863   int nbOfCells=getNumberOfCells();
6864   if(nbOfCells==0)
6865     return true;
6866   int lastPos=-1;
6867   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6868   for(const int *i=connI;i!=connI+nbOfCells;)
6869     {
6870       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6871       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6872       if(isTypeExists!=orderEnd)
6873         {
6874           int pos=(int)std::distance(orderBg,isTypeExists);
6875           if(pos<=lastPos)
6876             return false;
6877           lastPos=pos;
6878           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6879         }
6880       else
6881         {
6882           if(sg.find(curType)==sg.end())
6883             {
6884               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6885               sg.insert(curType);
6886             }
6887           else
6888             return false;
6889         }
6890     }
6891   return true;
6892 }
6893
6894 /*!
6895  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6896  * that tells for each cell the pos of its type in the array on type given in input parameter. The 2nd output parameter is an array with the same
6897  * number of tuples than input type array and with one component. This 2nd output array gives type by type the number of occurence of type in 'this'.
6898  */
6899 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6900 {
6901   checkConnectivityFullyDefined();
6902   int nbOfCells=getNumberOfCells();
6903   const int *conn=_nodal_connec->getConstPointer();
6904   const int *connI=_nodal_connec_index->getConstPointer();
6905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6907   tmpa->alloc(nbOfCells,1);
6908   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6909   tmpb->fillWithZero();
6910   int *tmp=tmpa->getPointer();
6911   int *tmp2=tmpb->getPointer();
6912   for(const int *i=connI;i!=connI+nbOfCells;i++)
6913     {
6914       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6915       if(where!=orderEnd)
6916         {
6917           int pos=(int)std::distance(orderBg,where);
6918           tmp2[pos]++;
6919           tmp[std::distance(connI,i)]=pos;
6920         }
6921       else
6922         {
6923           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6924           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6925           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6926           throw INTERP_KERNEL::Exception(oss.str().c_str());
6927         }
6928     }
6929   nbPerType=tmpb.retn();
6930   return tmpa.retn();
6931 }
6932
6933 /*!
6934  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6935  *
6936  * \return a new object containing the old to new correspondance.
6937  *
6938  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6939  */
6940 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6941 {
6942   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6943 }
6944
6945 /*!
6946  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [orderBg,orderEnd) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
6947  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6948  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6949  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6950  */
6951 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6952 {
6953   DataArrayInt *nbPerType=0;
6954   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6955   nbPerType->decrRef();
6956   return tmpa->buildPermArrPerLevel();
6957 }
6958
6959 /*!
6960  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6961  * The number of cells remains unchanged after the call of this method.
6962  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6963  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6964  *
6965  * \return the array giving the correspondance old to new.
6966  */
6967 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6968 {
6969   checkFullyDefined();
6970   computeTypes();
6971   const int *conn=_nodal_connec->getConstPointer();
6972   const int *connI=_nodal_connec_index->getConstPointer();
6973   int nbOfCells=getNumberOfCells();
6974   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6975   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6976     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6977       {
6978         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6979         types.push_back(curType);
6980         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6981       }
6982   DataArrayInt *ret=DataArrayInt::New();
6983   ret->alloc(nbOfCells,1);
6984   int *retPtr=ret->getPointer();
6985   std::fill(retPtr,retPtr+nbOfCells,-1);
6986   int newCellId=0;
6987   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6988     {
6989       for(const int *i=connI;i!=connI+nbOfCells;i++)
6990         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6991           retPtr[std::distance(connI,i)]=newCellId++;
6992     }
6993   renumberCells(retPtr,false);
6994   return ret;
6995 }
6996
6997 /*!
6998  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6999  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7000  * This method makes asumption that connectivity is correctly set before calling.
7001  */
7002 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7003 {
7004   checkFullyDefined();
7005   const int *conn=_nodal_connec->getConstPointer();
7006   const int *connI=_nodal_connec_index->getConstPointer();
7007   int nbOfCells=getNumberOfCells();
7008   std::vector<MEDCouplingUMesh *> ret;
7009   for(const int *i=connI;i!=connI+nbOfCells;)
7010     {
7011       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7012       int beginCellId=(int)std::distance(connI,i);
7013       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7014       int endCellId=(int)std::distance(connI,i);
7015       int sz=endCellId-beginCellId;
7016       int *cells=new int[sz];
7017       for(int j=0;j<sz;j++)
7018         cells[j]=beginCellId+j;
7019       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7020       delete [] cells;
7021       ret.push_back(m);
7022     }
7023   return ret;
7024 }
7025
7026 /*!
7027  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7028  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7029  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7030  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7031  * are not used here to avoid the build of big permutation array.
7032  *
7033  * \param [in] ms meshes with same mesh dimension lying on the same coords and sorted by type following de the same geometric type order than
7034  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7035  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7036  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7037  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7038  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7039  * \return A newly allocated unstructured mesh that is the result of the aggregation on same coords of all meshes in \b ms. This returned mesh
7040  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7041  */
7042 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7043                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7044                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7045 {
7046   std::vector<const MEDCouplingUMesh *> ms2;
7047   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7048     if(*it)
7049       {
7050         (*it)->checkConnectivityFullyDefined();
7051         ms2.push_back(*it);
7052       }
7053   if(ms2.empty())
7054     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7055   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7056   int meshDim=ms2[0]->getMeshDimension();
7057   std::vector<const MEDCouplingUMesh *> m1ssm;
7058   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7059   //
7060   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7061   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7062   int fake=0,rk=0;
7063   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7064   ret1->alloc(0,1); ret2->alloc(0,1);
7065   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7066     {
7067       if(meshDim!=(*it)->getMeshDimension())
7068         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7069       if(refCoo!=(*it)->getCoords())
7070         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7071       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7072       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7073       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7074       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7075         {
7076           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7077           m1ssmSingleAuto.push_back(singleCell);
7078           m1ssmSingle.push_back(singleCell);
7079           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7080         }
7081     }
7082   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7083   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7084   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7085   for(std::size_t i=0;i<m1ssm.size();i++)
7086     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7087   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7088   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7089   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7090   return ret0.retn();
7091 }
7092
7093 /*!
7094  * This method returns a newly created DataArrayInt instance.
7095  * This method retrieves cell ids in [begin,end) that have the type 'type'.
7096  */
7097 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
7098 {
7099   checkFullyDefined();
7100   const int *conn=_nodal_connec->getConstPointer();
7101   const int *connIndex=_nodal_connec_index->getConstPointer();
7102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7103   for(const int *w=begin;w!=end;w++)
7104     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7105       ret->pushBackSilent(*w);
7106   return ret.retn();
7107 }
7108
7109 /*!
7110  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7111  * are in [0:getNumberOfCells())
7112  */
7113 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
7114 {
7115   checkFullyDefined();
7116   const int *conn=_nodal_connec->getConstPointer();
7117   const int *connI=_nodal_connec_index->getConstPointer();
7118   int nbOfCells=getNumberOfCells();
7119   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
7120   int *tmp=new int[nbOfCells];
7121   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7122     {
7123       int j=0;
7124       for(const int *i=connI;i!=connI+nbOfCells;i++)
7125         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7126           tmp[std::distance(connI,i)]=j++;
7127     }
7128   DataArrayInt *ret=DataArrayInt::New();
7129   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7130   ret->copyStringInfoFrom(*da);
7131   int *retPtr=ret->getPointer();
7132   const int *daPtr=da->getConstPointer();
7133   int nbOfElems=da->getNbOfElems();
7134   for(int k=0;k<nbOfElems;k++)
7135     retPtr[k]=tmp[daPtr[k]];
7136   delete [] tmp;
7137   return ret;
7138 }
7139
7140 /*!
7141  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7142  * This method \b works \b for mesh sorted by type.
7143  * cells whose ids is in 'idsPerGeoType' array.
7144  * This method conserves coords and name of mesh.
7145  */
7146 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7147 {
7148   std::vector<int> code=getDistributionOfTypes();
7149   std::size_t nOfTypesInThis=code.size()/3;
7150   int sz=0,szOfType=0;
7151   for(std::size_t i=0;i<nOfTypesInThis;i++)
7152     {
7153       if(code[3*i]!=type)
7154         sz+=code[3*i+1];
7155       else
7156         szOfType=code[3*i+1];
7157     }
7158   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7159     if(*work<0 || *work>=szOfType)
7160       {
7161         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7162         oss << ". It should be in [0," << szOfType << ") !";
7163         throw INTERP_KERNEL::Exception(oss.str().c_str());
7164       }
7165   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7166   int *idsPtr=idsTokeep->getPointer();
7167   int offset=0;
7168   for(std::size_t i=0;i<nOfTypesInThis;i++)
7169     {
7170       if(code[3*i]!=type)
7171         for(int j=0;j<code[3*i+1];j++)
7172           *idsPtr++=offset+j;
7173       else
7174         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7175       offset+=code[3*i+1];
7176     }
7177   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7178   ret->copyTinyInfoFrom(this);
7179   return ret.retn();
7180 }
7181
7182 /*!
7183  * This method returns a vector of size 'this->getNumberOfCells()'.
7184  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7185  */
7186 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7187 {
7188   int ncell=getNumberOfCells();
7189   std::vector<bool> ret(ncell);
7190   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7191   const int *c=getNodalConnectivity()->getConstPointer();
7192   for(int i=0;i<ncell;i++)
7193     {
7194       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7195       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7196       ret[i]=cm.isQuadratic();
7197     }
7198   return ret;
7199 }
7200
7201 /*!
7202  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7203  */
7204 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7205 {
7206   if(other->getType()!=UNSTRUCTURED)
7207     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7208   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7209   return MergeUMeshes(this,otherC);
7210 }
7211
7212 /*!
7213  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7214  * computed by averaging coordinates of cell nodes, so this method is not a right
7215  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7216  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7217  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7218  *          components. The caller is to delete this array using decrRef() as it is
7219  *          no more needed.
7220  *  \throw If the coordinates array is not set.
7221  *  \throw If the nodal connectivity of cells is not defined.
7222  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7223  */
7224 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7225 {
7226   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7227   int spaceDim=getSpaceDimension();
7228   int nbOfCells=getNumberOfCells();
7229   ret->alloc(nbOfCells,spaceDim);
7230   ret->copyStringInfoFrom(*getCoords());
7231   double *ptToFill=ret->getPointer();
7232   const int *nodal=_nodal_connec->getConstPointer();
7233   const int *nodalI=_nodal_connec_index->getConstPointer();
7234   const double *coor=_coords->getConstPointer();
7235   for(int i=0;i<nbOfCells;i++)
7236     {
7237       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7238       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7239       ptToFill+=spaceDim;
7240     }
7241   return ret.retn();
7242 }
7243
7244 /*!
7245  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7246  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7247  * 
7248  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7249  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7250  * 
7251  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7252  * \throw If \a this is not fully defined (coordinates and connectivity)
7253  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7254  */
7255 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7256 {
7257   checkFullyDefined();
7258   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7259   int spaceDim=getSpaceDimension();
7260   int nbOfCells=getNumberOfCells();
7261   int nbOfNodes=getNumberOfNodes();
7262   ret->alloc(nbOfCells,spaceDim);
7263   double *ptToFill=ret->getPointer();
7264   const int *nodal=_nodal_connec->getConstPointer();
7265   const int *nodalI=_nodal_connec_index->getConstPointer();
7266   const double *coor=_coords->getConstPointer();
7267   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7268     {
7269       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7270       std::fill(ptToFill,ptToFill+spaceDim,0.);
7271       if(type!=INTERP_KERNEL::NORM_POLYHED)
7272         {
7273           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7274             {
7275               if(*conn>=0 && *conn<nbOfNodes)
7276                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7277               else
7278                 {
7279                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7280                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7281                 }
7282             }
7283           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7284           if(nbOfNodesInCell>0)
7285             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7286           else
7287             {
7288               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7289               throw INTERP_KERNEL::Exception(oss.str().c_str());
7290             }
7291         }
7292       else
7293         {
7294           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7295           s.erase(-1);
7296           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7297             {
7298               if(*it>=0 && *it<nbOfNodes)
7299                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7300               else
7301                 {
7302                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7303                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7304                 }
7305             }
7306           if(!s.empty())
7307             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7308           else
7309             {
7310               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7311               throw INTERP_KERNEL::Exception(oss.str().c_str());
7312             }
7313         }
7314     }
7315   return ret.retn();
7316 }
7317
7318 /*!
7319  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7320  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7321  * are specified via an array of cell ids. 
7322  *  \warning Validity of the specified cell ids is not checked! 
7323  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7324  *  \param [in] begin - an array of cell ids of interest.
7325  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7326  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7327  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7328  *          caller is to delete this array using decrRef() as it is no more needed. 
7329  *  \throw If the coordinates array is not set.
7330  *  \throw If the nodal connectivity of cells is not defined.
7331  *
7332  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7333  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7334  */
7335 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7336 {
7337   DataArrayDouble *ret=DataArrayDouble::New();
7338   int spaceDim=getSpaceDimension();
7339   int nbOfTuple=(int)std::distance(begin,end);
7340   ret->alloc(nbOfTuple,spaceDim);
7341   double *ptToFill=ret->getPointer();
7342   double *tmp=new double[spaceDim];
7343   const int *nodal=_nodal_connec->getConstPointer();
7344   const int *nodalI=_nodal_connec_index->getConstPointer();
7345   const double *coor=_coords->getConstPointer();
7346   for(const int *w=begin;w!=end;w++)
7347     {
7348       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7349       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7350       ptToFill+=spaceDim;
7351     }
7352   delete [] tmp;
7353   return ret;
7354 }
7355
7356 /*!
7357  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7358  * 
7359  */
7360 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7361 {
7362   if(!da)
7363     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7364   da->checkAllocated();
7365   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7366   ret->setCoords(da);
7367   int nbOfTuples=da->getNumberOfTuples();
7368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7370   c->alloc(2*nbOfTuples,1);
7371   cI->alloc(nbOfTuples+1,1);
7372   int *cp=c->getPointer();
7373   int *cip=cI->getPointer();
7374   *cip++=0;
7375   for(int i=0;i<nbOfTuples;i++)
7376     {
7377       *cp++=INTERP_KERNEL::NORM_POINT1;
7378       *cp++=i;
7379       *cip++=2*(i+1);
7380     }
7381   ret->setConnectivity(c,cI,true);
7382   return ret.retn();
7383 }
7384 /*!
7385  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7386  * Cells and nodes of
7387  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7388  *  \param [in] mesh1 - the first mesh.
7389  *  \param [in] mesh2 - the second mesh.
7390  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7391  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7392  *          is no more needed.
7393  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7394  *  \throw If the coordinates array is not set in none of the meshes.
7395  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7396  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7397  */
7398 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7399 {
7400   std::vector<const MEDCouplingUMesh *> tmp(2);
7401   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7402   return MergeUMeshes(tmp);
7403 }
7404
7405 /*!
7406  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7407  * Cells and nodes of
7408  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7409  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7410  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7411  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7412  *          is no more needed.
7413  *  \throw If \a a.size() == 0.
7414  *  \throw If \a a[ *i* ] == NULL.
7415  *  \throw If the coordinates array is not set in none of the meshes.
7416  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7417  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7418 */
7419 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7420 {
7421   std::size_t sz=a.size();
7422   if(sz==0)
7423     return MergeUMeshesLL(a);
7424   for(std::size_t ii=0;ii<sz;ii++)
7425     if(!a[ii])
7426       {
7427         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7428         throw INTERP_KERNEL::Exception(oss.str().c_str());
7429       }
7430   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7431   std::vector< const MEDCouplingUMesh * > aa(sz);
7432   int spaceDim=-3;
7433   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7434     {
7435       const MEDCouplingUMesh *cur=a[i];
7436       const DataArrayDouble *coo=cur->getCoords();
7437       if(coo)
7438         spaceDim=coo->getNumberOfComponents();
7439     }
7440   if(spaceDim==-3)
7441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7442   for(std::size_t i=0;i<sz;i++)
7443     {
7444       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7445       aa[i]=bb[i];
7446     }
7447   return MergeUMeshesLL(aa);
7448 }
7449
7450 /// @cond INTERNAL
7451
7452 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7453 {
7454   if(a.empty())
7455     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7456   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7457   int meshDim=(*it)->getMeshDimension();
7458   int nbOfCells=(*it)->getNumberOfCells();
7459   int meshLgth=(*it++)->getMeshLength();
7460   for(;it!=a.end();it++)
7461     {
7462       if(meshDim!=(*it)->getMeshDimension())
7463         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7464       nbOfCells+=(*it)->getNumberOfCells();
7465       meshLgth+=(*it)->getMeshLength();
7466     }
7467   std::vector<const MEDCouplingPointSet *> aps(a.size());
7468   std::copy(a.begin(),a.end(),aps.begin());
7469   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7470   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7471   ret->setCoords(pts);
7472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7473   c->alloc(meshLgth,1);
7474   int *cPtr=c->getPointer();
7475   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7476   cI->alloc(nbOfCells+1,1);
7477   int *cIPtr=cI->getPointer();
7478   *cIPtr++=0;
7479   int offset=0;
7480   int offset2=0;
7481   for(it=a.begin();it!=a.end();it++)
7482     {
7483       int curNbOfCell=(*it)->getNumberOfCells();
7484       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7485       const int *curC=(*it)->_nodal_connec->getConstPointer();
7486       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7487       for(int j=0;j<curNbOfCell;j++)
7488         {
7489           const int *src=curC+curCI[j];
7490           *cPtr++=*src++;
7491           for(;src!=curC+curCI[j+1];src++,cPtr++)
7492             {
7493               if(*src!=-1)
7494                 *cPtr=*src+offset2;
7495               else
7496                 *cPtr=-1;
7497             }
7498         }
7499       offset+=curCI[curNbOfCell];
7500       offset2+=(*it)->getNumberOfNodes();
7501     }
7502   //
7503   ret->setConnectivity(c,cI,true);
7504   return ret.retn();
7505 }
7506
7507 /// @endcond
7508
7509 /*!
7510  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7511  * dimension and sharing the node coordinates array.
7512  * All cells of the first mesh precede all cells of the second mesh
7513  * within the result mesh. 
7514  *  \param [in] mesh1 - the first mesh.
7515  *  \param [in] mesh2 - the second mesh.
7516  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7517  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7518  *          is no more needed.
7519  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7520  *  \throw If the meshes do not share the node coordinates array.
7521  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7522  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7523  */
7524 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7525 {
7526   std::vector<const MEDCouplingUMesh *> tmp(2);
7527   tmp[0]=mesh1; tmp[1]=mesh2;
7528   return MergeUMeshesOnSameCoords(tmp);
7529 }
7530
7531 /*!
7532  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7533  * dimension and sharing the node coordinates array.
7534  * All cells of the *i*-th mesh precede all cells of the
7535  * (*i*+1)-th mesh within the result mesh.
7536  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7537  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7538  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7539  *          is no more needed.
7540  *  \throw If \a a.size() == 0.
7541  *  \throw If \a a[ *i* ] == NULL.
7542  *  \throw If the meshes do not share the node coordinates array.
7543  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7544  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7545  */
7546 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7547 {
7548   if(meshes.empty())
7549     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7550   for(std::size_t ii=0;ii<meshes.size();ii++)
7551     if(!meshes[ii])
7552       {
7553         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7554         throw INTERP_KERNEL::Exception(oss.str().c_str());
7555       }
7556   const DataArrayDouble *coords=meshes.front()->getCoords();
7557   int meshDim=meshes.front()->getMeshDimension();
7558   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7559   int meshLgth=0;
7560   int meshIndexLgth=0;
7561   for(;iter!=meshes.end();iter++)
7562     {
7563       if(coords!=(*iter)->getCoords())
7564         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7565       if(meshDim!=(*iter)->getMeshDimension())
7566         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7567       meshLgth+=(*iter)->getMeshLength();
7568       meshIndexLgth+=(*iter)->getNumberOfCells();
7569     }
7570   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7571   nodal->alloc(meshLgth,1);
7572   int *nodalPtr=nodal->getPointer();
7573   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7574   nodalIndex->alloc(meshIndexLgth+1,1);
7575   int *nodalIndexPtr=nodalIndex->getPointer();
7576   int offset=0;
7577   for(iter=meshes.begin();iter!=meshes.end();iter++)
7578     {
7579       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7580       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7581       int nbOfCells=(*iter)->getNumberOfCells();
7582       int meshLgth2=(*iter)->getMeshLength();
7583       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7584       if(iter!=meshes.begin())
7585         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7586       else
7587         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7588       offset+=meshLgth2;
7589     }
7590   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7591   ret->setName("merge");
7592   ret->setMeshDimension(meshDim);
7593   ret->setConnectivity(nodal,nodalIndex,true);
7594   ret->setCoords(coords);
7595   return ret;
7596 }
7597
7598 /*!
7599  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7600  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7601  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7602  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7603  * New" mode are returned for each input mesh.
7604  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7605  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7606  *          valid values [0,1,2], see zipConnectivityTraducer().
7607  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7608  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7609  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7610  *          no more needed.
7611  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7612  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7613  *          is no more needed.
7614  *  \throw If \a meshes.size() == 0.
7615  *  \throw If \a meshes[ *i* ] == NULL.
7616  *  \throw If the meshes do not share the node coordinates array.
7617  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7618  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7619  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7620  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7621  */
7622 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7623 {
7624   //All checks are delegated to MergeUMeshesOnSameCoords
7625   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7626   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7627   corr.resize(meshes.size());
7628   std::size_t nbOfMeshes=meshes.size();
7629   int offset=0;
7630   const int *o2nPtr=o2n->getConstPointer();
7631   for(std::size_t i=0;i<nbOfMeshes;i++)
7632     {
7633       DataArrayInt *tmp=DataArrayInt::New();
7634       int curNbOfCells=meshes[i]->getNumberOfCells();
7635       tmp->alloc(curNbOfCells,1);
7636       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7637       offset+=curNbOfCells;
7638       tmp->setName(meshes[i]->getName());
7639       corr[i]=tmp;
7640     }
7641   return ret.retn();
7642 }
7643
7644 /*!
7645  * Makes all given meshes share the nodal connectivity array. The common connectivity
7646  * array is created by concatenating the connectivity arrays of all given meshes. All
7647  * the given meshes must be of the same space dimension but dimension of cells **can
7648  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7649  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7650  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7651  *  \param [in,out] meshes - a vector of meshes to update.
7652  *  \throw If any of \a meshes is NULL.
7653  *  \throw If the coordinates array is not set in any of \a meshes.
7654  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7655  *  \throw If \a meshes are of different space dimension.
7656  */
7657 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7658 {
7659   std::size_t sz=meshes.size();
7660   if(sz==0 || sz==1)
7661     return;
7662   std::vector< const DataArrayDouble * > coords(meshes.size());
7663   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7664   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7665     {
7666       if((*it))
7667         {
7668           (*it)->checkConnectivityFullyDefined();
7669           const DataArrayDouble *coo=(*it)->getCoords();
7670           if(coo)
7671             *it2=coo;
7672           else
7673             {
7674               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7675               oss << " has no coordinate array defined !";
7676               throw INTERP_KERNEL::Exception(oss.str().c_str());
7677             }
7678         }
7679       else
7680         {
7681           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7682           oss << " is null !";
7683           throw INTERP_KERNEL::Exception(oss.str().c_str());
7684         }
7685     }
7686   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7687   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7688   int offset=(*it)->getNumberOfNodes();
7689   (*it++)->setCoords(res);
7690   for(;it!=meshes.end();it++)
7691     {
7692       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7693       (*it)->setCoords(res);
7694       (*it)->shiftNodeNumbersInConn(offset);
7695       offset+=oldNumberOfNodes;
7696     }
7697 }
7698
7699 /*!
7700  * Merges nodes coincident with a given precision within all given meshes that share
7701  * the nodal connectivity array. The given meshes **can be of different** mesh
7702  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7703  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7704  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7705  *  \param [in,out] meshes - a vector of meshes to update.
7706  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7707  *  \throw If any of \a meshes is NULL.
7708  *  \throw If the \a meshes do not share the same node coordinates array.
7709  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7710  */
7711 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7712 {
7713   if(meshes.empty())
7714     return ;
7715   std::set<const DataArrayDouble *> s;
7716   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7717     {
7718       if(*it)
7719         s.insert((*it)->getCoords());
7720       else
7721         {
7722           std::ostringstream oss; oss << "MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords : In input vector of unstructured meshes of size " << meshes.size() << " the element #" << std::distance(meshes.begin(),it) << " is null !";
7723           throw INTERP_KERNEL::Exception(oss.str().c_str());
7724         }
7725     }
7726   if(s.size()!=1)
7727     {
7728       std::ostringstream oss; oss << "MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords : In input vector of unstructured meshes of size " << meshes.size() << ", it appears that they do not share the same instance of DataArrayDouble for coordiantes ! tryToShareSameCoordsPermute method can help to reach that !";
7729       throw INTERP_KERNEL::Exception(oss.str().c_str());
7730     }
7731   const DataArrayDouble *coo=*(s.begin());
7732   if(!coo)
7733     return;
7734   //
7735   DataArrayInt *comm,*commI;
7736   coo->findCommonTuples(eps,-1,comm,commI);
7737   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7738   int oldNbOfNodes=coo->getNumberOfTuples();
7739   int newNbOfNodes;
7740   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7741   if(oldNbOfNodes==newNbOfNodes)
7742     return ;
7743   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7744   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7745     {
7746       (*it)->renumberNodesInConn(o2n->getConstPointer());
7747       (*it)->setCoords(newCoords);
7748     } 
7749 }
7750
7751 /*!
7752  * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [connBg,connEnd) and returns its extruded cell by inserting the result at the end of ret.
7753  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7754  * \param isQuad specifies the policy of connectivity.
7755  * @ret in/out parameter in which the result will be append
7756  */
7757 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7758 {
7759   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7760   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7761   ret.push_back(cm.getExtrudedType());
7762   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7763   switch(flatType)
7764     {
7765     case INTERP_KERNEL::NORM_POINT1:
7766       {
7767         ret.push_back(connBg[1]);
7768         ret.push_back(connBg[1]+nbOfNodesPerLev);
7769         break;
7770       }
7771     case INTERP_KERNEL::NORM_SEG2:
7772       {
7773         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7774         ret.insert(ret.end(),conn,conn+4);
7775         break;
7776       }
7777     case INTERP_KERNEL::NORM_SEG3:
7778       {
7779         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7780         ret.insert(ret.end(),conn,conn+8);
7781         break;
7782       }
7783     case INTERP_KERNEL::NORM_QUAD4:
7784       {
7785         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7786         ret.insert(ret.end(),conn,conn+8);
7787         break;
7788       }
7789     case INTERP_KERNEL::NORM_TRI3:
7790       {
7791         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7792         ret.insert(ret.end(),conn,conn+6);
7793         break;
7794       }
7795     case INTERP_KERNEL::NORM_TRI6:
7796       {
7797         int conn[15]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4],connBg[5],connBg[6],connBg[4]+deltaz,connBg[5]+deltaz,connBg[6]+deltaz,
7798                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7799         ret.insert(ret.end(),conn,conn+15);
7800         break;
7801       }
7802     case INTERP_KERNEL::NORM_QUAD8:
7803       {
7804         int conn[20]={
7805           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7806           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7807           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7808         };
7809         ret.insert(ret.end(),conn,conn+20);
7810         break;
7811       }
7812     case INTERP_KERNEL::NORM_POLYGON:
7813       {
7814         std::back_insert_iterator< std::vector<int> > ii(ret);
7815         std::copy(connBg+1,connEnd,ii);
7816         *ii++=-1;
7817         std::reverse_iterator<const int *> rConnBg(connEnd);
7818         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7819         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7820         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7821         for(std::size_t i=0;i<nbOfRadFaces;i++)
7822           {
7823             *ii++=-1;
7824             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7825             std::copy(conn,conn+4,ii);
7826           }
7827         break;
7828       }
7829     default:
7830       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7831     }
7832 }
7833
7834 /*!
7835  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
7836  */
7837 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7838 {
7839   double v[3]={0.,0.,0.};
7840   std::size_t sz=std::distance(begin,end);
7841   if(isQuadratic)
7842     sz/=2;
7843   for(std::size_t i=0;i<sz;i++)
7844     {
7845       v[0]+=coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]+2]-coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]+1];
7846       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7847       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7848     }
7849   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7850 }
7851
7852 /*!
7853  * The polyhedron is specfied by its connectivity nodes in [begin,end).
7854  */
7855 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7856 {
7857   std::vector<std::pair<int,int> > edges;
7858   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7859   const int *bgFace=begin;
7860   for(std::size_t i=0;i<nbOfFaces;i++)
7861     {
7862       const int *endFace=std::find(bgFace+1,end,-1);
7863       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7864       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7865         {
7866           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7867           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7868             return false;
7869           edges.push_back(p1);
7870         }
7871       bgFace=endFace+1;
7872     }
7873   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7874 }
7875
7876 /*!
7877  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
7878  */
7879 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7880 {
7881   double vec0[3],vec1[3];
7882   std::size_t sz=std::distance(begin,end);
7883   if(sz%2!=0)
7884     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7885   int nbOfNodes=(int)sz/2;
7886   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7887   const double *pt0=coords+3*begin[0];
7888   const double *pt1=coords+3*begin[nbOfNodes];
7889   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7890   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7891 }
7892
7893 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7894 {
7895   std::size_t sz=std::distance(begin,end);
7896   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7897   std::size_t nbOfNodes(sz/2);
7898   std::copy(begin,end,(int *)tmp);
7899   for(std::size_t j=1;j<nbOfNodes;j++)
7900     {
7901       begin[j]=tmp[nbOfNodes-j];
7902       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7903     }
7904 }
7905
7906 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7907 {
7908   std::size_t sz=std::distance(begin,end);
7909   if(sz!=4)
7910     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7911   double vec0[3],vec1[3];
7912   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7913   vec0[0]=pt1[0]-pt0[0]; vec0[1]=pt1[1]-pt0[1]; vec0[2]=pt1[2]-pt0[2]; vec1[0]=pt2[0]-pt0[0]; vec1[1]=pt2[1]-pt0[1]; vec1[2]=pt2[2]-pt0[2]; 
7914   return ((vec0[1]*vec1[2]-vec0[2]*vec1[1])*(pt3[0]-pt0[0])+(vec0[2]*vec1[0]-vec0[0]*vec1[2])*(pt3[1]-pt0[1])+(vec0[0]*vec1[1]-vec0[1]*vec1[0])*(pt3[2]-pt0[2]))<0;
7915 }
7916
7917 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7918 {
7919   std::size_t sz=std::distance(begin,end);
7920   if(sz!=5)
7921     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7922   double vec0[3];
7923   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7924   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7925   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7926 }
7927
7928 /*!
7929  * This method performs a simplyfication of a single polyedron cell. To do that each face of cell whose connectivity is defined by [\b begin, \b end) 
7930  * is compared with the others in order to find faces in the same plane (with approx of eps). If any, the cells are grouped together and projected to
7931  * a 2D space.
7932  *
7933  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7934  * \param [in] coords the coordinates with nb of components exactly equal to 3
7935  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7936  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7937  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7938  */
7939 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7940 {
7941   int nbFaces=std::count(begin+1,end,-1)+1;
7942   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7943   double *vPtr=v->getPointer();
7944   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7945   double *pPtr=p->getPointer();
7946   const int *stFaceConn=begin+1;
7947   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7948     {
7949       const int *endFaceConn=std::find(stFaceConn,end,-1);
7950       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7951       stFaceConn=endFaceConn+1;
7952     }
7953   pPtr=p->getPointer(); vPtr=v->getPointer();
7954   DataArrayInt *comm1=0,*commI1=0;
7955   v->findCommonTuples(eps,-1,comm1,commI1);
7956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7957   const int *comm1Ptr=comm1->getConstPointer();
7958   const int *commI1Ptr=commI1->getConstPointer();
7959   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7960   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7961   //
7962   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7963   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7964   mm->finishInsertingCells();
7965   //
7966   for(int i=0;i<nbOfGrps1;i++)
7967     {
7968       int vecId=comm1Ptr[commI1Ptr[i]];
7969       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7970       DataArrayInt *comm2=0,*commI2=0;
7971       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7972       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7973       const int *comm2Ptr=comm2->getConstPointer();
7974       const int *commI2Ptr=commI2->getConstPointer();
7975       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7976       for(int j=0;j<nbOfGrps2;j++)
7977         {
7978           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7979             {
7980               res->insertAtTheEnd(begin,end);
7981               res->pushBackSilent(-1);
7982             }
7983           else
7984             {
7985               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7986               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7987               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7988               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7989               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7990               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7991               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7992               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7993               const int *idsNodePtr=idsNode->getConstPointer();
7994               double center[3]; center[0]=pPtr[pointId]*vPtr[3*vecId]; center[1]=pPtr[pointId]*vPtr[3*vecId+1]; center[2]=pPtr[pointId]*vPtr[3*vecId+2];
7995               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7996               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7997               if(std::abs(norm)>eps)
7998                 {
7999                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8000                   mm3->rotate(center,vec,angle);
8001                 }
8002               mm3->changeSpaceDimension(2);
8003               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8004               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8005               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8006               int nbOfCells=mm4->getNumberOfCells();
8007               for(int k=0;k<nbOfCells;k++)
8008                 {
8009                   int l=0;
8010                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8011                     res->pushBackSilent(idsNodePtr[*work]);
8012                   res->pushBackSilent(-1);
8013                 }
8014             }
8015         }
8016     }
8017   res->popBackSilent();
8018 }
8019
8020 /*!
8021  * This method computes the normalized vector of the plane and the pos of the point belonging to the plane and the line defined by the vector going
8022  * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
8023  * 
8024  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8025  * \param [in] coords coordinates expected to have 3 components.
8026  * \param [in] begin start of the nodal connectivity of the face.
8027  * \param [in] end end of the nodal connectivity (excluded) of the face.
8028  * \param [out] v the normalized vector of size 3
8029  * \param [out] p the pos of plane
8030  */
8031 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
8032 {
8033   std::size_t nbPoints=std::distance(begin,end);
8034   if(nbPoints<3)
8035     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8036   double vec[3]={0.,0.,0.};
8037   std::size_t j=0;
8038   bool refFound=false;
8039   for(;j<nbPoints-1 && !refFound;j++)
8040     {
8041       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8042       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8043       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8044       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8045       if(norm>eps)
8046         {
8047           refFound=true;
8048           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8049         }
8050     }
8051   for(std::size_t i=j;i<nbPoints-1;i++)
8052     {
8053       double curVec[3];
8054       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8055       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8056       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8057       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8058       if(norm<eps)
8059         continue;
8060       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8061       v[0]=vec[1]*curVec[2]-vec[2]*curVec[1]; v[1]=vec[2]*curVec[0]-vec[0]*curVec[2]; v[2]=vec[0]*curVec[1]-vec[1]*curVec[0];
8062       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8063       if(norm>eps)
8064         {
8065           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8066           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8067           return ;
8068         }
8069     }
8070   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8071 }
8072
8073 /*!
8074  * This method tries to obtain a well oriented polyhedron.
8075  * If the algorithm fails, an exception will be thrown.
8076  */
8077 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
8078 {
8079   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8080   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8081   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8082   isPerm[0]=true;
8083   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8084   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8085   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8086   //
8087   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8088     {
8089       bgFace=begin;
8090       std::size_t smthChanged=0;
8091       for(std::size_t i=0;i<nbOfFaces;i++)
8092         {
8093           endFace=std::find(bgFace+1,end,-1);
8094           nbOfEdgesInFace=std::distance(bgFace,endFace);
8095           if(!isPerm[i])
8096             {
8097               bool b;
8098               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8099                 {
8100                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8101                   std::pair<int,int> p2(p1.second,p1.first);
8102                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8103                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8104                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8105                 }
8106               if(isPerm[i])
8107                 { 
8108                   if(!b)
8109                     std::reverse(bgFace+1,endFace);
8110                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8111                     {
8112                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8113                       std::pair<int,int> p2(p1.second,p1.first);
8114                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8115                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8116                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8117                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8118                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8119                       if(it!=edgesOK.end())
8120                         {
8121                           edgesOK.erase(it);
8122                           edgesFinished.push_back(p1);
8123                         }
8124                       else
8125                         edgesOK.push_back(p1);
8126                     }
8127                 }
8128             }
8129           bgFace=endFace+1;
8130         }
8131       if(smthChanged==0)
8132         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8133     }
8134   if(!edgesOK.empty())
8135     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8136   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8137     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8138       bgFace=begin;
8139       for(std::size_t i=0;i<nbOfFaces;i++)
8140         {
8141           endFace=std::find(bgFace+1,end,-1);
8142           std::reverse(bgFace+1,endFace);
8143           bgFace=endFace+1;
8144         }
8145     }
8146 }
8147
8148 /*!
8149  * This method makes the assumption spacedimension == meshdimension == 2.
8150  * This method works only for linear cells.
8151  * 
8152  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8153  */
8154 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
8155 {
8156   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8157     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8158   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8159   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8160   int nbOfNodesExpected=m->getNumberOfNodes();
8161   if(m->getNumberOfCells()!=nbOfNodesExpected)
8162     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8163   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8164   const int *n2oPtr=n2o->getConstPointer();
8165   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8166   m->getReverseNodalConnectivity(revNodal,revNodalI);
8167   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8168   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8169   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8170   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8171   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
8172   if(nbOfNodesExpected<1)
8173     return ret.retn();
8174   int prevCell=0;
8175   int prevNode=nodalPtr[nodalIPtr[0]+1];
8176   *work++=n2oPtr[prevNode];
8177   for(int i=1;i<nbOfNodesExpected;i++)
8178     {
8179       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8180         {
8181           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8182           conn.erase(prevNode);
8183           if(conn.size()==1)
8184             {
8185               int curNode=*(conn.begin());
8186               *work++=n2oPtr[curNode];
8187               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8188               shar.erase(prevCell);
8189               if(shar.size()==1)
8190                 {
8191                   prevCell=*(shar.begin());
8192                   prevNode=curNode;
8193                 }
8194               else
8195                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8196             }
8197           else
8198             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8199         }
8200       else
8201         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8202     }
8203   return ret.retn();
8204 }
8205
8206 /*!
8207  * This method makes the assumption spacedimension == meshdimension == 3.
8208  * This method works only for linear cells.
8209  * 
8210  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8211  */
8212 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8213 {
8214   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8215     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8216   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8217   const int *conn=m->getNodalConnectivity()->getConstPointer();
8218   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8219   int nbOfCells=m->getNumberOfCells();
8220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8221   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8222   if(nbOfCells<1)
8223     return ret.retn();
8224   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8225   for(int i=1;i<nbOfCells;i++)
8226     {
8227       *work++=-1;
8228       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8229     }
8230   return ret.retn();
8231 }
8232
8233 /*!
8234  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8235  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8236  */
8237 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8238 {
8239   double *w=zipFrmt;
8240   if(spaceDim==3)
8241     for(int i=0;i<nbOfNodesInCell;i++)
8242       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8243   else if(spaceDim==2)
8244     {
8245       for(int i=0;i<nbOfNodesInCell;i++)
8246         {
8247           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8248           *w++=0.;
8249         }
8250     }
8251   else
8252     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8253 }
8254
8255 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8256 {
8257   int nbOfCells=getNumberOfCells();
8258   if(nbOfCells<=0)
8259     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8260   static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,-1,4};
8261   ofs << "  <" << getVTKDataSetType() << ">\n";
8262   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8263   ofs << "      <PointData>\n" << pointData << std::endl;
8264   ofs << "      </PointData>\n";
8265   ofs << "      <CellData>\n" << cellData << std::endl;
8266   ofs << "      </CellData>\n";
8267   ofs << "      <Points>\n";
8268   if(getSpaceDimension()==3)
8269     _coords->writeVTK(ofs,8,"Points");
8270   else
8271     {
8272       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8273       coo->writeVTK(ofs,8,"Points");
8274     }
8275   ofs << "      </Points>\n";
8276   ofs << "      <Cells>\n";
8277   const int *cPtr=_nodal_connec->getConstPointer();
8278   const int *cIPtr=_nodal_connec_index->getConstPointer();
8279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8283   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8284   int szFaceOffsets=0,szConn=0;
8285   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8286     {
8287       *w2=cPtr[cIPtr[i]];
8288       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8289         {
8290           *w1=-1;
8291           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8292           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8293         }
8294       else
8295         {
8296           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8297           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8298           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8299           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8300           w4=std::copy(c.begin(),c.end(),w4);
8301         }
8302     }
8303   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8304   types->writeVTK(ofs,8,"UInt8","types");
8305   offsets->writeVTK(ofs,8,"Int32","offsets");
8306   if(szFaceOffsets!=0)
8307     {//presence of Polyhedra
8308       connectivity->reAlloc(szConn);
8309       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8310       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8311       w1=faces->getPointer();
8312       for(int i=0;i<nbOfCells;i++)
8313         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8314           {
8315             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8316             *w1++=nbFaces;
8317             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8318             for(int j=0;j<nbFaces;j++)
8319               {
8320                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8321                 *w1++=(int)std::distance(w6,w5);
8322                 w1=std::copy(w6,w5,w1);
8323                 w6=w5+1;
8324               }
8325           }
8326       faces->writeVTK(ofs,8,"Int32","faces");
8327     }
8328   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8329   ofs << "      </Cells>\n";
8330   ofs << "    </Piece>\n";
8331   ofs << "  </" << getVTKDataSetType() << ">\n";
8332 }
8333
8334 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8335 {
8336   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8337   if(_mesh_dim==-2)
8338     { stream << " Not set !"; return ; }
8339   stream << " Mesh dimension : " << _mesh_dim << ".";
8340   if(_mesh_dim==-1)
8341     return ;
8342   if(!_coords)
8343     { stream << " No coordinates set !"; return ; }
8344   if(!_coords->isAllocated())
8345     { stream << " Coordinates set but not allocated !"; return ; }
8346   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8347   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8348   if(!_nodal_connec_index)
8349     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8350   if(!_nodal_connec_index->isAllocated())
8351     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8352   int lgth=_nodal_connec_index->getNumberOfTuples();
8353   int cpt=_nodal_connec_index->getNumberOfComponents();
8354   if(cpt!=1 || lgth<1)
8355     return ;
8356   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8357 }
8358
8359 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8360 {
8361   return std::string("UnstructuredGrid");
8362 }
8363
8364 /*!
8365  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8366  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8367  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8368  * meshes.
8369  *  \param [in] m1 - the first input mesh which is a partitioned object.
8370  *  \param [in] m2 - the second input mesh which is a partition tool.
8371  *  \param [in] eps - precision used to detect coincident mesh entities.
8372  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8373  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8374  *         this array using decrRef() as it is no more needed.
8375  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8376  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8377  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8378  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8379  *         it is no more needed.  
8380  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8381  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8382  *         is no more needed.  
8383  *  \throw If the coordinates array is not set in any of the meshes.
8384  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8385  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8386  */
8387 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8388 {
8389   m1->checkFullyDefined();
8390   m2->checkFullyDefined();
8391   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8393   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8394   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8395   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8396   std::vector<double> addCoo,addCoordsQuadratic;
8397   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8398   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8399   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8400                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8401   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8403   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8404   std::vector< std::vector<int> > intersectEdge2;
8405   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8406   subDiv2.clear(); dd5=0; dd6=0;
8407   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8408   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8409   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8410                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8411   //
8412   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8413   addCooDa->alloc((int)(addCoo.size())/2,2);
8414   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8415   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8416   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8417   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8418   std::vector<const DataArrayDouble *> coordss(4);
8419   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8420   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8421   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8422   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8423   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8424   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8425   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8426   ret->setConnectivity(conn,connI,true);
8427   ret->setCoords(coo);
8428   cellNb1=c1.retn(); cellNb2=c2.retn();
8429   return ret.retn();
8430 }
8431
8432 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8433                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8434                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8435                                                          const std::vector<double>& addCoords,
8436                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8437 {
8438   static const int SPACEDIM=2;
8439   std::vector<double> bbox1,bbox2;
8440   const double *coo1=m1->getCoords()->getConstPointer();
8441   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8442   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8443   int offset1=m1->getNumberOfNodes();
8444   const double *coo2=m2->getCoords()->getConstPointer();
8445   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8446   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8447   int offset2=offset1+m2->getNumberOfNodes();
8448   int offset3=offset2+((int)addCoords.size())/2;
8449   m1->getBoundingBoxForBBTree(bbox1);
8450   m2->getBoundingBoxForBBTree(bbox2);
8451   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8452   int ncell1=m1->getNumberOfCells();
8453   crI.push_back(0);
8454   for(int i=0;i<ncell1;i++)
8455     {
8456       std::vector<int> candidates2;
8457       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8458       std::map<INTERP_KERNEL::Node *,int> mapp;
8459       std::map<int,INTERP_KERNEL::Node *> mappRev;
8460       INTERP_KERNEL::QuadraticPolygon pol1;
8461       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8462       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8463       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8464       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8465                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8466       //
8467       std::set<INTERP_KERNEL::Edge *> edges1;// store all edges of pol1 that are NOT consumed by intersect cells. If any after iteration over candidates2 -> a part of pol1 should appear in result
8468       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8469       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8470       for(it1.first();!it1.finished();it1.next())
8471         edges1.insert(it1.current()->getPtr());
8472       //
8473       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8474       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8475       int ii=0;
8476       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8477         {
8478           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8479           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8480           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8481           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8482                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8483         }
8484       ii=0;
8485       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8486         {
8487           pol1.initLocationsWithOther(pol2s[ii]);
8488           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8489           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8490           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8491         }
8492       if(!edges1.empty())
8493         {
8494           try
8495             {
8496               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8497             }
8498           catch(INTERP_KERNEL::Exception& e)
8499             {
8500               std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what();
8501               throw INTERP_KERNEL::Exception(oss.str().c_str());
8502             }
8503         }
8504       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8505         (*it).second->decrRef();
8506     }
8507 }
8508
8509 /*!
8510  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8511  * 
8512  */
8513 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8514                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8515                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8516                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8517                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8518 {
8519   static const int SPACEDIM=2;
8520   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8521   desc2=DataArrayInt::New();
8522   descIndx2=DataArrayInt::New();
8523   revDesc2=DataArrayInt::New();
8524   revDescIndx2=DataArrayInt::New();
8525   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8526   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8527   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8528   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8529   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8530   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8531   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8532   std::vector<double> bbox1,bbox2;
8533   m1Desc->getBoundingBoxForBBTree(bbox1);
8534   m2Desc->getBoundingBoxForBBTree(bbox2);
8535   int ncell1=m1Desc->getNumberOfCells();
8536   int ncell2=m2Desc->getNumberOfCells();
8537   intersectEdge1.resize(ncell1);
8538   colinear2.resize(ncell2);
8539   subDiv2.resize(ncell2);
8540   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8541   std::vector<int> candidates1(1);
8542   int offset1=m1->getNumberOfNodes();
8543   int offset2=offset1+m2->getNumberOfNodes();
8544   for(int i=0;i<ncell1;i++)
8545     {
8546       std::vector<int> candidates2;
8547       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8548       if(!candidates2.empty())
8549         {
8550           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8551           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8552           candidates1[0]=i;
8553           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8554           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8555           delete pol2;
8556           delete pol1;
8557         }
8558       else
8559         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8560     }
8561   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8562   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8563 }
8564
8565 /*!
8566  * This method performs the 2nd step of Partition of 2D mesh.
8567  * This method has 4 inputs :
8568  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8569  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8570  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8571  * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8572  * \param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8573  * \param m2 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method.
8574  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8575  */
8576 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
8577 {
8578   int offset1=m1->getNumberOfNodes();
8579   int ncell=m2->getNumberOfCells();
8580   const int *c=m2->getNodalConnectivity()->getConstPointer();
8581   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8582   const double *coo=m2->getCoords()->getConstPointer();
8583   const double *cooBis=m1->getCoords()->getConstPointer();
8584   int offset2=offset1+m2->getNumberOfNodes();
8585   intersectEdge.resize(ncell);
8586   for(int i=0;i<ncell;i++,cI++)
8587     {
8588       const std::vector<int>& divs=subDiv[i];
8589       int nnode=cI[1]-cI[0]-1;
8590       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8591       std::map<INTERP_KERNEL::Node *, int> mapp22;
8592       for(int j=0;j<nnode;j++)
8593         {
8594           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8595           int nnid=c[(*cI)+j+1];
8596           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8597           mapp22[nn]=nnid+offset1;
8598         }
8599       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8600       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8601         ((*it).second.first)->decrRef();
8602       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8603       std::map<INTERP_KERNEL::Node *,int> mapp3;
8604       for(std::size_t j=0;j<divs.size();j++)
8605         {
8606           int id=divs[j];
8607           INTERP_KERNEL::Node *tmp=0;
8608           if(id<offset1)
8609             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8610           else if(id<offset2)
8611             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8612           else
8613             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8614           addNodes[j]=tmp;
8615           mapp3[tmp]=id;
8616         }
8617       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8618       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8619         (*it)->decrRef();
8620       e->decrRef();
8621     }
8622 }
8623
8624 /*!
8625  * This method is part of the Slice3D algorithm. It is the first step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
8626  * This method allows to compute given the status of 3D curve cells and the descending connectivity 3DSurf->3DCurve to deduce the intersection of each 3D surf cells
8627  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8628  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8629  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8630  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8631  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8632  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8633  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8634  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8635  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8636  * \param [out] cut3DSuf input/output param.
8637  */
8638 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8639                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8640                                                    const int *desc, const int *descIndx, 
8641                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8642 {
8643   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8644   int nbOf3DSurfCell=(int)cut3DSurf.size();
8645   for(int i=0;i<nbOf3DSurfCell;i++)
8646     {
8647       std::vector<int> res;
8648       int offset=descIndx[i];
8649       int nbOfSeg=descIndx[i+1]-offset;
8650       for(int j=0;j<nbOfSeg;j++)
8651         {
8652           int edgeId=desc[offset+j];
8653           int status=cut3DCurve[edgeId];
8654           if(status!=-2)
8655             {
8656               if(status>-1)
8657                 res.push_back(status);
8658               else
8659                 {
8660                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8661                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8662                 }
8663             }
8664         }
8665       switch(res.size())
8666         {
8667         case 2:
8668           {
8669             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8670             break;
8671           }
8672         case 1:
8673         case 0:
8674           {
8675             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8676             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8677             if(res.size()==2)
8678               {
8679                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8680               }
8681             else
8682               {
8683                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8684               }
8685             break;
8686           }
8687         default:
8688           {// case when plane is on a multi colinear edge of a polyhedron
8689             if((int)res.size()==2*nbOfSeg)
8690               {
8691                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8692               }
8693             else
8694               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8695           }
8696         }
8697     }
8698 }
8699
8700 /*!
8701  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8702  * This method is part of the Slice3D algorithm. It is the second step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
8703  * This method allows to compute given the result of 3D surf cells with plane and the descending connectivity 3D->3DSurf to deduce the intersection of each 3D cells
8704  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8705  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8706  * \param desc is the descending connectivity 3D->3DSurf
8707  * \param descIndx is the descending connectivity index 3D->3DSurf
8708  */
8709 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8710                                                   const int *desc, const int *descIndx,
8711                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8712 {
8713   checkFullyDefined();
8714   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8715     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8716   const int *nodal3D=_nodal_connec->getConstPointer();
8717   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8718   int nbOfCells=getNumberOfCells();
8719   for(int i=0;i<nbOfCells;i++)
8720     {
8721       std::map<int, std::set<int> > m;
8722       int offset=descIndx[i];
8723       int nbOfFaces=descIndx[i+1]-offset;
8724       int start=-1;
8725       int end=-1;
8726       for(int j=0;j<nbOfFaces;j++)
8727         {
8728           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8729           if(p.first!=-1 && p.second!=-1)
8730             {
8731               if(p.first!=-2)
8732                 {
8733                   start=p.first; end=p.second;
8734                   m[p.first].insert(p.second);
8735                   m[p.second].insert(p.first);
8736                 }
8737               else
8738                 {
8739                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8740                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8741                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8742                   INTERP_KERNEL::NormalizedCellType cmsId;
8743                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8744                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8745                   for(unsigned k=0;k<nbOfNodesSon;k++)
8746                     {
8747                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8748                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8749                     }
8750                 }
8751             }
8752         }
8753       if(m.empty())
8754         continue;
8755       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8756       int prev=end;
8757       while(end!=start)
8758         {
8759           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8760           const std::set<int>& s=(*it).second;
8761           std::set<int> s2; s2.insert(prev);
8762           std::set<int> s3;
8763           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8764           if(s3.size()==1)
8765             {
8766               int val=*s3.begin();
8767               conn.push_back(start);
8768               prev=start;
8769               start=val;
8770             }
8771           else
8772             start=end;
8773         }
8774       conn.push_back(end);
8775       if(conn.size()>3)
8776         {
8777           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8778           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8779           cellIds->pushBackSilent(i);
8780         }
8781     }
8782 }
8783
8784 /*!
8785  * This method compute the convex hull of a single 2D cell. This method tries to conserve at maximum the given input connectivity. In particular, if the orientation of cell is not clockwise
8786  * as in MED format norm. If definitely the result of Jarvis algorithm is not matchable with the input connectivity, the result will be copied into \b nodalConnecOut parameter and
8787  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8788  * This method excepts that \b coords parameter is expected to be in dimension 2. [\b nodalConnBg, \b nodalConnEnd) is the nodal connectivity of the input
8789  * cell (geometric cell type included at the position 0). If the meshdimension of the input cell is not equal to 2 an INTERP_KERNEL::Exception will be thrown.
8790  * 
8791  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8792  */
8793 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8794 {
8795   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8796   if(sz>=4)
8797     {
8798       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8799       if(cm.getDimension()==2)
8800         {
8801           const int *node=nodalConnBg+1;
8802           int startNode=*node++;
8803           double refX=coords[2*startNode];
8804           for(;node!=nodalConnEnd;node++)
8805             {
8806               if(coords[2*(*node)]<refX)
8807                 {
8808                   startNode=*node;
8809                   refX=coords[2*startNode];
8810                 }
8811             }
8812           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8813           refX=1e300;
8814           double tmp1;
8815           double tmp2[2];
8816           double angle0=-M_PI/2;
8817           //
8818           int nextNode=-1;
8819           int prevNode=-1;
8820           double resRef;
8821           double angleNext=0.;
8822           while(nextNode!=startNode)
8823             {
8824               nextNode=-1;
8825               resRef=1e300;
8826               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8827                 {
8828                   if(*node!=tmpOut.back() && *node!=prevNode)
8829                     {
8830                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8831                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8832                       double res;
8833                       if(angleM<=angle0)
8834                         res=angle0-angleM;
8835                       else
8836                         res=angle0-angleM+2.*M_PI;
8837                       if(res<resRef)
8838                         {
8839                           nextNode=*node;
8840                           resRef=res;
8841                           angleNext=angleM;
8842                         }
8843                     }
8844                 }
8845               if(nextNode!=startNode)
8846                 {
8847                   angle0=angleNext-M_PI;
8848                   if(angle0<-M_PI)
8849                     angle0+=2*M_PI;
8850                   prevNode=tmpOut.back();
8851                   tmpOut.push_back(nextNode);
8852                 }
8853             }
8854           std::vector<int> tmp3(2*(sz-1));
8855           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8856           std::copy(nodalConnBg+1,nodalConnEnd,it);
8857           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8858             {
8859               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8860               return false;
8861             }
8862           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8863             {
8864               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8865               return false;
8866             }
8867           else
8868             {
8869               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8870               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8871               return true;
8872             }
8873         }
8874       else
8875         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8876     }
8877   else
8878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8879 }
8880
8881 /*!
8882  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8883  * This method will not impact the size of inout parameter \b arrIndx but the size of \b arr will be modified in case of suppression.
8884  * 
8885  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8886  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8887  * \param [in,out] arr array in which the remove operation will be done.
8888  * \param [in,out] arrIndx array in the remove operation will modify
8889  * \param [in] offsetForRemoval (by default 0) offset so that for each i in [0,arrIndx->getNumberOfTuples()-1) removal process will be performed in the following range [arr+arrIndx[i]+offsetForRemoval,arr+arr[i+1])
8890  * \return true if \b arr and \b arrIndx have been modified, false if not.
8891  */
8892 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8893 {
8894   if(!arrIndx || !arr)
8895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8896   if(offsetForRemoval<0)
8897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8898   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8899   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8900   int *arrIPtr=arrIndx->getPointer();
8901   *arrIPtr++=0;
8902   int previousArrI=0;
8903   const int *arrPtr=arr->getConstPointer();
8904   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8905   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8906     {
8907       if(*arrIPtr-previousArrI>offsetForRemoval)
8908         {
8909           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8910             {
8911               if(s.find(*work)==s.end())
8912                 arrOut.push_back(*work);
8913             }
8914         }
8915       previousArrI=*arrIPtr;
8916       *arrIPtr=(int)arrOut.size();
8917     }
8918   if(arr->getNumberOfTuples()==(int)arrOut.size())
8919     return false;
8920   arr->alloc((int)arrOut.size(),1);
8921   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8922   return true;
8923 }
8924
8925 /*!
8926  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8927  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8928  * The selection of extraction is done standardly in new2old format.
8929  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8930  *
8931  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8932  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8933  * \param [in] arrIn arr origin array from which the extraction will be done.
8934  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8935  * \param [out] arrOut the resulting array
8936  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8937  */
8938 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8939                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8940 {
8941   if(!arrIn || !arrIndxIn)
8942     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8943   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8944   const int *arrInPtr=arrIn->getConstPointer();
8945   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8946   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8947   int maxSizeOfArr=arrIn->getNumberOfTuples();
8948   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8949   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8950   arrIo->alloc((int)(sz+1),1);
8951   const int *idsIt=idsOfSelectBg;
8952   int *work=arrIo->getPointer();
8953   *work++=0;
8954   int lgth=0;
8955   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8956     {
8957       if(*idsIt>=0 && *idsIt<nbOfGrps)
8958         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8959       else
8960         {
8961           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8962           throw INTERP_KERNEL::Exception(oss.str().c_str());
8963         }
8964       if(lgth>=work[-1])
8965         *work=lgth;
8966       else
8967         {
8968           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8969           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8970           throw INTERP_KERNEL::Exception(oss.str().c_str());
8971         }
8972     }
8973   arro->alloc(lgth,1);
8974   work=arro->getPointer();
8975   idsIt=idsOfSelectBg;
8976   for(std::size_t i=0;i<sz;i++,idsIt++)
8977     {
8978       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8979         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8980       else
8981         {
8982           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8983           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8984           throw INTERP_KERNEL::Exception(oss.str().c_str());
8985         }
8986     }
8987   arrOut=arro.retn();
8988   arrIndexOut=arrIo.retn();
8989 }
8990
8991 /*!
8992  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8993  * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [\b idsOfSelectBg, \b idsOfSelectEnd) and for
8994  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8995  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8996  *
8997  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8998  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8999  * \param [in] arrIn arr origin array from which the extraction will be done.
9000  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9001  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9002  * \param [in] srcArrIndex index array of \b srcArr
9003  * \param [out] arrOut the resulting array
9004  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9005  * 
9006  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9007  */
9008 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9009                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9010                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9011 {
9012   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9013     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9016   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9017   std::vector<bool> v(nbOfTuples,true);
9018   int offset=0;
9019   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9020   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9021   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9022     {
9023       if(*it>=0 && *it<nbOfTuples)
9024         {
9025           v[*it]=false;
9026           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9027         }
9028       else
9029         {
9030           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9031           throw INTERP_KERNEL::Exception(oss.str().c_str());
9032         }
9033     }
9034   srcArrIndexPtr=srcArrIndex->getConstPointer();
9035   arrIo->alloc(nbOfTuples+1,1);
9036   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9037   const int *arrInPtr=arrIn->getConstPointer();
9038   const int *srcArrPtr=srcArr->getConstPointer();
9039   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9040   int *arroPtr=arro->getPointer();
9041   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9042     {
9043       if(v[ii])
9044         {
9045           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9046           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9047         }
9048       else
9049         {
9050           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9051           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9052           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9053         }
9054     }
9055   arrOut=arro.retn();
9056   arrIndexOut=arrIo.retn();
9057 }
9058
9059 /*!
9060  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9061  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9062  *
9063  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9064  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9065  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9066  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9067  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9068  * \param [in] srcArrIndex index array of \b srcArr
9069  * 
9070  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9071  */
9072 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9073                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9074 {
9075   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9076     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9077   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9078   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9079   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9080   int *arrInOutPtr=arrInOut->getPointer();
9081   const int *srcArrPtr=srcArr->getConstPointer();
9082   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9083     {
9084       if(*it>=0 && *it<nbOfTuples)
9085         {
9086           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9087             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9088           else
9089             {
9090               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " id (idsOfSelectBg[" << std::distance(idsOfSelectBg,it)<< "]) is " << *it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9091               throw INTERP_KERNEL::Exception(oss.str().c_str());
9092             }
9093         }
9094       else
9095         {
9096           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9097           throw INTERP_KERNEL::Exception(oss.str().c_str());
9098         }
9099     }
9100 }
9101
9102 /*!
9103  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9104  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9105  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
9106  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9107  * A negative value in \b arrIn means that it is ignored.
9108  * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
9109  * 
9110  * \param [in] arrIn arr origin array from which the extraction will be done.
9111  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9112  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9113  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9114  */
9115 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9116 {
9117   int seed=0,nbOfDepthPeelingPerformed=0;
9118   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9119 }
9120
9121 /*!
9122  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9123  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9124  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
9125  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9126  * A negative value in \b arrIn means that it is ignored.
9127  * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
9128  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9129  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9130  * \param [in] arrIn arr origin array from which the extraction will be done.
9131  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9132  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9133  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9134  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9135  * \sa MEDCouplingUMesh::partitionBySpreadZone
9136  */
9137 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9138 {
9139   nbOfDepthPeelingPerformed=0;
9140   if(!arrIndxIn)
9141     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9142   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9143   if(nbOfTuples<=0)
9144     {
9145       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9146       return ret;
9147     }
9148   //
9149   std::vector<bool> fetched(nbOfTuples,false);
9150   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9151 }
9152
9153 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9154 {
9155   nbOfDepthPeelingPerformed=0;
9156   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9157     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9158   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9159   std::vector<bool> fetched2(nbOfTuples,false);
9160   int i=0;
9161   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9162     {
9163       if(*seedElt>=0 && *seedElt<nbOfTuples)
9164         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9165       else
9166         { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
9167     }
9168   const int *arrInPtr=arrIn->getConstPointer();
9169   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9170   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9171   std::vector<int> idsToFetch1(seedBg,seedEnd);
9172   std::vector<int> idsToFetch2;
9173   std::vector<int> *idsToFetch=&idsToFetch1;
9174   std::vector<int> *idsToFetchOther=&idsToFetch2;
9175   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9176     {
9177       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9178         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9179           if(!fetched[*it2])
9180             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9181       std::swap(idsToFetch,idsToFetchOther);
9182       idsToFetchOther->clear();
9183       nbOfDepthPeelingPerformed++;
9184     }
9185   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9186   i=0;
9187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9188   int *retPtr=ret->getPointer();
9189   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9190     if(*it)
9191       *retPtr++=i;
9192   return ret.retn();
9193 }
9194
9195 /*!
9196  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9197  * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [\b idsOfSelectBg, \b idsOfSelectEnd) and for
9198  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9199  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9200  *
9201  * \param [in] start begin of set of ids of the input extraction (included)
9202  * \param [in] end end of set of ids of the input extraction (excluded)
9203  * \param [in] step step of the set of ids in range mode.
9204  * \param [in] arrIn arr origin array from which the extraction will be done.
9205  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9206  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9207  * \param [in] srcArrIndex index array of \b srcArr
9208  * \param [out] arrOut the resulting array
9209  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9210  * 
9211  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9212  */
9213 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9214                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9215                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9216 {
9217   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9218     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9221   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9222   int offset=0;
9223   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9224   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9225   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9226   int it=start;
9227   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9228     {
9229       if(it>=0 && it<nbOfTuples)
9230         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9231       else
9232         {
9233           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9234           throw INTERP_KERNEL::Exception(oss.str().c_str());
9235         }
9236     }
9237   srcArrIndexPtr=srcArrIndex->getConstPointer();
9238   arrIo->alloc(nbOfTuples+1,1);
9239   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9240   const int *arrInPtr=arrIn->getConstPointer();
9241   const int *srcArrPtr=srcArr->getConstPointer();
9242   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9243   int *arroPtr=arro->getPointer();
9244   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9245     {
9246       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9247       if(pos<0)
9248         {
9249           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9250           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9251         }
9252       else
9253         {
9254           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9255           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9256         }
9257     }
9258   arrOut=arro.retn();
9259   arrIndexOut=arrIo.retn();
9260 }
9261
9262 /*!
9263  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9264  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9265  *
9266  * \param [in] start begin of set of ids of the input extraction (included)
9267  * \param [in] end end of set of ids of the input extraction (excluded)
9268  * \param [in] step step of the set of ids in range mode.
9269  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9270  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9271  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9272  * \param [in] srcArrIndex index array of \b srcArr
9273  * 
9274  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9275  */
9276 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9277                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9278 {
9279   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9281   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9282   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9283   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9284   int *arrInOutPtr=arrInOut->getPointer();
9285   const int *srcArrPtr=srcArr->getConstPointer();
9286   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9287   int it=start;
9288   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9289     {
9290       if(it>=0 && it<nbOfTuples)
9291         {
9292           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9293             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9294           else
9295             {
9296               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9297               throw INTERP_KERNEL::Exception(oss.str().c_str());
9298             }
9299         }
9300       else
9301         {
9302           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9303           throw INTERP_KERNEL::Exception(oss.str().c_str());
9304         }
9305     }
9306 }
9307
9308 /*!
9309  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9310  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9311  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9312  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9313  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9314  * 
9315  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9316  */
9317 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9318 {
9319   checkFullyDefined();
9320   int mdim=getMeshDimension();
9321   int spaceDim=getSpaceDimension();
9322   if(mdim!=spaceDim)
9323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9324   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9325   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9326   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9327   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9328   ret->setCoords(getCoords());
9329   ret->allocateCells((int)partition.size());
9330   //
9331   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9332     {
9333       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9334       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9335       switch(mdim)
9336         {
9337         case 2:
9338           cell=tmp->buildUnionOf2DMesh();
9339           break;
9340         case 3:
9341           cell=tmp->buildUnionOf3DMesh();
9342           break;
9343         default:
9344           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9345         }
9346       
9347       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9348     }
9349   //
9350   ret->finishInsertingCells();
9351   return ret.retn();
9352 }
9353
9354 /*!
9355  * This method partitions \b this into contiguous zone.
9356  * This method only needs a well defined connectivity. Coordinates are not considered here.
9357  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9358  */
9359 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9360 {
9361   //#if 0
9362   int nbOfCellsCur=getNumberOfCells();
9363   std::vector<DataArrayInt *> ret;
9364   if(nbOfCellsCur<=0)
9365     return ret;
9366   DataArrayInt *neigh=0,*neighI=0;
9367   computeNeighborsOfCells(neigh,neighI);
9368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9369   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9370   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9371   int seed=0;
9372   while(seed<nbOfCellsCur)
9373     {
9374       int nbOfPeelPerformed=0;
9375       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9376       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9377     }
9378   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9379     ret.push_back((*it).retn());
9380   return ret;
9381   //#endif
9382 #if 0
9383   int nbOfCellsCur=getNumberOfCells();
9384   DataArrayInt *neigh=0,*neighI=0;
9385   computeNeighborsOfCells(neigh,neighI);
9386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9388   std::vector<DataArrayInt *> ret;
9389   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9390   while(nbOfCellsCur>0)
9391     {
9392       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9393       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9394       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9395       ret2.push_back(tmp2);  ret.push_back(tmp2);
9396       nbOfCellsCur=tmp3->getNumberOfTuples();
9397       if(nbOfCellsCur>0)
9398         {
9399           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9400           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9401           neighAuto=neigh;
9402           neighIAuto=neighI;
9403           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9404           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9405         }
9406     }
9407   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9408     (*it)->incrRef();
9409   return ret;
9410 #endif
9411 }
9412
9413 /*!
9414  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9415  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9416  *
9417  * \param [in] code a code with the same format than those returned by MEDCouplingUMesh::getDistributionOfTypes except for the code[3*k+2] that should contain start id of chunck.
9418  * \return a newly allocated DataArrayInt to be managed by the caller.
9419  * \throw In case of \a code has not the right format (typically of size 3*n)
9420  */
9421 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9422 {
9423   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9424   std::size_t nb=code.size()/3;
9425   if(code.size()%3!=0)
9426     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9427   ret->alloc((int)nb,2);
9428   int *retPtr=ret->getPointer();
9429   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9430     {
9431       retPtr[0]=code[3*i+2];
9432       retPtr[1]=code[3*i+2]+code[3*i+1];
9433     }
9434   return ret.retn();
9435 }
9436
9437 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9438                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9439 {
9440   if(mesh)
9441     {
9442       mesh->incrRef();
9443       _nb_cell=mesh->getNumberOfCells();
9444     }
9445 }
9446
9447 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9448 {
9449   if(_mesh)
9450     _mesh->decrRef();
9451   if(_own_cell)
9452     delete _cell;
9453 }
9454
9455 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9456                                                                                                                                _own_cell(false),_cell_id(bg-1),
9457                                                                                                                                _nb_cell(end)
9458 {
9459   if(mesh)
9460     mesh->incrRef();
9461 }
9462
9463 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9464 {
9465   _cell_id++;
9466   if(_cell_id<_nb_cell)
9467     {
9468       _cell->next();
9469       return _cell;
9470     }
9471   else
9472     return 0;
9473 }
9474
9475 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9476 {
9477   if(_mesh)
9478     _mesh->incrRef();
9479 }
9480
9481 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9482 {
9483   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9484 }
9485
9486 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9487 {
9488   if(_mesh)
9489     _mesh->decrRef();
9490 }
9491
9492 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9493                                                                                                                                                                   _itc(itc),
9494                                                                                                                                                                   _bg(bg),_end(end)
9495 {
9496   if(_mesh)
9497     _mesh->incrRef();
9498 }
9499
9500 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9501 {
9502   if(_mesh)
9503     _mesh->decrRef();
9504 }
9505
9506 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9507 {
9508   return _type;
9509 }
9510
9511 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9512 {
9513   return _end-_bg;
9514 }
9515
9516 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9517 {
9518   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9519 }
9520
9521 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9522 {
9523   if(mesh)
9524     {
9525       mesh->incrRef();
9526       _nb_cell=mesh->getNumberOfCells();
9527     }
9528 }
9529
9530 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9531 {
9532   if(_mesh)
9533     _mesh->decrRef();
9534   delete _cell;
9535 }
9536
9537 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9538 {
9539   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9540   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9541   if(_cell_id<_nb_cell)
9542     {
9543       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9544       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9545       int startId=_cell_id;
9546       _cell_id+=nbOfElems;
9547       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9548     }
9549   else
9550     return 0;
9551 }
9552
9553 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9554 {
9555   if(mesh)
9556     {
9557       _conn=mesh->getNodalConnectivity()->getPointer();
9558       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9559     }
9560 }
9561
9562 void MEDCouplingUMeshCell::next()
9563 {
9564   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9565     {
9566       _conn+=_conn_lgth;
9567       _conn_indx++;
9568     }
9569   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9570 }
9571
9572 std::string MEDCouplingUMeshCell::repr() const
9573 {
9574   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9575     {
9576       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9577       oss << " : ";
9578       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9579       return oss.str();
9580     }
9581   else
9582     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9583 }
9584
9585 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9586 {
9587   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9588     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9589   else
9590     return INTERP_KERNEL::NORM_ERROR;
9591 }
9592
9593 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9594 {
9595   lgth=_conn_lgth;
9596   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9597     return _conn;
9598   else
9599     return 0;
9600 }