Salome HOME
Merge from V6_main (dev of Anthony GEAY) 11/06/2013
[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 '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  */
377 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
378 {
379   return _types;
380 }
381
382 /*!
383  * This method is a method that compares 'this' and 'other'.
384  * This method compares \b all attributes, even names and component names.
385  */
386 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
387 {
388   if(!other)
389     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
390   std::ostringstream oss; oss.precision(15);
391   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
392   if(!otherC)
393     {
394       reason="mesh given in input is not castable in MEDCouplingUMesh !";
395       return false;
396     }
397   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
398     return false;
399   if(_mesh_dim!=otherC->_mesh_dim)
400     {
401       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
402       reason=oss.str();
403       return false;
404     }
405   if(_types!=otherC->_types)
406     {
407       oss << "umesh geometric type mismatch :\nThis geometric types are :";
408       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
409         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
410       oss << "\nOther geometric types are :";
411       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
412         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
413       reason=oss.str();
414       return false;
415     }
416   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
417     if(_nodal_connec==0 || otherC->_nodal_connec==0)
418       {
419         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
420         return false;
421       }
422   if(_nodal_connec!=otherC->_nodal_connec)
423     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
424       {
425         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
426         return false;
427       }
428   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
429     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
430       {
431         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
432         return false;
433       }
434   if(_nodal_connec_index!=otherC->_nodal_connec_index)
435     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
436       {
437         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
438         return false;
439       }
440   return true;
441 }
442
443 /*!
444  * Checks if data arrays of this mesh (node coordinates, nodal
445  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
446  * not considered.
447  *  \param [in] other - the mesh to compare with.
448  *  \param [in] prec - precision value used to compare node coordinates.
449  *  \return bool - \a true if the two meshes are same.
450  */
451 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
452 {
453   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
454   if(!otherC)
455     return false;
456   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
457     return false;
458   if(_mesh_dim!=otherC->_mesh_dim)
459     return false;
460   if(_types!=otherC->_types)
461     return false;
462   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
463     if(_nodal_connec==0 || otherC->_nodal_connec==0)
464       return false;
465   if(_nodal_connec!=otherC->_nodal_connec)
466     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
467       return false;
468   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
469     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
470       return false;
471   if(_nodal_connec_index!=otherC->_nodal_connec_index)
472     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
473       return false;
474   return true;
475 }
476
477 /*!
478  * Checks if \a this and \a other meshes are geometrically equivalent, else an
479  * exception is thrown. The meshes are
480  * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
481  * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
482  * the \a other mesh (with use of a specified cell comparison technique). The mapping 
483  * from \a other to \a this for nodes and cells is returned via out parameters.
484  *  \param [in] other - the mesh to compare with.
485  *  \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
486  *         each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
487  *  \param [in] prec - the precision used to compare nodes of the two meshes.
488  *  \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
489  *         to delete this array using decrRef() as it is no more needed.
490  *  \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
491  *         to delete this array using decrRef() as it is no more needed.
492  *  \throw If the two meshes do not match.
493  *
494  *  \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
495  *  \ref  py_mcumesh_checkDeepEquivalWith "Here is a Python example".
496  */
497 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
498                                             DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
499 {
500   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
501   if(!otherC)
502     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
503   MEDCouplingMesh::checkFastEquivalWith(other,prec);
504   if(_types!=otherC->_types)
505     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
506   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
507   bool areNodesMerged;
508   int newNbOfNodes;
509   int oldNbOfNodes=getNumberOfNodes();
510   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
511   //mergeNodes
512   if(!areNodesMerged)
513     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
514   const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
515   if(pt!=da->getConstPointer()+da->getNbOfElems())
516     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
517   m->renumberNodes(da->getConstPointer(),newNbOfNodes);
518   //
519   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
520   da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
521   
522   //
523   da=m->zipConnectivityTraducer(cellCompPol);
524   int nbCells=getNumberOfCells();
525   int maxId=-1;
526   if(nbCells!=0)
527     maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells);
528   pt=std::find_if(da->getConstPointer()+nbCells,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
529   if(pt!=da->getConstPointer()+da->getNbOfElems())
530     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
531   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(nbCells,da->getNbOfElems(),1);
532   nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
533   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
534 }
535
536 /*!
537  * Checks if \a this and \a other meshes are geometrically equivalent, else an
538  * exception is thrown. The meshes are considered equivalent if (1) they share one
539  * node coordinates array and (2) they contain the same cells (with use of a specified
540  * cell comparison technique). The mapping from cells of the \a other to ones of \a this 
541  * is returned via an out parameter.
542  *  \param [in] other - the mesh to compare with.
543  *  \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
544  *         each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
545  *  \param [in] prec - a not used parameter.
546  *  \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
547  *         to delete this array using decrRef() as it is no more needed.
548  *  \throw If the two meshes do not match.
549  *
550  * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
551  * \ref  py_mcumesh_checkDeepEquivalWith "Here is a Python example".
552  */
553 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
554                                                        DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
555 {
556   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
557   if(!otherC)
558     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
559   MEDCouplingMesh::checkFastEquivalWith(other,prec);
560   if(_types!=otherC->_types)
561     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
562   if(_coords!=otherC->_coords)
563     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
564   std::vector<const MEDCouplingUMesh *> ms(2);
565   ms[0]=this;
566   ms[1]=otherC;
567   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
568   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
569   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
570   const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
571   if(pt!=da->getConstPointer()+da->getNbOfElems())
572     {
573       throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
574     }
575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
576   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
577 }
578
579 /*!
580  * Checks if \a this and \a other meshes are geometrically equivalent with high
581  * probability, else an exception is thrown. The meshes are considered equivalent if
582  * (1) meshes contain the same number of nodes and the same number of elements of the
583  * same types (2) three cells of the two meshes (first, last and middle) are based
584  * on coincident nodes (with a specified precision).
585  *  \param [in] other - the mesh to compare with.
586  *  \param [in] prec - the precision used to compare nodes of the two meshes.
587  *  \throw If the two meshes do not match.
588  */
589 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
590 {
591   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
592   if(!otherC)
593     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
594   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
595   int nbOfCells=getNumberOfCells();
596   if(nbOfCells<1)
597     return ;
598   bool status=true;
599   status&=areCellsFrom2MeshEqual(otherC,0,prec);
600   status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
601   status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
602   if(!status)
603     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
604 }
605
606 /*!
607  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
608  * cells each node belongs to.
609  * \warning For speed reasons, this method does not check if node ids in the nodal
610  *          connectivity correspond to the size of node coordinates array.
611  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
612  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
613  *        dividing cell ids in \a revNodal into groups each referring to one
614  *        node. Its every element (except the last one) is an index pointing to the
615  *         first id of a group of cells. For example cells sharing the node #1 are 
616  *        described by following range of indices: 
617  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
618  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
619  *        Number of cells sharing the *i*-th node is
620  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
621  * \throw If the coordinates array is not set.
622  * \throw If the nodal connectivity of cells is not defined.
623  * 
624  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
625  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
626  */
627 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
628 {
629   checkFullyDefined();
630   int nbOfNodes=getNumberOfNodes();
631   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
632   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
633   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
634   const int *conn=_nodal_connec->getConstPointer();
635   const int *connIndex=_nodal_connec_index->getConstPointer();
636   int nbOfCells=getNumberOfCells();
637   int nbOfEltsInRevNodal=0;
638   for(int eltId=0;eltId<nbOfCells;eltId++)
639     {
640       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
641       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
642       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
643         if(*iter>=0)//for polyhedrons
644           {
645             nbOfEltsInRevNodal++;
646             revNodalIndxPtr[(*iter)+1]++;
647           }
648     }
649   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
650   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
651   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
652   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
653   for(int eltId=0;eltId<nbOfCells;eltId++)
654     {
655       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
656       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
657       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
658         if(*iter>=0)//for polyhedrons
659           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
660     }
661 }
662
663 /// @cond INTERNAL
664
665 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
666 {
667   return id;
668 }
669
670 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
671 {
672   if(!compute)
673     return id+1;
674   else
675     {
676       if(cm.getOrientationStatus(nb,conn1,conn2))
677         return id+1;
678       else
679         return -(id+1);
680     }
681 }
682
683 class MinusOneSonsGenerator
684 {
685 public:
686   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
688   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689   static const int DELTA=1;
690 private:
691   const INTERP_KERNEL::CellModel& _cm;
692 };
693
694 class MinusOneSonsGeneratorBiQuadratic
695 {
696 public:
697   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
698   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
699   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
700   static const int DELTA=1;
701 private:
702   const INTERP_KERNEL::CellModel& _cm;
703 };
704
705 class MinusTwoSonsGenerator
706 {
707 public:
708   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
709   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
710   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
711   static const int DELTA=2;
712 private:
713   const INTERP_KERNEL::CellModel& _cm;
714 };
715
716 /// @endcond
717
718 /*!
719  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
720  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
721  * describing correspondence between cells of \a this and the result meshes are
722  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
723  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
724  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
725  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
726  * \warning For speed reasons, this method does not check if node ids in the nodal
727  *          connectivity correspond to the size of node coordinates array.
728  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
729  *          to write this mesh to the MED file, its cells must be sorted using
730  *          sortCellsInMEDFileFrmt().
731  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
732  *         each cell of \a this mesh.
733  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
734  *        dividing cell ids in \a desc into groups each referring to one
735  *        cell of \a this mesh. Its every element (except the last one) is an index
736  *        pointing to the first id of a group of cells. For example cells of the
737  *        result mesh bounding the cell #1 of \a this mesh are described by following
738  *        range of indices:
739  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
740  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
741  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
742  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
743  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
744  *         by each cell of the result mesh.
745  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
746  *        in the result mesh,
747  *        dividing cell ids in \a revDesc into groups each referring to one
748  *        cell of the result mesh the same way as \a descIndx divides \a desc.
749  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
750  *        delete this mesh using decrRef() as it is no more needed.
751  *  \throw If the coordinates array is not set.
752  *  \throw If the nodal connectivity of cells is node defined.
753  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
754  *         revDescIndx == NULL.
755  * 
756  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
757  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
758  * \sa buildDescendingConnectivity2()
759  */
760 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
761 {
762   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
763 }
764
765 /*!
766  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
767  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
768  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
769  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
770  * \sa MEDCouplingUMesh::buildDescendingConnectivity
771  */
772 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
773 {
774   checkFullyDefined();
775   if(getMeshDimension()!=3)
776     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
777   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
778 }
779
780 /*!
781  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
782  * this->getMeshDimension(), that bound cells of \a this mesh. In
783  * addition arrays describing correspondence between cells of \a this and the result
784  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
785  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
786  *  mesh. This method differs from buildDescendingConnectivity() in that apart
787  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
788  * result meshes. So a positive id means that order of nodes in corresponding cells
789  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
790  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
791  * i.e. cell ids are one-based.
792  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
793  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
794  * \warning For speed reasons, this method does not check if node ids in the nodal
795  *          connectivity correspond to the size of node coordinates array.
796  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
797  *          to write this mesh to the MED file, its cells must be sorted using
798  *          sortCellsInMEDFileFrmt().
799  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
800  *         each cell of \a this mesh.
801  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
802  *        dividing cell ids in \a desc into groups each referring to one
803  *        cell of \a this mesh. Its every element (except the last one) is an index
804  *        pointing to the first id of a group of cells. For example cells of the
805  *        result mesh bounding the cell #1 of \a this mesh are described by following
806  *        range of indices:
807  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
808  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
809  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
810  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
811  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
812  *         by each cell of the result mesh.
813  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
814  *        in the result mesh,
815  *        dividing cell ids in \a revDesc into groups each referring to one
816  *        cell of the result mesh the same way as \a descIndx divides \a desc.
817  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
818  *        shares the node coordinates array with \a this mesh. The caller is to
819  *        delete this mesh using decrRef() as it is no more needed.
820  *  \throw If the coordinates array is not set.
821  *  \throw If the nodal connectivity of cells is node defined.
822  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
823  *         revDescIndx == NULL.
824  * 
825  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
826  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
827  * \sa buildDescendingConnectivity()
828  */
829 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
830 {
831   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
832 }
833
834 /*!
835  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
836  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
837  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
838  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
839  *
840  * \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
841  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
842  * \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.
843  */
844 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
845 {
846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
847   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
850   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
851   meshDM1=0;
852   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
853 }
854
855 /*!
856  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
857  * 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,
858  * excluding a set of meshdim-1 cells in input descending connectivity.
859  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
860  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
861  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
862  *
863  * \param [in] desc descending connectivity array.
864  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
865  * \param [in] revDesc reverse descending connectivity array.
866  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
867  * \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
868  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
869  * \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.
870  */
871 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
872                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
873 {
874   if(!desc || !descIndx || !revDesc || !revDescIndx)
875     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
876   const int *descPtr=desc->getConstPointer();
877   const int *descIPtr=descIndx->getConstPointer();
878   const int *revDescPtr=revDesc->getConstPointer();
879   const int *revDescIPtr=revDescIndx->getConstPointer();
880   //
881   int nbCells=descIndx->getNumberOfTuples()-1;
882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
884   int *out1Ptr=out1->getPointer();
885   *out1Ptr++=0;
886   out0->reserve(desc->getNumberOfTuples());
887   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
888     {
889       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
890         {
891           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
892           s.erase(i);
893           out0->insertAtTheEnd(s.begin(),s.end());
894         }
895       *out1Ptr=out0->getNumberOfTuples();
896     }
897   neighbors=out0.retn();
898   neighborsIndx=out1.retn();
899 }
900
901 /// @cond INTERNAL
902
903 /*!
904  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
905  * For speed reasons no check of this will be done.
906  */
907 template<class SonsGenerator>
908 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
909 {
910   if(!desc || !descIndx || !revDesc || !revDescIndx)
911     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
912   checkConnectivityFullyDefined();
913   int nbOfCells=getNumberOfCells();
914   int nbOfNodes=getNumberOfNodes();
915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
916   int *revNodalIndxPtr=revNodalIndx->getPointer();
917   const int *conn=_nodal_connec->getConstPointer();
918   const int *connIndex=_nodal_connec_index->getConstPointer();
919   std::string name="Mesh constituent of "; name+=getName();
920   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
921   ret->setCoords(getCoords());
922   ret->allocateCells(2*nbOfCells);
923   descIndx->alloc(nbOfCells+1,1);
924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
925   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
926   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
927     {
928       int pos=connIndex[eltId];
929       int posP1=connIndex[eltId+1];
930       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
931       SonsGenerator sg(cm);
932       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
933       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
934       for(unsigned i=0;i<nbOfSons;i++)
935         {
936           INTERP_KERNEL::NormalizedCellType cmsId;
937           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
938           for(unsigned k=0;k<nbOfNodesSon;k++)
939             if(tmp[k]>=0)
940               revNodalIndxPtr[tmp[k]+1]++;
941           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
942           revDesc2->pushBackSilent(eltId);
943         }
944       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
945     }
946   int nbOfCellsM1=ret->getNumberOfCells();
947   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
948   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
949   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
950   int *revNodalPtr=revNodal->getPointer();
951   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
952   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
953   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
954     {
955       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
956       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
957       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
958         if(*iter>=0)//for polyhedrons
959           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
960     }
961   //
962   DataArrayInt *commonCells=0,*commonCellsI=0;
963   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
964   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
965   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
966   int newNbOfCellsM1=-1;
967   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
968                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
969   std::vector<bool> isImpacted(nbOfCellsM1,false);
970   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
971     for(int work2=work[0];work2!=work[1];work2++)
972       isImpacted[commonCellsPtr[work2]]=true;
973   const int *o2nM1Ptr=o2nM1->getConstPointer();
974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
975   const int *n2oM1Ptr=n2oM1->getConstPointer();
976   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
977   ret2->copyTinyInfoFrom(this);
978   desc->alloc(descIndx->back(),1);
979   int *descPtr=desc->getPointer();
980   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
981   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
982     {
983       if(!isImpacted[i])
984         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
985       else
986         {
987           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
988             {
989               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
990               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
991             }
992           else
993             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
994         }
995     }
996   revDesc->reserve(newNbOfCellsM1);
997   revDescIndx->alloc(newNbOfCellsM1+1,1);
998   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
999   const int *revDesc2Ptr=revDesc2->getConstPointer();
1000   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1001     {
1002       int oldCellIdM1=n2oM1Ptr[i];
1003       if(!isImpacted[oldCellIdM1])
1004         {
1005           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1006           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1007         }
1008       else
1009         {
1010           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1011             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1012           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1013           commonCellsIPtr++;
1014         }
1015     }
1016   //
1017   return ret2.retn();
1018 }
1019
1020 struct MEDCouplingAccVisit
1021 {
1022   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1023   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1024   int _new_nb_of_nodes;
1025 };
1026
1027 /// @endcond
1028
1029 /*!
1030  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1031  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1032  * array of cell ids. Pay attention that after conversion all algorithms work slower
1033  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1034  * conversion due presence of invalid ids in the array of cells to convert, as a
1035  * result \a this mesh contains some already converted elements. In this case the 2D
1036  * mesh remains valid but 3D mesh becomes \b inconsistent!
1037  *  \warning This method can significantly modify the order of geometric types in \a this,
1038  *          hence, to write this mesh to the MED file, its cells must be sorted using
1039  *          sortCellsInMEDFileFrmt().
1040  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1041  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1042  *         cellIdsToConvertBg.
1043  *  \throw If the coordinates array is not set.
1044  *  \throw If the nodal connectivity of cells is node defined.
1045  *  \throw If dimension of \a this mesh is not either 2 or 3.
1046  *
1047  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1048  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1049  */
1050 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1051 {
1052   checkFullyDefined();
1053   int dim=getMeshDimension();
1054   if(dim<2 || dim>3)
1055     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1056   int nbOfCells=getNumberOfCells();
1057   if(dim==2)
1058     {
1059       const int *connIndex=_nodal_connec_index->getConstPointer();
1060       int *conn=_nodal_connec->getPointer();
1061       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1062         {
1063           if(*iter>=0 && *iter<nbOfCells)
1064             {
1065               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1066               if(!cm.isQuadratic())
1067                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1068               else
1069                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1070             }
1071           else
1072             {
1073               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1074               oss << " in range [0," << nbOfCells << ") !";
1075               throw INTERP_KERNEL::Exception(oss.str().c_str());
1076             }
1077         }
1078     }
1079   else
1080     {
1081       int *connIndex=_nodal_connec_index->getPointer();
1082       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1083       const int *connOld=_nodal_connec->getConstPointer();
1084       int connOldLgth=_nodal_connec->getNbOfElems();
1085       std::vector<int> connNew(connOld,connOld+connOldLgth);
1086       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1087         {
1088           if(*iter>=0 && *iter<nbOfCells)
1089             {
1090               int pos=connIndex[*iter];
1091               int posP1=connIndex[(*iter)+1];
1092               int lgthOld=posP1-pos-1;
1093               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1094               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1095               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1096               int *tmp=new int[nbOfFaces*lgthOld];
1097               int *work=tmp;
1098               for(int j=0;j<(int)nbOfFaces;j++)
1099                 {
1100                   INTERP_KERNEL::NormalizedCellType type;
1101                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1102                   work+=offset;
1103                   *work++=-1;
1104                 }
1105               std::size_t newLgth=std::distance(tmp,work)-1;
1106               std::size_t delta=newLgth-lgthOld;
1107               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1108               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1109               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1110               delete [] tmp;
1111             }
1112           else
1113             {
1114               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1115               oss << " in range [0," << nbOfCells << ") !";
1116               throw INTERP_KERNEL::Exception(oss.str().c_str());
1117             }
1118         }
1119       _nodal_connec->alloc((int)connNew.size(),1);
1120       int *newConnPtr=_nodal_connec->getPointer();
1121       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1122     }
1123   computeTypes();
1124 }
1125
1126 /*!
1127  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1128  * polyhedrons (if \a this is a 3D mesh).
1129  *  \warning As this method is purely for user-friendliness and no optimization is
1130  *          done to avoid construction of a useless vector, this method can be costly
1131  *          in memory.
1132  *  \throw If the coordinates array is not set.
1133  *  \throw If the nodal connectivity of cells is node defined.
1134  *  \throw If dimension of \a this mesh is not either 2 or 3.
1135  */
1136 void MEDCouplingUMesh::convertAllToPoly()
1137 {
1138   int nbOfCells=getNumberOfCells();
1139   std::vector<int> cellIds(nbOfCells);
1140   for(int i=0;i<nbOfCells;i++)
1141     cellIds[i]=i;
1142   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1143 }
1144
1145 /*!
1146  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1147  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1148  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1149  * base facet of the volume and the second half of nodes describes an opposite facet
1150  * having the same number of nodes as the base one. This method converts such
1151  * connectivity to a valid polyhedral format where connectivity of each facet is
1152  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1153  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1154  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1155  * a correct orientation of the first facet of a polyhedron, else orientation of a
1156  * corrected cell is reverse.<br>
1157  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1158  * it releases the user from boring description of polyhedra connectivity in the valid
1159  * format.
1160  *  \throw If \a this->getMeshDimension() != 3.
1161  *  \throw If \a this->getSpaceDimension() != 3.
1162  *  \throw If the nodal connectivity of cells is not defined.
1163  *  \throw If the coordinates array is not set.
1164  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1165  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1166  *
1167  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1168  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1169  */
1170 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1171 {
1172   checkFullyDefined();
1173   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1175   int nbOfCells=getNumberOfCells();
1176   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1177   newCi->alloc(nbOfCells+1,1);
1178   int *newci=newCi->getPointer();
1179   const int *ci=_nodal_connec_index->getConstPointer();
1180   const int *c=_nodal_connec->getConstPointer();
1181   newci[0]=0;
1182   for(int i=0;i<nbOfCells;i++)
1183     {
1184       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1185       if(type==INTERP_KERNEL::NORM_POLYHED)
1186         {
1187           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1188             {
1189               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1190               throw INTERP_KERNEL::Exception(oss.str().c_str());
1191             }
1192           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1193           if(n2%2!=0)
1194             {
1195               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 !";
1196               throw INTERP_KERNEL::Exception(oss.str().c_str());
1197             }
1198           int n1=(int)(n2/2);
1199           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)
1200         }
1201       else
1202         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1203     }
1204   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1205   newC->alloc(newci[nbOfCells],1);
1206   int *newc=newC->getPointer();
1207   for(int i=0;i<nbOfCells;i++)
1208     {
1209       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1210       if(type==INTERP_KERNEL::NORM_POLYHED)
1211         {
1212           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1213           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1214           *newc++=-1;
1215           for(std::size_t j=0;j<n1;j++)
1216             {
1217               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1218               newc[n1+5*j]=-1;
1219               newc[n1+5*j+1]=c[ci[i]+1+j];
1220               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1221               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1222               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1223             }
1224           newc+=n1*6;
1225         }
1226       else
1227         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1228     }
1229   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1230   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1231 }
1232
1233
1234 /*!
1235  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1236  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1237  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1238  *          to write this mesh to the MED file, its cells must be sorted using
1239  *          sortCellsInMEDFileFrmt().
1240  * \return \c true if at least one cell has been converted, \c false else. In the
1241  *         last case the nodal connectivity remains unchanged.
1242  * \throw If the coordinates array is not set.
1243  * \throw If the nodal connectivity of cells is not defined.
1244  * \throw If \a this->getMeshDimension() < 0.
1245  */
1246 bool MEDCouplingUMesh::unPolyze()
1247 {
1248   checkFullyDefined();
1249   int mdim=getMeshDimension();
1250   if(mdim<0)
1251     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1252   if(mdim<=1)
1253     return false;
1254   int nbOfCells=getNumberOfCells();
1255   if(nbOfCells<1)
1256     return false;
1257   int initMeshLgth=getMeshLength();
1258   int *conn=_nodal_connec->getPointer();
1259   int *index=_nodal_connec_index->getPointer();
1260   int posOfCurCell=0;
1261   int newPos=0;
1262   int lgthOfCurCell;
1263   bool ret=false;
1264   for(int i=0;i<nbOfCells;i++)
1265     {
1266       lgthOfCurCell=index[i+1]-posOfCurCell;
1267       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1268       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1269       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1270       int newLgth;
1271       if(cm.isDynamic())
1272         {
1273           switch(cm.getDimension())
1274             {
1275             case 2:
1276               {
1277                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1278                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1279                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1280                 break;
1281               }
1282             case 3:
1283               {
1284                 int nbOfFaces,lgthOfPolyhConn;
1285                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1286                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1287                 break;
1288               }
1289             case 1:
1290               {
1291                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1292                 break;
1293               }
1294             }
1295           ret=ret || (newType!=type);
1296           conn[newPos]=newType;
1297           newPos+=newLgth+1;
1298           posOfCurCell=index[i+1];
1299           index[i+1]=newPos;
1300         }
1301       else
1302         {
1303           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1304           newPos+=lgthOfCurCell;
1305           posOfCurCell+=lgthOfCurCell;
1306           index[i+1]=newPos;
1307         }
1308     }
1309   if(newPos!=initMeshLgth)
1310     _nodal_connec->reAlloc(newPos);
1311   if(ret)
1312     computeTypes();
1313   return ret;
1314 }
1315
1316 /*!
1317  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1318  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1319  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1320  *
1321  * \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 
1322  *             precision.
1323  */
1324 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1325 {
1326   checkFullyDefined();
1327   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1328     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1329   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1330   coords->recenterForMaxPrecision(eps);
1331   //
1332   int nbOfCells=getNumberOfCells();
1333   const int *conn=_nodal_connec->getConstPointer();
1334   const int *index=_nodal_connec_index->getConstPointer();
1335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1336   connINew->alloc(nbOfCells+1,1);
1337   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1339   bool changed=false;
1340   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1341     {
1342       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1343         {
1344           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1345           changed=true;
1346         }
1347       else
1348         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1349       *connINewPtr=connNew->getNumberOfTuples();
1350     }
1351   if(changed)
1352     setConnectivity(connNew,connINew,false);
1353 }
1354
1355 /*!
1356  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1357  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1358  * the format of returned DataArrayInt instance.
1359  * 
1360  * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1361  * \sa MEDCouplingUMesh::getNodeIdsInUse
1362  */
1363 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1364 {
1365   checkConnectivityFullyDefined();
1366   int nbOfCells=getNumberOfCells();
1367   const int *connIndex=_nodal_connec_index->getConstPointer();
1368   const int *conn=_nodal_connec->getConstPointer();
1369   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1370   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1371   std::vector<bool> retS(maxElt,false);
1372   for(int i=0;i<nbOfCells;i++)
1373     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1374       if(conn[j]>=0)
1375         retS[conn[j]]=true;
1376   int sz=0;
1377   for(int i=0;i<maxElt;i++)
1378     if(retS[i])
1379       sz++;
1380   DataArrayInt *ret=DataArrayInt::New();
1381   ret->alloc(sz,1);
1382   int *retPtr=ret->getPointer();
1383   for(int i=0;i<maxElt;i++)
1384     if(retS[i])
1385       *retPtr++=i;
1386   return ret;
1387 }
1388
1389 /*!
1390  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1391  * \sa MEDCouplingUMesh::getNodeIdsInUse
1392  */
1393 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1394 {
1395   int nbOfNodes=(int)nodeIdsInUse.size();
1396   int nbOfCells=getNumberOfCells();
1397   const int *connIndex=_nodal_connec_index->getConstPointer();
1398   const int *conn=_nodal_connec->getConstPointer();
1399   for(int i=0;i<nbOfCells;i++)
1400     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1401       if(conn[j]>=0)
1402         {
1403           if(conn[j]<nbOfNodes)
1404             nodeIdsInUse[conn[j]]=true;
1405           else
1406             {
1407               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1408               throw INTERP_KERNEL::Exception(oss.str().c_str());
1409             }
1410         }
1411 }
1412
1413 /*!
1414  * Finds nodes not used in any cell and returns an array giving a new id to every node
1415  * by excluding the unused nodes, for which the array holds -1. The result array is
1416  * a mapping in "Old to New" mode. 
1417  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1418  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1419  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1420  *          if the node is unused or a new id else. The caller is to delete this
1421  *          array using decrRef() as it is no more needed.  
1422  *  \throw If the coordinates array is not set.
1423  *  \throw If the nodal connectivity of cells is not defined.
1424  *  \throw If the nodal connectivity includes an invalid id.
1425  *
1426  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1427  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1428  * \sa computeNodeIdsAlg()
1429  */
1430 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1431 {
1432   nbrOfNodesInUse=-1;
1433   int nbOfNodes=getNumberOfNodes();
1434   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1435   ret->alloc(nbOfNodes,1);
1436   int *traducer=ret->getPointer();
1437   std::fill(traducer,traducer+nbOfNodes,-1);
1438   int nbOfCells=getNumberOfCells();
1439   const int *connIndex=_nodal_connec_index->getConstPointer();
1440   const int *conn=_nodal_connec->getConstPointer();
1441   for(int i=0;i<nbOfCells;i++)
1442     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1443       if(conn[j]>=0)
1444         {
1445           if(conn[j]<nbOfNodes)
1446             traducer[conn[j]]=1;
1447           else
1448             {
1449               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1450               throw INTERP_KERNEL::Exception(oss.str().c_str());
1451             }
1452         }
1453   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1454   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1455   return ret.retn();
1456 }
1457
1458 /*!
1459  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1460  * For each cell in \b this the number of nodes constituting cell is computed.
1461  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1462  * So for pohyhedrons some nodes can be counted several times in the returned result.
1463  * 
1464  * \return a newly allocated array
1465  */
1466 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1467 {
1468   checkConnectivityFullyDefined();
1469   int nbOfCells=getNumberOfCells();
1470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1471   ret->alloc(nbOfCells,1);
1472   int *retPtr=ret->getPointer();
1473   const int *conn=getNodalConnectivity()->getConstPointer();
1474   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1475   for(int i=0;i<nbOfCells;i++,retPtr++)
1476     {
1477       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1478         *retPtr=connI[i+1]-connI[i]-1;
1479       else
1480         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1481     }
1482   return ret.retn();
1483 }
1484
1485 /*!
1486  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1487  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1488  * 
1489  * \return a newly allocated array
1490  */
1491 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1492 {
1493   checkConnectivityFullyDefined();
1494   int nbOfCells=getNumberOfCells();
1495   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1496   ret->alloc(nbOfCells,1);
1497   int *retPtr=ret->getPointer();
1498   const int *conn=getNodalConnectivity()->getConstPointer();
1499   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1500   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1501     {
1502       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1503       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1504     }
1505   return ret.retn();
1506 }
1507
1508 /*!
1509  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1510  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1511  * array mean that the corresponding old node is no more used. 
1512  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1513  *           this->getNumberOfNodes() before call of this method. The caller is to
1514  *           delete this array using decrRef() as it is no more needed. 
1515  *  \throw If the coordinates array is not set.
1516  *  \throw If the nodal connectivity of cells is not defined.
1517  *  \throw If the nodal connectivity includes an invalid id.
1518  *
1519  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1520  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1521  */
1522 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1523 {
1524   int newNbOfNodes=-1;
1525   DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1526   renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1527   return traducer;
1528 }
1529
1530 /*!
1531  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1532  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1533  */
1534 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1535 {
1536   switch(compType)
1537     {
1538     case 0:
1539       return AreCellsEqual0(conn,connI,cell1,cell2);
1540     case 1:
1541       return AreCellsEqual1(conn,connI,cell1,cell2);
1542     case 2:
1543       return AreCellsEqual2(conn,connI,cell1,cell2);
1544     case 3:
1545       return AreCellsEqual3(conn,connI,cell1,cell2);
1546     case 7:
1547       return AreCellsEqual7(conn,connI,cell1,cell2);
1548     }
1549   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1550 }
1551
1552 /*!
1553  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1554  */
1555 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1556 {
1557   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1558     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1559   return 0;
1560 }
1561
1562 /*!
1563  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1564  */
1565 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1566 {
1567   int sz=connI[cell1+1]-connI[cell1];
1568   if(sz==connI[cell2+1]-connI[cell2])
1569     {
1570       if(conn[connI[cell1]]==conn[connI[cell2]])
1571         {
1572           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1573           unsigned dim=cm.getDimension();
1574           if(dim!=3)
1575             {
1576               if(dim!=1)
1577                 {
1578                   int sz1=2*(sz-1);
1579                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1580                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1581                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1582                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1583                   return work!=tmp+sz1?1:0;
1584                 }
1585               else
1586                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1587             }
1588           else
1589             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1590         }
1591     }
1592   return 0;
1593 }
1594
1595 /*!
1596  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1597  */
1598 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1599 {
1600   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1601     {
1602       if(conn[connI[cell1]]==conn[connI[cell2]])
1603         {
1604           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1605           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1606           return s1==s2?1:0;
1607         }
1608     }
1609   return 0;
1610 }
1611
1612 /*!
1613  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1614  */
1615 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1616 {
1617   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1618     {
1619       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1620       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1621       return s1==s2?1:0;
1622     }
1623   return 0;
1624 }
1625
1626 /*!
1627  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1628  */
1629 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1630 {
1631   int sz=connI[cell1+1]-connI[cell1];
1632   if(sz==connI[cell2+1]-connI[cell2])
1633     {
1634       if(conn[connI[cell1]]==conn[connI[cell2]])
1635         {
1636           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1637           unsigned dim=cm.getDimension();
1638           if(dim!=3)
1639             {
1640               if(dim!=1)
1641                 {
1642                   int sz1=2*(sz-1);
1643                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1644                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1645                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1646                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1647                   if(work!=tmp+sz1)
1648                     return 1;
1649                   else
1650                     {
1651                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1652                       std::reverse_iterator<int *> it2((int *)tmp);
1653                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1654                         return 2;
1655                       else
1656                         return 0;
1657                     }
1658                   
1659                   return work!=tmp+sz1?1:0;
1660                 }
1661               else
1662                 {//case of SEG2 and SEG3
1663                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1664                     return 1;
1665                   if(!cm.isQuadratic())
1666                     {
1667                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1668                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1669                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1670                         return 2;
1671                       return 0;
1672                     }
1673                   else
1674                     {
1675                       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])
1676                         return 2;
1677                       return 0;
1678                     }
1679                 }
1680             }
1681           else
1682             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1683         }
1684     }
1685   return 0;
1686 }
1687
1688
1689 /*!
1690  * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1691  * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1692  */
1693 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1694 {
1695   if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1696     return false;
1697   std::vector<int> c1,c2;
1698   getNodeIdsOfCell(cellId,c1);
1699   other->getNodeIdsOfCell(cellId,c2);
1700   std::size_t sz=c1.size();
1701   if(sz!=c2.size())
1702     return false;
1703   for(std::size_t i=0;i<sz;i++)
1704     {
1705       std::vector<double> n1,n2;
1706       getCoordinatesOfNode(c1[0],n1);
1707       other->getCoordinatesOfNode(c2[0],n2);
1708       std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1709       std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1710       if(*std::max_element(n1.begin(),n1.end())>prec)
1711         return false;
1712     }
1713   return true;
1714 }
1715
1716 /*!
1717  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1718  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1719  * and result remains unchanged.
1720  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1721  * If in 'candidates' pool -1 value is considered as an empty value.
1722  * WARNING this method returns only ONE set of result !
1723  */
1724 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1725 {
1726   if(candidates.size()<1)
1727     return false;
1728   bool ret=false;
1729   std::vector<int>::const_iterator iter=candidates.begin();
1730   int start=(*iter++);
1731   for(;iter!=candidates.end();iter++)
1732     {
1733       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1734       if(status!=0)
1735         {
1736           if(!ret)
1737             {
1738               result->pushBackSilent(start);
1739               ret=true;
1740             }
1741           if(status==1)
1742             result->pushBackSilent(*iter);
1743           else
1744             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1745         }
1746     }
1747   return ret;
1748 }
1749
1750 /*!
1751  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1752  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1753  *
1754  * \param [in] compType input specifying the technique used to compare cells each other.
1755  *   - 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.
1756  *   - 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)
1757  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1758  *   - 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
1759  * can be used for users not sensitive to orientation of cell
1760  * \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.
1761  * \param [out] commonCells
1762  * \param [out] commonCellsI
1763  * \return the correspondance array old to new in a newly allocated array.
1764  * 
1765  */
1766 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1767 {
1768   checkConnectivityFullyDefined();
1769   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1770   getReverseNodalConnectivity(revNodal,revNodalI);
1771   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1772 }
1773
1774 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1775                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1776 {
1777   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1778   int nbOfCells=nodalI->getNumberOfTuples()-1;
1779   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1780   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1781   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1782   std::vector<bool> isFetched(nbOfCells,false);
1783   if(startCellId==0)
1784     {
1785       for(int i=0;i<nbOfCells;i++)
1786         {
1787           if(!isFetched[i])
1788             {
1789               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1790               std::vector<int> v,v2;
1791               if(connOfNode!=connPtr+connIPtr[i+1])
1792                 {
1793                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1794                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1795                   connOfNode++;
1796                 }
1797               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1798                 if(*connOfNode>=0)
1799                   {
1800                     v=v2;
1801                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1802                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1803                     v2.resize(std::distance(v2.begin(),it));
1804                   }
1805               if(v2.size()>1)
1806                 {
1807                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1808                     {
1809                       int pos=commonCellsI->back();
1810                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1811                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1812                         isFetched[*it]=true;
1813                     }
1814                 }
1815             }
1816         }
1817     }
1818   else
1819     {
1820       for(int i=startCellId;i<nbOfCells;i++)
1821         {
1822           if(!isFetched[i])
1823             {
1824               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1825               std::vector<int> v,v2;
1826               if(connOfNode!=connPtr+connIPtr[i+1])
1827                 {
1828                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1829                   connOfNode++;
1830                 }
1831               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1832                 if(*connOfNode>=0)
1833                   {
1834                     v=v2;
1835                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1836                     v2.resize(std::distance(v2.begin(),it));
1837                   }
1838               if(v2.size()>1)
1839                 {
1840                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1841                     {
1842                       int pos=commonCellsI->back();
1843                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1844                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1845                         isFetched[*it]=true;
1846                     }
1847                 }
1848             }
1849         }
1850     }
1851   commonCellsArr=commonCells.retn();
1852   commonCellsIArr=commonCellsI.retn();
1853 }
1854
1855 /*!
1856  * Removes duplicates of cells from \a this mesh and returns an array mapping between
1857  * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1858  * equal cells found.
1859  *  \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1860  *           to write this mesh to the MED file, its cells must be sorted using
1861  *           sortCellsInMEDFileFrmt().
1862  *  \param [in] compType - specifies a cell comparison technique. Meaning of its
1863  *          valid values [0,1,2] is as follows.
1864  *   - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1865  *         connectivity and type. This is the strongest policy.
1866  *   - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1867  *         are based on same nodes and have the same type and orientation.
1868  *   - 2 : "nodal". Two cells are considered equal \c iff they
1869  *         are based on same nodes and have the same type. This is the weakest
1870  *         policy, it can be used by users not sensitive to cell orientation.
1871  *  \param [in] startCellId - specifies the cell id at which search for equal cells
1872  *         starts. By default it is 0, which means that all cells in \a this will be
1873  *         scanned. 
1874  *  \return DataArrayInt - a new instance of DataArrayInt, of length \a
1875  *           this->getNumberOfCells() before call of this method. The caller is to
1876  *           delete this array using decrRef() as it is no more needed. 
1877  *  \throw If the coordinates array is not set.
1878  *  \throw If the nodal connectivity of cells is not defined.
1879  *  \throw If the nodal connectivity includes an invalid id.
1880  *
1881  *  \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1882  *  \ref  py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1883  */
1884 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1885 {
1886   DataArrayInt *commonCells=0,*commonCellsI=0;
1887   findCommonCells(compType,startCellId,commonCells,commonCellsI);
1888   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1889   int newNbOfCells=-1;
1890   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1891                                                                                                           commonCellsI->end(),newNbOfCells);
1892   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1893   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1894   setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1895   return ret.retn();
1896 }
1897
1898 /*!
1899  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1900  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1901  * than \a other->getNumberOfCells() in the returned array means that there is no
1902  * corresponding cell in \a this mesh.
1903  * It is expected that \a this and \a other meshes share the same node coordinates
1904  * array, if it is not so an exception is thrown. 
1905  *  \param [in] other - the mesh to compare with.
1906  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1907  *         valid values [0,1,2], see zipConnectivityTraducer().
1908  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1909  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1910  *         values. The caller is to delete this array using
1911  *         decrRef() as it is no more needed.
1912  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1913  *         mesh.
1914  *
1915  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1916  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1917  *  \sa checkDeepEquivalOnSameNodesWith()
1918  *  \sa checkGeoEquivalWith()
1919  */
1920 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1921 {
1922   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1923   int nbOfCells=getNumberOfCells();
1924   static const int possibleCompType[]={0,1,2};
1925   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1926     {
1927       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1928       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1929       oss << " !";
1930       throw INTERP_KERNEL::Exception(oss.str().c_str());
1931     }
1932   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1933   arr=o2n->substr(nbOfCells);
1934   arr->setName(other->getName());
1935   int tmp;
1936   if(other->getNumberOfCells()==0)
1937     return true;
1938   return arr->getMaxValue(tmp)<nbOfCells;
1939 }
1940
1941 /*!
1942  * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1943  * This method tries to determine if \b other is fully included in \b this.
1944  * The main difference is that this method is not expected to throw exception.
1945  * This method has two outputs :
1946  *
1947  * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1948  * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1949  */
1950 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1951 {
1952   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1953   DataArrayInt *commonCells=0,*commonCellsI=0;
1954   int thisNbCells=getNumberOfCells();
1955   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1957   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1958   int otherNbCells=other->getNumberOfCells();
1959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1960   arr2->alloc(otherNbCells,1);
1961   arr2->fillWithZero();
1962   int *arr2Ptr=arr2->getPointer();
1963   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1964   for(int i=0;i<nbOfCommon;i++)
1965     {
1966       int start=commonCellsPtr[commonCellsIPtr[i]];
1967       if(start<thisNbCells)
1968         {
1969           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1970             {
1971               int sig=commonCellsPtr[j]>0?1:-1;
1972               int val=std::abs(commonCellsPtr[j])-1;
1973               if(val>=thisNbCells)
1974                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1975             }
1976         }
1977     }
1978   arr2->setName(other->getName());
1979   if(arr2->presenceOfValue(0))
1980     return false;
1981   arr=arr2.retn();
1982   return true;
1983 }
1984
1985 /*!
1986  * Merges nodes equal within \a precision and returns an array describing the 
1987  * permutation used to remove duplicate nodes.
1988  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1989  *              considered not coincident.
1990  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1991  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1992  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1993  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1994  *          is to delete this array using decrRef() as it is no more needed.
1995  *  \throw If the coordinates array is not set.
1996  *  \throw If the nodal connectivity of cells is not defined.
1997  *
1998  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1999  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
2000  */
2001 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
2002 {
2003   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2004   if(areNodesMerged)
2005     renumberNodes(ret->getConstPointer(),newNbOfNodes);
2006   return ret;
2007 }
2008
2009
2010 /*!
2011  * Merges nodes equal within \a precision and returns an array describing the 
2012  * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
2013  *  of merged nodes is changed to be at their barycenter.
2014  *  \param [in] precision - minimal absolute distance between two nodes at which they are
2015  *              considered not coincident.
2016  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
2017  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
2018  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
2019  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
2020  *          is to delete this array using decrRef() as it is no more needed.
2021  *  \throw If the coordinates array is not set.
2022  *  \throw If the nodal connectivity of cells is not defined.
2023  *
2024  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
2025  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
2026  */
2027 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
2028 {
2029   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2030   if(areNodesMerged)
2031     renumberNodes2(ret->getConstPointer(),newNbOfNodes);
2032   return ret;
2033 }
2034
2035 /*!
2036  * Substitutes node coordinates array of \a this mesh with that of \a other mesh
2037  * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
2038  * meshes match with a specified precision, else an exception is thrown and \a this
2039  * remains unchanged. In case of success the nodal connectivity of \a this mesh
2040  * is permuted according to new order of nodes.
2041  * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
2042  * coordinates (and so more expensive) than simple equality.
2043  *  \param [in] other - the other mesh whose node coordinates array will be used by
2044  *         \a this mesh in case of their equality.
2045  *  \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
2046  *  \throw If the coordinates array of \a this is not set.
2047  *  \throw If the coordinates array of \a other is not set.
2048  *  \throw If the coordinates of \a this and \a other do not match.
2049  */
2050 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
2051 {
2052   const DataArrayDouble *coords=other.getCoords();
2053   if(!coords)
2054     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
2055   if(!_coords)
2056     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
2057   int otherNbOfNodes=other.getNumberOfNodes();
2058   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
2059   _coords->incrRef();
2060   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
2061   setCoords(newCoords);
2062   bool areNodesMerged;
2063   int newNbOfNodes;
2064   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
2065   if(!areNodesMerged)
2066     {
2067       setCoords(oldCoords);
2068       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
2069     }
2070   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
2071   const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
2072   if(pt!=da->getConstPointer()+da->getNbOfElems())
2073     {
2074       setCoords(oldCoords);
2075       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
2076     }
2077   setCoords(oldCoords);
2078   renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
2079   setCoords(coords);
2080 }
2081
2082 /*!
2083  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2084  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2085  * cellIds is not given explicitely but by a range python like.
2086  * 
2087  * \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.
2088  * \return a newly allocated
2089  * 
2090  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2091  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2092  */
2093 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
2094 {
2095   if(getMeshDimension()!=-1)
2096     {
2097       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
2098       if(!keepCoords)
2099         ret->zipCoords();
2100       return ret;
2101     }
2102   else
2103     {
2104       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2105       if(newNbOfCells!=1)
2106         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2107       if(start!=0)
2108         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2109       incrRef();
2110       return const_cast<MEDCouplingUMesh *>(this);
2111     }
2112 }
2113
2114 /*!
2115  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2116  * The result mesh shares or not the node coordinates array with \a this mesh depending
2117  * on \a keepCoords parameter.
2118  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2119  *           to write this mesh to the MED file, its cells must be sorted using
2120  *           sortCellsInMEDFileFrmt().
2121  *  \param [in] begin - an array of cell ids to include to the new mesh.
2122  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2123  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2124  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2125  *         by calling zipCoords().
2126  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2127  *         to delete this mesh using decrRef() as it is no more needed. 
2128  *  \throw If the coordinates array is not set.
2129  *  \throw If the nodal connectivity of cells is not defined.
2130  *  \throw If any cell id in the array \a begin is not valid.
2131  *
2132  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2133  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2134  */
2135 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2136 {
2137   if(getMeshDimension()!=-1)
2138     {
2139       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
2140       if(!keepCoords)
2141         ret->zipCoords();
2142       return ret;
2143     }
2144   else
2145     {
2146       if(end-begin!=1)
2147         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2148       if(begin[0]!=0)
2149         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2150       incrRef();
2151       return const_cast<MEDCouplingUMesh *>(this);
2152     }
2153 }
2154
2155 /*!
2156  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2157  *
2158  * 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.
2159  * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2160  * The number of cells of \b this will remain the same with this method.
2161  *
2162  * \param [in] begin begin of cell ids (included) of cells in this to assign
2163  * \param [in] end end of cell ids (excluded) of cells in this to assign
2164  * \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).
2165  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2166  */
2167 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2168 {
2169   checkConnectivityFullyDefined();
2170   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2171   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2172     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2173   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2174     {
2175       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2176       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2177       throw INTERP_KERNEL::Exception(oss.str().c_str());
2178     }
2179   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2180   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2181     {
2182       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2183       throw INTERP_KERNEL::Exception(oss.str().c_str());
2184     }
2185   int nbOfCells=getNumberOfCells();
2186   bool easyAssign=true;
2187   const int *connI=_nodal_connec_index->getConstPointer();
2188   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2189   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2190     {
2191       if(*it>=0 && *it<nbOfCells)
2192         {
2193           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2194         }
2195       else
2196         {
2197           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2198           throw INTERP_KERNEL::Exception(oss.str().c_str());
2199         }
2200     }
2201   if(easyAssign)
2202     {
2203       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2204       computeTypes();
2205     }
2206   else
2207     {
2208       DataArrayInt *arrOut=0,*arrIOut=0;
2209       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2210                                                arrOut,arrIOut);
2211       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2212       setConnectivity(arrOut,arrIOut,true);
2213     }
2214 }
2215
2216 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2217 {
2218   checkConnectivityFullyDefined();
2219   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2220   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2221     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2222   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2223     {
2224       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2225       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2226       throw INTERP_KERNEL::Exception(oss.str().c_str());
2227     }
2228   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2229   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2230     {
2231       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2232       throw INTERP_KERNEL::Exception(oss.str().c_str());
2233     }
2234   int nbOfCells=getNumberOfCells();
2235   bool easyAssign=true;
2236   const int *connI=_nodal_connec_index->getConstPointer();
2237   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2238   int it=start;
2239   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2240     {
2241       if(it>=0 && it<nbOfCells)
2242         {
2243           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2244         }
2245       else
2246         {
2247           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2248           throw INTERP_KERNEL::Exception(oss.str().c_str());
2249         }
2250     }
2251   if(easyAssign)
2252     {
2253       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2254       computeTypes();
2255     }
2256   else
2257     {
2258       DataArrayInt *arrOut=0,*arrIOut=0;
2259       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2260                                                 arrOut,arrIOut);
2261       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2262       setConnectivity(arrOut,arrIOut,true);
2263     }
2264 }                      
2265
2266 /*!
2267  * Finds cells whose all nodes are in a given array of node ids.
2268  *  \param [in] partBg - the array of node ids.
2269  *  \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2270  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2271  *          cells. The caller is to delete this array using decrRef() as it is no
2272  *          more needed.
2273  *  \throw If the coordinates array is not set.
2274  *  \throw If the nodal connectivity of cells is not defined.
2275  *  \throw If any cell id in \a partBg is not valid.
2276  *
2277  *  \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2278  *  \ref  py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2279  */
2280 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2281 {
2282   DataArrayInt *cellIdsKept=0;
2283   fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2284   cellIdsKept->setName(getName());
2285   return cellIdsKept;
2286 }
2287
2288 /*!
2289  * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2290  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2291  * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2292  * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2293  *
2294  * \param [in] begin input start of array of node ids.
2295  * \param [in] end input end of array of node ids.
2296  * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
2297  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2298  */
2299 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2300 {
2301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2302   checkConnectivityFullyDefined();
2303   int tmp=-1;
2304   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2305   std::vector<bool> fastFinder(sz,false);
2306   for(const int *work=begin;work!=end;work++)
2307     if(*work>=0 && *work<sz)
2308       fastFinder[*work]=true;
2309   int nbOfCells=getNumberOfCells();
2310   const int *conn=getNodalConnectivity()->getConstPointer();
2311   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2312   for(int i=0;i<nbOfCells;i++)
2313     {
2314       int ref=0,nbOfHit=0;
2315       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2316         if(*work2>=0)
2317           {
2318             ref++;
2319             if(fastFinder[*work2])
2320               nbOfHit++;
2321           }
2322       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2323         cellIdsKept->pushBackSilent(i);
2324     }
2325   cellIdsKeptArr=cellIdsKept.retn();
2326 }
2327
2328 /*!
2329  * Finds cells whose all or some nodes are in a given array of node ids.
2330  *  \param [in] begin - the array of node ids.
2331  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2332  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2333  *         array \a begin are returned only, else cells whose any node is in the
2334  *         array \a begin are returned.
2335  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2336  *         cells. The caller is to delete this array using decrRef() as it is no more
2337  *         needed. 
2338  *  \throw If the coordinates array is not set.
2339  *  \throw If the nodal connectivity of cells is not defined.
2340  *  \throw If any cell id in \a begin is not valid.
2341  *
2342  *  \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2343  *  \ref  py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2344  */
2345 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2346 {
2347   DataArrayInt *cellIdsKept=0;
2348   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2349   cellIdsKept->setName(getName());
2350   return cellIdsKept;
2351 }
2352
2353 /*!
2354  Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
2355  copy are selected basing on specified node ids and the value of \a fullyIn
2356  parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the 
2357  array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
2358  node is in the array of node ids. The created mesh shares the node coordinates array
2359  with \a this mesh.
2360  *  \param [in] begin - the array of node ids.
2361  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2362  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2363  *         array \a begin are copied, else cells whose any node is in the
2364  *         array \a begin are copied.
2365  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2366  *         to delete this mesh using decrRef() as it is no more needed. 
2367  *  \throw If the coordinates array is not set.
2368  *  \throw If the nodal connectivity of cells is not defined.
2369  *  \throw If any node id in \a begin is not valid.
2370  *
2371  *  \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
2372  *  \ref  py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
2373  */
2374 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2375 {
2376   DataArrayInt *cellIdsKept=0;
2377   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2379   return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2380 }
2381
2382 /*!
2383  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2384  * this->getMeshDimension(), that bound some cells of \a this mesh.
2385  * The cells of lower dimension to include to the result mesh are selected basing on
2386  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2387  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2388  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2389  * created mesh shares the node coordinates array with \a this mesh. 
2390  *  \param [in] begin - the array of node ids.
2391  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2392  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2393  *         array \a begin are added, else cells whose any node is in the
2394  *         array \a begin are added.
2395  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2396  *         to delete this mesh using decrRef() as it is no more needed. 
2397  *  \throw If the coordinates array is not set.
2398  *  \throw If the nodal connectivity of cells is not defined.
2399  *  \throw If any node id in \a begin is not valid.
2400  *
2401  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2402  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2403  */
2404 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2405 {
2406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2407   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2408   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2409   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2410   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2411 }
2412
2413 /*!
2414  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2415  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2416  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2417  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2418  *         by calling zipCoords().
2419  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2420  *         to delete this mesh using decrRef() as it is no more needed. 
2421  *  \throw If the coordinates array is not set.
2422  *  \throw If the nodal connectivity of cells is not defined.
2423  *
2424  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2425  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2426  */
2427 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2428 {
2429   DataArrayInt *desc=DataArrayInt::New();
2430   DataArrayInt *descIndx=DataArrayInt::New();
2431   DataArrayInt *revDesc=DataArrayInt::New();
2432   DataArrayInt *revDescIndx=DataArrayInt::New();
2433   //
2434   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2435   revDesc->decrRef();
2436   desc->decrRef();
2437   descIndx->decrRef();
2438   int nbOfCells=meshDM1->getNumberOfCells();
2439   const int *revDescIndxC=revDescIndx->getConstPointer();
2440   std::vector<int> boundaryCells;
2441   for(int i=0;i<nbOfCells;i++)
2442     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2443       boundaryCells.push_back(i);
2444   revDescIndx->decrRef();
2445   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2446   return ret;
2447 }
2448
2449 /*!
2450  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2451  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2452  * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown. 
2453  */
2454 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2455 {
2456   checkFullyDefined();
2457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2461   //
2462   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2463   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2464   //
2465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2467   const int *revDescPtr=revDesc->getConstPointer();
2468   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2469   int nbOfCells=getNumberOfCells();
2470   std::vector<bool> ret1(nbOfCells,false);
2471   int sz=0;
2472   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2473     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2474       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2475   //
2476   DataArrayInt *ret2=DataArrayInt::New();
2477   ret2->alloc(sz,1);
2478   int *ret2Ptr=ret2->getPointer();
2479   sz=0;
2480   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2481     if(*it)
2482       *ret2Ptr++=sz;
2483   ret2->setName("BoundaryCells");
2484   return ret2;
2485 }
2486
2487 /*!
2488  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2489  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2490  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2491  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2492  *
2493  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2494  * This method method returns cells ids set s = s1 + s2 where :
2495  * 
2496  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2497  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2498  *
2499  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2500  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2501  *
2502  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2503  * \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
2504  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2505  */
2506 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2507 {
2508   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2509     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2510   checkConnectivityFullyDefined();
2511   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2512   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2513     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2516   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2518   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2519   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2520   DataArrayInt *idsOtherInConsti=0;
2521   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2522   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2523   if(!b)
2524     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2525   std::set<int> s1;
2526   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2527     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2528   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2529   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2530   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2531   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2533   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2534   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2535   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2536   neighThisPartAuto=0;
2537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2538   const int li[2]={0,1};
2539   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2540   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2541   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2542   s_renum1->sort();
2543   //
2544   cellIdsRk0=s0arr.retn();
2545   cellIdsRk1=s_renum1.retn();
2546 }
2547
2548 /*!
2549  * 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
2550  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2551  * 
2552  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2553  */
2554 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2555 {
2556   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2560   //
2561   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2562   revDesc=0; desc=0; descIndx=0;
2563   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2565   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2566 }
2567
2568 /*!
2569  * Finds nodes lying on the boundary of \a this mesh.
2570  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2571  *          nodes. The caller is to delete this array using decrRef() as it is no
2572  *          more needed.
2573  *  \throw If the coordinates array is not set.
2574  *  \throw If the nodal connectivity of cells is node defined.
2575  *
2576  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2577  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2578  */
2579 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2580 {
2581   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2582   return skin->computeFetchedNodeIds();
2583 }
2584
2585 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2586 {
2587   incrRef();
2588   return const_cast<MEDCouplingUMesh *>(this);
2589 }
2590
2591 /*!
2592  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2593  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
2594  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2595  * array is modified accordingly.
2596  *  \param [in] newNodeNumbers - a permutation array, of length \a
2597  *         this->getNumberOfNodes(), in "Old to New" mode. 
2598  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2599  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering.
2600  *  \throw If the coordinates array is not set.
2601  *  \throw If the nodal connectivity of cells is not defined.
2602  *
2603  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2604  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
2605  */
2606 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2607 {
2608   MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2609   renumberNodesInConn(newNodeNumbers);
2610 }
2611
2612 /*!
2613  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2614  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
2615  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2616  * array is modified accordingly. In contrast to renumberNodes(), location
2617  * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
2618  *  \param [in] newNodeNumbers - a permutation array, of length \a
2619  *         this->getNumberOfNodes(), in "Old to New" mode. 
2620  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2621  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
2622  *         actually one more than the maximal id in \a newNodeNumbers.
2623  *  \throw If the coordinates array is not set.
2624  *  \throw If the nodal connectivity of cells is not defined.
2625  *
2626  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2627  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
2628  */
2629 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2630 {
2631   MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2632   renumberNodesInConn(newNodeNumbers);
2633 }
2634
2635 /*!
2636  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2637  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2638  * 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.
2639  * 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.
2640  * 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.
2641  *
2642  * \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
2643  *             parameter is altered during the call.
2644  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2645  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2646  * \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.
2647  *
2648  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2649  */
2650 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2651                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2652 {
2653   checkFullyDefined();
2654   otherDimM1OnSameCoords.checkFullyDefined();
2655   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2657   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2658     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2659   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2660   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2662   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2663   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2664   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2665   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2668   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2669   //
2670   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2671   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2672   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2673   DataArrayInt *idsTmp=0;
2674   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2675   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2676   if(!b)
2677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2678   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2679   DataArrayInt *tmp0=0,*tmp1=0;
2680   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2681   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2682   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2683   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2685   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2686   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2687   //
2688   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2689   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2690   nodeIdsToDuplicate=s3.retn();
2691 }
2692
2693 /*!
2694  * This method operates a modification of the connectivity and coords in \b this.
2695  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2696  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2697  * 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
2698  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2699  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2700  * 
2701  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2702  * 
2703  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2704  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2705  */
2706 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2707 {
2708   int nbOfNodes=getNumberOfNodes();
2709   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2710   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2711 }
2712
2713 /*!
2714  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2715  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2716  * This method is a generalization of shiftNodeNumbersInConn().
2717  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2718  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2719  *         this->getNumberOfNodes(), in "Old to New" mode. 
2720  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2721  *  \throw If the nodal connectivity of cells is not defined.
2722  *
2723  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2724  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2725  */
2726 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2727 {
2728   checkConnectivityFullyDefined();
2729   int *conn=getNodalConnectivity()->getPointer();
2730   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2731   int nbOfCells=getNumberOfCells();
2732   for(int i=0;i<nbOfCells;i++)
2733     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2734       {
2735         int& node=conn[iconn];
2736         if(node>=0)//avoid polyhedron separator
2737           {
2738             node=newNodeNumbersO2N[node];
2739           }
2740       }
2741   _nodal_connec->declareAsNew();
2742   updateTime();
2743 }
2744
2745 /*!
2746  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2747  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2748  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2749  * 
2750  * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2751  */
2752 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2753 {
2754   checkConnectivityFullyDefined();
2755   int *conn=getNodalConnectivity()->getPointer();
2756   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2757   int nbOfCells=getNumberOfCells();
2758   for(int i=0;i<nbOfCells;i++)
2759     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2760       {
2761         int& node=conn[iconn];
2762         if(node>=0)//avoid polyhedron separator
2763           {
2764             node+=delta;
2765           }
2766       }
2767   _nodal_connec->declareAsNew();
2768   updateTime();
2769 }
2770
2771 /*!
2772  * This method operates a modification of the connectivity in \b this.
2773  * 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.
2774  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2775  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2776  * 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
2777  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2778  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2779  * 
2780  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2781  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2782  * 
2783  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2784  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2785  * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd). 
2786  */
2787 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2788 {
2789   checkConnectivityFullyDefined();
2790   std::map<int,int> m;
2791   int val=offset;
2792   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2793     m[*work]=val;
2794   int *conn=getNodalConnectivity()->getPointer();
2795   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2796   int nbOfCells=getNumberOfCells();
2797   for(int i=0;i<nbOfCells;i++)
2798     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2799       {
2800         int& node=conn[iconn];
2801         if(node>=0)//avoid polyhedron separator
2802           {
2803             std::map<int,int>::iterator it=m.find(node);
2804             if(it!=m.end())
2805               node=(*it).second;
2806           }
2807       }
2808   updateTime();
2809 }
2810
2811 /*!
2812  * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2813  *
2814  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2815  * After the call of this method the number of cells remains the same as before.
2816  *
2817  * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2818  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2819  * be strictly in [0;this->getNumberOfCells()).
2820  *
2821  * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2822  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2823  * should be contained in[0;this->getNumberOfCells()).
2824  * 
2825  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2826  */
2827 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2828 {
2829   checkConnectivityFullyDefined();
2830   int nbCells=getNumberOfCells();
2831   const int *array=old2NewBg;
2832   if(check)
2833     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2834   //
2835   const int *conn=_nodal_connec->getConstPointer();
2836   const int *connI=_nodal_connec_index->getConstPointer();
2837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2839   const int *n2oPtr=n2o->begin();
2840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2841   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2842   newConn->copyStringInfoFrom(*_nodal_connec);
2843   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2844   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2845   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2846   //
2847   int *newC=newConn->getPointer();
2848   int *newCI=newConnI->getPointer();
2849   int loc=0;
2850   newCI[0]=loc;
2851   for(int i=0;i<nbCells;i++)
2852     {
2853       int pos=n2oPtr[i];
2854       int nbOfElts=connI[pos+1]-connI[pos];
2855       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2856       loc+=nbOfElts;
2857       newCI[i+1]=loc;
2858     }
2859   //
2860   setConnectivity(newConn,newConnI);
2861   if(check)
2862     free(const_cast<int *>(array));
2863 }
2864
2865 /*!
2866  * Finds cells whose bounding boxes intersect a given bounding box.
2867  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2868  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2869  *         zMax (if in 3D). 
2870  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2871  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2872  *         extent of the bounding box of cell to produce an addition to this bounding box.
2873  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2874  *         cells. The caller is to delete this array using decrRef() as it is no more
2875  *         needed. 
2876  *  \throw If the coordinates array is not set.
2877  *  \throw If the nodal connectivity of cells is not defined.
2878  *
2879  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2880  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2881  */
2882 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2883 {
2884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2885   if(getMeshDimension()==-1)
2886     {
2887       elems->pushBackSilent(0);
2888       return elems.retn();
2889     }
2890   int dim=getSpaceDimension();
2891   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2892   const int* conn      = getNodalConnectivity()->getConstPointer();
2893   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2894   const double* coords = getCoords()->getConstPointer();
2895   int nbOfCells=getNumberOfCells();
2896   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2897     {
2898       for (int i=0; i<dim; i++)
2899         {
2900           elem_bb[i*2]=std::numeric_limits<double>::max();
2901           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2902         }
2903
2904       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2905         {
2906           int node= conn[inode];
2907           if(node>=0)//avoid polyhedron separator
2908             {
2909               for (int idim=0; idim<dim; idim++)
2910                 {
2911                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2912                     {
2913                       elem_bb[idim*2] = coords[node*dim+idim] ;
2914                     }
2915                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2916                     {
2917                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2918                     }
2919                 }
2920             }
2921         }
2922       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2923         elems->pushBackSilent(ielem);
2924     }
2925   return elems.retn();
2926 }
2927
2928 /*!
2929  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2930  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2931  * added in 'elems' parameter.
2932  */
2933 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2934 {
2935   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2936   if(getMeshDimension()==-1)
2937     {
2938       elems->pushBackSilent(0);
2939       return elems.retn();
2940     }
2941   int dim=getSpaceDimension();
2942   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2943   const int* conn      = getNodalConnectivity()->getConstPointer();
2944   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2945   const double* coords = getCoords()->getConstPointer();
2946   int nbOfCells=getNumberOfCells();
2947   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2948     {
2949       for (int i=0; i<dim; i++)
2950         {
2951           elem_bb[i*2]=std::numeric_limits<double>::max();
2952           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2953         }
2954
2955       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2956         {
2957           int node= conn[inode];
2958           if(node>=0)//avoid polyhedron separator
2959             {
2960               for (int idim=0; idim<dim; idim++)
2961                 {
2962                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2963                     {
2964                       elem_bb[idim*2] = coords[node*dim+idim] ;
2965                     }
2966                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2967                     {
2968                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2969                     }
2970                 }
2971             }
2972         }
2973       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2974         elems->pushBackSilent(ielem);
2975     }
2976   return elems.retn();
2977 }
2978
2979 /*!
2980  * Returns a type of a cell by its id.
2981  *  \param [in] cellId - the id of the cell of interest.
2982  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2983  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2984  */
2985 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2986 {
2987   const int *ptI=_nodal_connec_index->getConstPointer();
2988   const int *pt=_nodal_connec->getConstPointer();
2989   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2990     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2991   else
2992     {
2993       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2994       throw INTERP_KERNEL::Exception(oss.str().c_str());
2995     }
2996 }
2997
2998 /*!
2999  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
3000  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
3001  * The coordinates array is not considered here.
3002  *
3003  * \param [in] type the geometric type
3004  * \return cell ids in this having geometric type \a type.
3005  */
3006 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
3007 {
3008   
3009   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
3010   ret->alloc(0,1);
3011   checkConnectivityFullyDefined();
3012   int nbCells=getNumberOfCells();
3013   int mdim=getMeshDimension();
3014   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
3015   if(mdim!=(int)cm.getDimension())
3016     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
3017   const int *ptI=_nodal_connec_index->getConstPointer();
3018   const int *pt=_nodal_connec->getConstPointer();
3019   for(int i=0;i<nbCells;i++)
3020     {
3021       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
3022         ret->pushBackSilent(i);
3023     }
3024   return ret.retn();
3025 }
3026
3027 /*!
3028  * Returns nb of cells having the geometric type 'type'.
3029  */
3030 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
3031 {
3032   const int *ptI=_nodal_connec_index->getConstPointer();
3033   const int *pt=_nodal_connec->getConstPointer();
3034   int nbOfCells=getNumberOfCells();
3035   int ret=0;
3036   for(int i=0;i<nbOfCells;i++)
3037     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3038       ret++;
3039   return ret;
3040 }
3041
3042 /*!
3043  * Returns the nodal connectivity of a given cell.
3044  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3045  * all returned node ids can be used in getCoordinatesOfNode().
3046  *  \param [in] cellId - an id of the cell of interest.
3047  *  \param [in,out] conn - a vector where the node ids are appended. It is not
3048  *         cleared before the appending.
3049  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3050  */
3051 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3052 {
3053   const int *ptI=_nodal_connec_index->getConstPointer();
3054   const int *pt=_nodal_connec->getConstPointer();
3055   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3056     if(*w>=0)
3057       conn.push_back(*w);
3058 }
3059
3060 std::string MEDCouplingUMesh::simpleRepr() const
3061 {
3062   static const char msg0[]="No coordinates specified !";
3063   std::ostringstream ret;
3064   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3065   ret << "Description of mesh : \"" << getDescription() << "\"\n";
3066   int tmpp1,tmpp2;
3067   double tt=getTime(tmpp1,tmpp2);
3068   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3069   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
3070   if(_mesh_dim>=-1)
3071     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3072   else
3073     { ret << " Mesh dimension has not been set or is invalid !"; }
3074   if(_coords!=0)
3075     {
3076       const int spaceDim=getSpaceDimension();
3077       ret << spaceDim << "\nInfo attached on space dimension : ";
3078       for(int i=0;i<spaceDim;i++)
3079         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3080       ret << "\n";
3081     }
3082   else
3083     ret << msg0 << "\n";
3084   ret << "Number of nodes : ";
3085   if(_coords!=0)
3086     ret << getNumberOfNodes() << "\n";
3087   else
3088     ret << msg0 << "\n";
3089   ret << "Number of cells : ";
3090   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3091     ret << getNumberOfCells() << "\n";
3092   else
3093     ret << "No connectivity specified !" << "\n";
3094   ret << "Cell types present : ";
3095   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3096     {
3097       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3098       ret << cm.getRepr() << " ";
3099     }
3100   ret << "\n";
3101   return ret.str();
3102 }
3103
3104 std::string MEDCouplingUMesh::advancedRepr() const
3105 {
3106   std::ostringstream ret;
3107   ret << simpleRepr();
3108   ret << "\nCoordinates array : \n___________________\n\n";
3109   if(_coords)
3110     _coords->reprWithoutNameStream(ret);
3111   else
3112     ret << "No array set !\n";
3113   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3114   reprConnectivityOfThisLL(ret);
3115   return ret.str();
3116 }
3117
3118 /*!
3119  * This method returns a C++ code that is a dump of \a this.
3120  * This method will throw if this is not fully defined.
3121  */
3122 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
3123 {
3124   static const char coordsName[]="coords";
3125   static const char connName[]="conn";
3126   static const char connIName[]="connI";
3127   checkFullyDefined();
3128   std::ostringstream ret; ret << "// coordinates" << std::endl;
3129   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3130   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3131   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3132   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3133   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3134   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3135   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3136   return ret.str();
3137 }
3138
3139 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3140 {
3141   std::ostringstream ret;
3142   reprConnectivityOfThisLL(ret);
3143   return ret.str();
3144 }
3145
3146 /*!
3147  * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
3148  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3149  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3150  * some algos).
3151  * 
3152  * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3153  * This method analyzes the 3 arrays of 'this'. For each the following behaviour is done : if the array is null a newly one is created
3154  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3155  */
3156 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
3157 {
3158   int mdim=getMeshDimension();
3159   if(mdim<0)
3160     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3161   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3163   bool needToCpyCT=true;
3164   if(!_nodal_connec)
3165     {
3166       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3167       needToCpyCT=false;
3168     }
3169   else
3170     {
3171       tmp1=_nodal_connec;
3172       tmp1->incrRef();
3173     }
3174   if(!_nodal_connec_index)
3175     {
3176       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3177       needToCpyCT=false;
3178     }
3179   else
3180     {
3181       tmp2=_nodal_connec_index;
3182       tmp2->incrRef();
3183     }
3184   ret->setConnectivity(tmp1,tmp2,false);
3185   if(needToCpyCT)
3186     ret->_types=_types;
3187   if(!_coords)
3188     {
3189       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3190       ret->setCoords(coords);
3191     }
3192   else
3193     ret->setCoords(_coords);
3194   return ret.retn();
3195 }
3196
3197 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3198 {
3199   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3200     {
3201       int nbOfCells=getNumberOfCells();
3202       const int *c=_nodal_connec->getConstPointer();
3203       const int *ci=_nodal_connec_index->getConstPointer();
3204       for(int i=0;i<nbOfCells;i++)
3205         {
3206           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3207           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3208           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3209           stream << "\n";
3210         }
3211     }
3212   else
3213     stream << "Connectivity not defined !\n";
3214 }
3215
3216 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3217 {
3218   const int *ptI=_nodal_connec_index->getConstPointer();
3219   const int *pt=_nodal_connec->getConstPointer();
3220   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3221     return ptI[cellId+1]-ptI[cellId]-1;
3222   else
3223     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3224 }
3225
3226 /*!
3227  * Returns types of cells of the specified part of \a this mesh.
3228  * This method avoids computing sub-mesh explicitely to get its types.
3229  *  \param [in] begin - an array of cell ids of interest.
3230  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3231  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3232  *         describing the cell types. 
3233  *  \throw If the coordinates array is not set.
3234  *  \throw If the nodal connectivity of cells is not defined.
3235  *  \sa getAllTypes()
3236  */
3237 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
3238 {
3239   checkFullyDefined();
3240   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3241   const int *conn=_nodal_connec->getConstPointer();
3242   const int *connIndex=_nodal_connec_index->getConstPointer();
3243   for(const int *w=begin;w!=end;w++)
3244     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3245   return ret;
3246 }
3247
3248 /*!
3249  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3250  * a set of types of cells constituting \a this mesh. 
3251  * This method is for advanced users having prepared their connectivity before. For
3252  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3253  *  \param [in] conn - the nodal connectivity array. 
3254  *  \param [in] connIndex - the nodal connectivity index array.
3255  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3256  *         mesh is updated.
3257  */
3258 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3259 {
3260   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3261   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3262   if(isComputingTypes)
3263     computeTypes();
3264   declareAsNew();
3265 }
3266
3267 /*!
3268  * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
3269  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3270  */
3271 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3272                                                                                  _nodal_connec(0),_nodal_connec_index(0),
3273                                                                                 _types(other._types)
3274 {
3275   if(other._nodal_connec)
3276     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3277   if(other._nodal_connec_index)
3278     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3279 }
3280
3281 MEDCouplingUMesh::~MEDCouplingUMesh()
3282 {
3283   if(_nodal_connec)
3284     _nodal_connec->decrRef();
3285   if(_nodal_connec_index)
3286     _nodal_connec_index->decrRef();
3287 }
3288
3289 /*!
3290  * Recomputes a set of cell types of \a this mesh. For more info see
3291  * \ref MEDCouplingUMeshNodalConnectivity.
3292  */
3293 void MEDCouplingUMesh::computeTypes()
3294 {
3295   if(_nodal_connec && _nodal_connec_index)
3296     {
3297       _types.clear();
3298       const int *conn=_nodal_connec->getConstPointer();
3299       const int *connIndex=_nodal_connec_index->getConstPointer();
3300       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3301       if (nbOfElem > 0)
3302         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3303           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3304     }
3305 }
3306
3307 /*!
3308  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3309  */
3310 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3311 {
3312   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3313     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3314 }
3315
3316 /*!
3317  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3318  */
3319 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3320 {
3321   if(!_nodal_connec_index || !_nodal_connec)
3322     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3323 }
3324
3325 /*!
3326  * Returns a number of cells constituting \a this mesh. 
3327  *  \return int - the number of cells in \a this mesh.
3328  *  \throw If the nodal connectivity of cells is not defined.
3329  */
3330 int MEDCouplingUMesh::getNumberOfCells() const
3331
3332   if(_nodal_connec_index)
3333     return _nodal_connec_index->getNumberOfTuples()-1;
3334   else
3335     if(_mesh_dim==-1)
3336       return 1;
3337     else
3338       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3339 }
3340
3341 /*!
3342  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3343  * mesh. For more info see \ref MEDCouplingMeshesPage.
3344  *  \return int - the dimension of \a this mesh.
3345  *  \throw If the mesh dimension is not defined using setMeshDimension().
3346  */
3347 int MEDCouplingUMesh::getMeshDimension() const
3348 {
3349   if(_mesh_dim<-1)
3350     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3351   return _mesh_dim;
3352 }
3353
3354 /*!
3355  * Returns a length of the nodal connectivity array.
3356  * This method is for test reason. Normally the integer returned is not useable by
3357  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3358  *  \return int - the length of the nodal connectivity array.
3359  */
3360 int MEDCouplingUMesh::getMeshLength() const
3361 {
3362   return _nodal_connec->getNbOfElems();
3363 }
3364
3365 /*!
3366  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3367  */
3368 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3369 {
3370   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3371   tinyInfo.push_back(getMeshDimension());
3372   tinyInfo.push_back(getNumberOfCells());
3373   if(_nodal_connec)
3374     tinyInfo.push_back(getMeshLength());
3375   else
3376     tinyInfo.push_back(-1);
3377 }
3378
3379 /*!
3380  * First step of unserialization process.
3381  */
3382 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3383 {
3384   return tinyInfo[6]<=0;
3385 }
3386
3387 /*!
3388  * Second step of serialization process.
3389  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3390  */
3391 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3392 {
3393   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3394   if(tinyInfo[5]!=-1)
3395     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3396 }
3397
3398 /*!
3399  * Third and final step of serialization process.
3400  */
3401 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3402 {
3403   MEDCouplingPointSet::serialize(a1,a2);
3404   if(getMeshDimension()>-1)
3405     {
3406       a1=DataArrayInt::New();
3407       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3408       int *ptA1=a1->getPointer();
3409       const int *conn=getNodalConnectivity()->getConstPointer();
3410       const int *index=getNodalConnectivityIndex()->getConstPointer();
3411       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3412       std::copy(conn,conn+getMeshLength(),ptA1);
3413     }
3414   else
3415     a1=0;
3416 }
3417
3418 /*!
3419  * Second and final unserialization process.
3420  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3421  */
3422 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3423 {
3424   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3425   setMeshDimension(tinyInfo[5]);
3426   if(tinyInfo[7]!=-1)
3427     {
3428       // Connectivity
3429       const int *recvBuffer=a1->getConstPointer();
3430       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3431       myConnecIndex->alloc(tinyInfo[6]+1,1);
3432       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3433       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3434       myConnec->alloc(tinyInfo[7],1);
3435       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3436       setConnectivity(myConnec, myConnecIndex);
3437     }
3438 }
3439
3440 /*!
3441  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3442  * CellIds are given using range specified by a start an end and step.
3443  */
3444 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3445 {
3446   checkFullyDefined();
3447   int ncell=getNumberOfCells();
3448   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3449   ret->_mesh_dim=_mesh_dim;
3450   ret->setCoords(_coords);
3451   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3452   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3453   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3454   int work=start;
3455   const int *conn=_nodal_connec->getConstPointer();
3456   const int *connIndex=_nodal_connec_index->getConstPointer();
3457   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3458     {
3459       if(work>=0 && work<ncell)
3460         {
3461           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3462         }
3463       else
3464         {
3465           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3466           throw INTERP_KERNEL::Exception(oss.str().c_str());
3467         }
3468     }
3469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3470   int *newConnPtr=newConn->getPointer();
3471   std::set<INTERP_KERNEL::NormalizedCellType> types;
3472   work=start;
3473   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3474     {
3475       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3476       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3477     }
3478   ret->setConnectivity(newConn,newConnI,false);
3479   ret->_types=types;
3480   ret->copyTinyInfoFrom(this);
3481   return ret.retn();
3482 }
3483
3484 /*!
3485  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3486  * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3487  * The return newly allocated mesh will share the same coordinates as 'this'.
3488  */
3489 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3490 {
3491   checkFullyDefined();
3492   int ncell=getNumberOfCells();
3493   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3494   ret->_mesh_dim=_mesh_dim;
3495   ret->setCoords(_coords);
3496   std::size_t nbOfElemsRet=std::distance(begin,end);
3497   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3498   connIndexRet[0]=0;
3499   const int *conn=_nodal_connec->getConstPointer();
3500   const int *connIndex=_nodal_connec_index->getConstPointer();
3501   int newNbring=0;
3502   for(const int *work=begin;work!=end;work++,newNbring++)
3503     {
3504       if(*work>=0 && *work<ncell)
3505         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3506       else
3507         {
3508           free(connIndexRet);
3509           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3510           throw INTERP_KERNEL::Exception(oss.str().c_str());
3511         }
3512     }
3513   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3514   int *connRetWork=connRet;
3515   std::set<INTERP_KERNEL::NormalizedCellType> types;
3516   for(const int *work=begin;work!=end;work++)
3517     {
3518       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3519       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3520     }
3521   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3522   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3524   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3525   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3526   ret->_types=types;
3527   ret->copyTinyInfoFrom(this);
3528   return ret.retn();
3529 }
3530
3531 /*!
3532  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3533  * mesh.<br>
3534  * For 1D cells, the returned field contains lengths.<br>
3535  * For 2D cells, the returned field contains areas.<br>
3536  * For 3D cells, the returned field contains volumes.
3537  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3538  *         orientation, i.e. the volume is always positive.
3539  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3540  *         and one time . The caller is to delete this field using decrRef() as it is no
3541  *         more needed.
3542  */
3543 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3544 {
3545   std::string name="MeasureOfMesh_";
3546   name+=getName();
3547   int nbelem=getNumberOfCells();
3548   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3549   field->setName(name.c_str());
3550   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3551   array->alloc(nbelem,1);
3552   double *area_vol=array->getPointer();
3553   field->setArray(array) ; array=0;
3554   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3555   field->synchronizeTimeWithMesh();
3556   if(getMeshDimension()!=-1)
3557     {
3558       int ipt;
3559       INTERP_KERNEL::NormalizedCellType type;
3560       int dim_space=getSpaceDimension();
3561       const double *coords=getCoords()->getConstPointer();
3562       const int *connec=getNodalConnectivity()->getConstPointer();
3563       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3564       for(int iel=0;iel<nbelem;iel++)
3565         {
3566           ipt=connec_index[iel];
3567           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3568           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);
3569         }
3570       if(isAbs)
3571         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3572     }
3573   else
3574     {
3575       area_vol[0]=std::numeric_limits<double>::max();
3576     }
3577   return field.retn();
3578 }
3579
3580 /*!
3581  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3582  * mesh.<br>
3583  * For 1D cells, the returned array contains lengths.<br>
3584  * For 2D cells, the returned array contains areas.<br>
3585  * For 3D cells, the returned array contains volumes.
3586  * This method avoids building explicitly a part of \a this mesh to perform the work.
3587  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3588  *         orientation, i.e. the volume is always positive.
3589  *  \param [in] begin - an array of cell ids of interest.
3590  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3591  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3592  *          delete this array using decrRef() as it is no more needed.
3593  * 
3594  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3595  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3596  *  \sa getMeasureField()
3597  */
3598 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3599 {
3600   std::string name="PartMeasureOfMesh_";
3601   name+=getName();
3602   int nbelem=(int)std::distance(begin,end);
3603   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3604   array->setName(name.c_str());
3605   array->alloc(nbelem,1);
3606   double *area_vol=array->getPointer();
3607   if(getMeshDimension()!=-1)
3608     {
3609       int ipt;
3610       INTERP_KERNEL::NormalizedCellType type;
3611       int dim_space=getSpaceDimension();
3612       const double *coords=getCoords()->getConstPointer();
3613       const int *connec=getNodalConnectivity()->getConstPointer();
3614       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3615       for(const int *iel=begin;iel!=end;iel++)
3616         {
3617           ipt=connec_index[*iel];
3618           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3619           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3620         }
3621       if(isAbs)
3622         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3623     }
3624   else
3625     {
3626       area_vol[0]=std::numeric_limits<double>::max();
3627     }
3628   return array.retn();
3629 }
3630
3631 /*!
3632  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3633  * \a this one. The returned field contains the dual cell volume for each corresponding
3634  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3635  *  the dual mesh in P1 sens of \a this.<br>
3636  * For 1D cells, the returned field contains lengths.<br>
3637  * For 2D cells, the returned field contains areas.<br>
3638  * For 3D cells, the returned field contains volumes.
3639  * This method is useful to check "P1*" conservative interpolators.
3640  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3641  *         orientation, i.e. the volume is always positive.
3642  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3643  *          nodes and one time. The caller is to delete this array using decrRef() as
3644  *          it is no more needed.
3645  */
3646 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3647 {
3648   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3649   std::string name="MeasureOnNodeOfMesh_";
3650   name+=getName();
3651   int nbNodes=getNumberOfNodes();
3652   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3653   double cst=1./((double)getMeshDimension()+1.);
3654   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3655   array->alloc(nbNodes,1);
3656   double *valsToFill=array->getPointer();
3657   std::fill(valsToFill,valsToFill+nbNodes,0.);
3658   const double *values=tmp->getArray()->getConstPointer();
3659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3661   getReverseNodalConnectivity(da,daInd);
3662   const int *daPtr=da->getConstPointer();
3663   const int *daIPtr=daInd->getConstPointer();
3664   for(int i=0;i<nbNodes;i++)
3665     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3666       valsToFill[i]+=cst*values[*cell];
3667   ret->setMesh(this);
3668   ret->setArray(array);
3669   return ret.retn();
3670 }
3671
3672 /*!
3673  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3674  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3675  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3676  * and are normalized.
3677  * <br> \a this can be either 
3678  * - a  2D mesh in 2D or 3D space or 
3679  * - an 1D mesh in 2D space.
3680  * 
3681  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3682  *          cells and one time. The caller is to delete this field using decrRef() as
3683  *          it is no more needed.
3684  *  \throw If the nodal connectivity of cells is not defined.
3685  *  \throw If the coordinates array is not set.
3686  *  \throw If the mesh dimension is not set.
3687  *  \throw If the mesh and space dimension is not as specified above.
3688  */
3689 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3690 {
3691   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3692     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3693   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3694   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3695   int nbOfCells=getNumberOfCells();
3696   int nbComp=getMeshDimension()+1;
3697   array->alloc(nbOfCells,nbComp);
3698   double *vals=array->getPointer();
3699   const int *connI=_nodal_connec_index->getConstPointer();
3700   const int *conn=_nodal_connec->getConstPointer();
3701   const double *coords=_coords->getConstPointer();
3702   if(getMeshDimension()==2)
3703     {
3704       if(getSpaceDimension()==3)
3705         {
3706           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3707           const double *locPtr=loc->getConstPointer();
3708           for(int i=0;i<nbOfCells;i++,vals+=3)
3709             {
3710               int offset=connI[i];
3711               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3712               double n=INTERP_KERNEL::norm<3>(vals);
3713               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3714             }
3715         }
3716       else
3717         {
3718           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3719           const double *isAbsPtr=isAbs->getArray()->begin();
3720           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3721             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3722         }
3723     }
3724   else//meshdimension==1
3725     {
3726       double tmp[2];
3727       for(int i=0;i<nbOfCells;i++)
3728         {
3729           int offset=connI[i];
3730           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3731           double n=INTERP_KERNEL::norm<2>(tmp);
3732           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3733           *vals++=-tmp[1];
3734           *vals++=tmp[0];
3735         }
3736     }
3737   ret->setArray(array);
3738   ret->setMesh(this);
3739   ret->synchronizeTimeWithSupport();
3740   return ret.retn();
3741 }
3742
3743 /*!
3744  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3745  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3746  * and are normalized.
3747  * <br> \a this can be either 
3748  * - a  2D mesh in 2D or 3D space or 
3749  * - an 1D mesh in 2D space.
3750  * 
3751  * This method avoids building explicitly a part of \a this mesh to perform the work.
3752  *  \param [in] begin - an array of cell ids of interest.
3753  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3754  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3755  *          cells and one time. The caller is to delete this field using decrRef() as
3756  *          it is no more needed.
3757  *  \throw If the nodal connectivity of cells is not defined.
3758  *  \throw If the coordinates array is not set.
3759  *  \throw If the mesh dimension is not set.
3760  *  \throw If the mesh and space dimension is not as specified above.
3761  *  \sa buildOrthogonalField()
3762  *
3763  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3764  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3765  */
3766 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3767 {
3768   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3769     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3770   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3771   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3772   std::size_t nbelems=std::distance(begin,end);
3773   int nbComp=getMeshDimension()+1;
3774   array->alloc((int)nbelems,nbComp);
3775   double *vals=array->getPointer();
3776   const int *connI=_nodal_connec_index->getConstPointer();
3777   const int *conn=_nodal_connec->getConstPointer();
3778   const double *coords=_coords->getConstPointer();
3779   if(getMeshDimension()==2)
3780     {
3781       if(getSpaceDimension()==3)
3782         {
3783           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3784           const double *locPtr=loc->getConstPointer();
3785           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3786             {
3787               int offset=connI[*i];
3788               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3789               double n=INTERP_KERNEL::norm<3>(vals);
3790               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3791             }
3792         }
3793       else
3794         {
3795           for(std::size_t i=0;i<nbelems;i++)
3796             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3797         }
3798     }
3799   else//meshdimension==1
3800     {
3801       double tmp[2];
3802       for(const int *i=begin;i!=end;i++)
3803         {
3804           int offset=connI[*i];
3805           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3806           double n=INTERP_KERNEL::norm<2>(tmp);
3807           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3808           *vals++=-tmp[1];
3809           *vals++=tmp[0];
3810         }
3811     }
3812   ret->setArray(array);
3813   ret->setMesh(this);
3814   ret->synchronizeTimeWithSupport();
3815   return ret.retn();
3816 }
3817
3818 /*!
3819  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3820  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3821  * and are \b not normalized.
3822  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3823  *          cells and one time. The caller is to delete this field using decrRef() as
3824  *          it is no more needed.
3825  *  \throw If the nodal connectivity of cells is not defined.
3826  *  \throw If the coordinates array is not set.
3827  *  \throw If \a this->getMeshDimension() != 1.
3828  *  \throw If \a this mesh includes cells of type other than SEG2.
3829  */
3830 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3831 {
3832    if(getMeshDimension()!=1)
3833     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3834    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3835      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3836    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3837    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3838    int nbOfCells=getNumberOfCells();
3839    int spaceDim=getSpaceDimension();
3840    array->alloc(nbOfCells,spaceDim);
3841    double *pt=array->getPointer();
3842    const double *coo=getCoords()->getConstPointer();
3843    std::vector<int> conn;
3844    conn.reserve(2);
3845    for(int i=0;i<nbOfCells;i++)
3846      {
3847        conn.resize(0);
3848        getNodeIdsOfCell(i,conn);
3849        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3850      }
3851    ret->setArray(array);
3852    ret->setMesh(this);
3853    ret->synchronizeTimeWithSupport();
3854    return ret.retn();   
3855 }
3856
3857 /*!
3858  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3859  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3860  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3861  * from. If a result face is shared by two 3D cells, then the face in included twice in
3862  * the result mesh.
3863  *  \param [in] origin - 3 components of a point defining location of the plane.
3864  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3865  *         must be greater than 1e-6.
3866  *  \param [in] eps - half-thickness of the plane.
3867  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3868  *         producing correspondent 2D cells. The caller is to delete this array
3869  *         using decrRef() as it is no more needed.
3870  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3871  *         not share the node coordinates array with \a this mesh. The caller is to
3872  *         delete this mesh using decrRef() as it is no more needed.  
3873  *  \throw If the coordinates array is not set.
3874  *  \throw If the nodal connectivity of cells is not defined.
3875  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3876  *  \throw If magnitude of \a vec is less than 1e-6.
3877  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3878  *  \throw If \a this includes quadratic cells.
3879  */
3880 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3881 {
3882   checkFullyDefined();
3883   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3884     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3886   if(candidates->empty())
3887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3888   std::vector<int> nodes;
3889   DataArrayInt *cellIds1D=0;
3890   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3891   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3892   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3893   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3896   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3897   revDesc2=0; revDescIndx2=0;
3898   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3899   revDesc1=0; revDescIndx1=0;
3900   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3901   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3902   //
3903   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3904   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3905     cut3DCurve[*it]=-1;
3906   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3907   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3908   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3909                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3910                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3912   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3913   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3914   if(cellIds2->empty())
3915     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3916   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3917   ret->setCoords(mDesc1->getCoords());
3918   ret->setConnectivity(conn,connI,true);
3919   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3920   return ret.retn();
3921 }
3922
3923 /*!
3924  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3925 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
3926 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3927 the result mesh.
3928  *  \param [in] origin - 3 components of a point defining location of the plane.
3929  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3930  *         must be greater than 1e-6.
3931  *  \param [in] eps - half-thickness of the plane.
3932  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3933  *         producing correspondent segments. The caller is to delete this array
3934  *         using decrRef() as it is no more needed.
3935  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3936  *         mesh in 3D space. This mesh does not share the node coordinates array with
3937  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3938  *         no more needed. 
3939  *  \throw If the coordinates array is not set.
3940  *  \throw If the nodal connectivity of cells is not defined.
3941  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3942  *  \throw If magnitude of \a vec is less than 1e-6.
3943  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3944  *  \throw If \a this includes quadratic cells.
3945  */
3946 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3947 {
3948   checkFullyDefined();
3949   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3950     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3952   if(candidates->empty())
3953     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3954   std::vector<int> nodes;
3955   DataArrayInt *cellIds1D=0;
3956   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3957   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3961   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3962   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3963   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3964   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3965   //
3966   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3967   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3968     cut3DCurve[*it]=-1;
3969   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3970   int ncellsSub=subMesh->getNumberOfCells();
3971   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3972   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3973                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3974                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3976   conn->alloc(0,1);
3977   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3978   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3979   for(int i=0;i<ncellsSub;i++)
3980     {
3981       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3982         {
3983           if(cut3DSurf[i].first!=-2)
3984             {
3985               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3986               connI->pushBackSilent(conn->getNumberOfTuples());
3987               cellIds2->pushBackSilent(i);
3988             }
3989           else
3990             {
3991               int cellId3DSurf=cut3DSurf[i].second;
3992               int offset=nodalI[cellId3DSurf]+1;
3993               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3994               for(int j=0;j<nbOfEdges;j++)
3995                 {
3996                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3997                   connI->pushBackSilent(conn->getNumberOfTuples());
3998                   cellIds2->pushBackSilent(cellId3DSurf);
3999                 }
4000             }
4001         }
4002     }
4003   if(cellIds2->empty())
4004     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
4005   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
4006   ret->setCoords(mDesc1->getCoords());
4007   ret->setConnectivity(conn,connI,true);
4008   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
4009   return ret.retn();
4010 }
4011
4012 /*!
4013  * Finds cells whose bounding boxes intersect a given plane.
4014  *  \param [in] origin - 3 components of a point defining location of the plane.
4015  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
4016  *         must be greater than 1e-6.
4017  *  \param [in] eps - half-thickness of the plane.
4018  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
4019  *         cells. The caller is to delete this array using decrRef() as it is no more
4020  *         needed.
4021  *  \throw If the coordinates array is not set.
4022  *  \throw If the nodal connectivity of cells is not defined.
4023  *  \throw If \a this->getSpaceDimension() != 3.
4024  *  \throw If magnitude of \a vec is less than 1e-6.
4025  *  \sa buildSlice3D()
4026  */
4027 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
4028 {
4029   checkFullyDefined();
4030   if(getSpaceDimension()!=3)
4031     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4032   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4033   if(normm<1e-6)
4034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4035   double vec2[3];
4036   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4037   double angle=acos(vec[2]/normm);
4038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
4039   double bbox[6];
4040   if(angle>eps)
4041     {
4042       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
4043       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
4044       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4045       mw->setCoords(coo);
4046       mw->getBoundingBox(bbox);
4047       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4048       cellIds=mw->getCellsInBoundingBox(bbox,eps);
4049     }
4050   else
4051     {
4052       getBoundingBox(bbox);
4053       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4054       cellIds=getCellsInBoundingBox(bbox,eps);
4055     }
4056   return cellIds.retn();
4057 }
4058
4059 /*!
4060  * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4061  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4062  * No consideration of coordinate is done by this method.
4063  * 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)
4064  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
4065  */
4066 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
4067 {
4068   if(getMeshDimension()!=1)
4069     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4070   int nbCells=getNumberOfCells();
4071   if(nbCells<1)
4072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4073   const int *connI=_nodal_connec_index->getConstPointer();
4074   const int *conn=_nodal_connec->getConstPointer();
4075   int ref=conn[connI[0]+2];
4076   for(int i=1;i<nbCells;i++)
4077     {
4078       if(conn[connI[i]+1]!=ref)
4079         return false;
4080       ref=conn[connI[i]+2];
4081     }
4082   return true;
4083 }
4084
4085 /*!
4086  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4087  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4088  * @param pt reference point of the line
4089  * @param v normalized director vector of the line
4090  * @param eps max precision before throwing an exception
4091  * @param res output of size this->getNumberOfCells
4092  */
4093 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4094 {
4095   if(getMeshDimension()!=1)
4096     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4097    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4098      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4099    if(getSpaceDimension()!=3)
4100      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4101    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4102    const double *fPtr=f->getArray()->getConstPointer();
4103    double tmp[3];
4104    for(int i=0;i<getNumberOfCells();i++)
4105      {
4106        const double *tmp1=fPtr+3*i;
4107        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4108        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4109        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4110        double n1=INTERP_KERNEL::norm<3>(tmp);
4111        n1/=INTERP_KERNEL::norm<3>(tmp1);
4112        if(n1>eps)
4113          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4114      }
4115    const double *coo=getCoords()->getConstPointer();
4116    for(int i=0;i<getNumberOfNodes();i++)
4117      {
4118        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4119        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4120        res[i]=std::accumulate(tmp,tmp+3,0.);
4121      }
4122 }
4123
4124 /*!
4125  * 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. 
4126  * \a this is expected to be a mesh so that its space dimension is equal to its
4127  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4128  * 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).
4129  
4130  * 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
4131  * 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).
4132  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4133  *
4134  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4135  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4136  *
4137  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4138  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4139  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4140  * \return the positive value of the distance.
4141  * \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
4142  * dimension - 1.
4143  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4144  */
4145 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
4146 {
4147   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4148   if(meshDim!=spaceDim-1)
4149     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4150   if(meshDim!=2 && meshDim!=1)
4151     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4152   checkFullyDefined();
4153   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4154     { 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()); }
4155   DataArrayInt *ret1=0;
4156   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4157   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4158   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4159   cellId=*ret1Safe->begin();
4160   return *ret0->begin();
4161 }
4162
4163 /*!
4164  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4165  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4166  * 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
4167  * 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).
4168  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4169  * 
4170  * \a this is expected to be a mesh so that its space dimension is equal to its
4171  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4172  * 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).
4173  *
4174  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4175  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4176  *
4177  * \param [in] pts the list of points in which each tuple represents a point
4178  * \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.
4179  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4180  * \throw if number of components of \a pts is not equal to the space dimension.
4181  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4182  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4183  */
4184 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
4185 {
4186   if(!pts)
4187     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4188   pts->checkAllocated();
4189   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4190   if(meshDim!=spaceDim-1)
4191     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4192   if(meshDim!=2 && meshDim!=1)
4193     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4194   if(pts->getNumberOfComponents()!=spaceDim)
4195     {
4196       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4197       throw INTERP_KERNEL::Exception(oss.str().c_str());
4198     }
4199   checkFullyDefined();
4200   int nbCells=getNumberOfCells();
4201   if(nbCells==0)
4202     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4203   int nbOfPts=pts->getNumberOfTuples();
4204   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4205   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4206   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4207   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4208   std::vector<double> bbox;
4209   getBoundingBoxForBBTree(bbox);
4210   switch(spaceDim)
4211     {
4212     case 3:
4213       {
4214         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
4215         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4216           {
4217             double x=std::numeric_limits<double>::max();
4218             std::vector<int> elems;
4219             myTree.getMinDistanceOfMax(ptsPtr,x);
4220             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4221             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4222           }
4223         break;
4224       }
4225     case 2:
4226       {
4227         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
4228         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4229           {
4230             double x=std::numeric_limits<double>::max();
4231             std::vector<int> elems;
4232             myTree.getMinDistanceOfMax(ptsPtr,x);
4233             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4234             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4235           }
4236         break;
4237       }
4238     default:
4239       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4240     }
4241   cellIds=ret1.retn();
4242   return ret0.retn();
4243 }
4244
4245 /*!
4246  * \param [in] pt the start pointer (included) of the coordinates of the point
4247  * \param [in] cellIdsBg the start pointer (included) of cellIds
4248  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4249  * \param [in] nc nodal connectivity
4250  * \param [in] ncI nodal connectivity index
4251  * \param [in,out] ret0 the min distance between \a this and the external input point
4252  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4253  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4254  */
4255 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)
4256 {
4257   cellId=-1;
4258   ret0=std::numeric_limits<double>::max();
4259   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4260     {
4261       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4262         {
4263         case INTERP_KERNEL::NORM_TRI3:
4264           {
4265             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4266             if(tmp<ret0)
4267               { ret0=tmp; cellId=*zeCell; }
4268             break;
4269           }
4270         case INTERP_KERNEL::NORM_QUAD4:
4271         case INTERP_KERNEL::NORM_POLYGON:
4272           {
4273             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4274             if(tmp<ret0)
4275               { ret0=tmp; cellId=*zeCell; }
4276             break;
4277           }
4278         default:
4279           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4280         }
4281     }
4282 }
4283
4284 /*!
4285  * \param [in] pt the start pointer (included) of the coordinates of the point
4286  * \param [in] cellIdsBg the start pointer (included) of cellIds
4287  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4288  * \param [in] nc nodal connectivity
4289  * \param [in] ncI nodal connectivity index
4290  * \param [in,out] ret0 the min distance between \a this and the external input point
4291  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4292  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4293  */
4294 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)
4295 {
4296   cellId=-1;
4297   ret0=std::numeric_limits<double>::max();
4298   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4299     {
4300        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4301         {
4302         case INTERP_KERNEL::NORM_SEG2:
4303           {
4304             std::size_t uselessEntry=0;
4305             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4306             tmp=sqrt(tmp);
4307             if(tmp<ret0)
4308               { ret0=tmp; cellId=*zeCell; }
4309             break;
4310           }
4311         default:
4312           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4313         }
4314     }
4315 }
4316
4317 /*!
4318  * Finds cells in contact with a ball (i.e. a point with precision). 
4319  * \warning This method is suitable if the caller intends to evaluate only one
4320  *          point, for more points getCellsContainingPoints() is recommended as it is
4321  *          faster. 
4322  *  \param [in] pos - array of coordinates of the ball central point.
4323  *  \param [in] eps - ball radius.
4324  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4325  *         if there are no such cells.
4326  *  \throw If the coordinates array is not set.
4327  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4328  */
4329 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4330 {
4331   std::vector<int> elts;
4332   getCellsContainingPoint(pos,eps,elts);
4333   if(elts.empty())
4334     return -1;
4335   return elts.front();
4336 }
4337
4338 /*!
4339  * Finds cells in contact with a ball (i.e. a point with precision).
4340  * \warning This method is suitable if the caller intends to evaluate only one
4341  *          point, for more points getCellsContainingPoints() is recommended as it is
4342  *          faster. 
4343  *  \param [in] pos - array of coordinates of the ball central point.
4344  *  \param [in] eps - ball radius.
4345  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
4346  *         before inserting ids.
4347  *  \throw If the coordinates array is not set.
4348  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4349  *
4350  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4351  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4352  */
4353 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4354 {
4355   std::vector<int> eltsIndex;
4356   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4357 }
4358
4359 /// @cond INTERNAL
4360
4361 namespace ParaMEDMEM
4362 {
4363   template<const int SPACEDIMM>
4364   class DummyClsMCUG
4365   {
4366   public:
4367     static const int MY_SPACEDIM=SPACEDIMM;
4368     static const int MY_MESHDIM=8;
4369     typedef int MyConnType;
4370     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4371     // begin
4372     // useless, but for windows compilation ...
4373     const double* getCoordinatesPtr() const { return 0; }
4374     const int* getConnectivityPtr() const { return 0; }
4375     const int* getConnectivityIndexPtr() const { return 0; }
4376     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4377     // end
4378   };
4379
4380   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4381   {
4382     INTERP_KERNEL::Edge *ret=0;
4383     switch(typ)
4384       {
4385       case INTERP_KERNEL::NORM_SEG2:
4386         {
4387           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4388           break;
4389         }
4390       case INTERP_KERNEL::NORM_SEG3:
4391         {
4392           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4393           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4394           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4395           bool colinearity=inters.areColinears();
4396           delete e1; delete e2;
4397           if(colinearity)
4398             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4399           else
4400             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4401           mapp2[bg[2]].second=false;
4402           break;
4403         }
4404       default:
4405         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4406       }
4407     return ret;
4408   }
4409
4410   /*!
4411    * 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'.
4412    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4413    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4414    */
4415   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4416   {
4417     mapp.clear();
4418     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.
4419     const double *coo=mDesc->getCoords()->getConstPointer();
4420     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4421     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4422     std::set<int> s;
4423     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4424       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4425     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4426       {
4427         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4428         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4429       }
4430     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4431     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4432       {
4433         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4434         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4435       }
4436     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4437       {
4438         if((*it2).second.second)
4439           mapp[(*it2).second.first]=(*it2).first;
4440         ((*it2).second.first)->decrRef();
4441       }
4442     return ret;
4443   }
4444
4445   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4446   {
4447     if(nodeId>=offset2)
4448       {
4449         int locId=nodeId-offset2;
4450         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4451       }
4452     if(nodeId>=offset1)
4453       {
4454         int locId=nodeId-offset1;
4455         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4456       }
4457     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4458   }
4459
4460   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4461                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4462                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4463   {
4464     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4465       {
4466         int eltId1=abs(*desc1)-1;
4467         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4468           {
4469             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4470             if(it==mappRev.end())
4471               {
4472                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4473                 mapp[node]=*it1;
4474                 mappRev[*it1]=node;
4475               }
4476           }
4477       }
4478   }
4479 }
4480
4481 /// @endcond
4482
4483 template<int SPACEDIM>
4484 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4485                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4486 {
4487   std::vector<double> bbox;
4488   eltsIndex.resize(nbOfPoints+1);
4489   eltsIndex[0]=0;
4490   elts.clear();
4491   getBoundingBoxForBBTree(bbox);
4492   int nbOfCells=getNumberOfCells();
4493   const int *conn=_nodal_connec->getConstPointer();
4494   const int *connI=_nodal_connec_index->getConstPointer();
4495   double bb[2*SPACEDIM];
4496   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4497   for(int i=0;i<nbOfPoints;i++)
4498     {
4499       eltsIndex[i+1]=eltsIndex[i];
4500       for(int j=0;j<SPACEDIM;j++)
4501         {
4502           bb[2*j]=pos[SPACEDIM*i+j];
4503           bb[2*j+1]=pos[SPACEDIM*i+j];
4504         }
4505       std::vector<int> candidates;
4506       myTree.getIntersectingElems(bb,candidates);
4507       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4508         {
4509           int sz=connI[(*iter)+1]-connI[*iter]-1;
4510           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4511                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4512                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4513             {
4514               eltsIndex[i+1]++;
4515               elts.push_back(*iter);
4516             }
4517         }
4518     }
4519 }
4520 /*!
4521  * Finds cells in contact with several balls (i.e. points with precision).
4522  * This method is an extension of getCellContainingPoint() and
4523  * getCellsContainingPoint() for the case of multiple points.
4524  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4525  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4526  *         this->getSpaceDimension() * \a nbOfPoints 
4527  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4528  *  \param [in] eps - radius of balls (i.e. the precision).
4529  *  \param [in,out] elts - vector returning ids of found cells.
4530  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4531  *         dividing cell ids in \a elts into groups each referring to one
4532  *         point. Its every element (except the last one) is an index pointing to the
4533  *         first id of a group of cells. For example cells in contact with the *i*-th
4534  *         point are described by following range of indices:
4535  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4536  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4537  *         Number of cells in contact with the *i*-th point is
4538  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4539  *  \throw If the coordinates array is not set.
4540  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4541  *
4542  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4543  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4544  */
4545 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4546                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4547 {
4548   int spaceDim=getSpaceDimension();
4549   int mDim=getMeshDimension();
4550   if(spaceDim==3)
4551     {
4552       if(mDim==3)
4553         {
4554           const double *coords=_coords->getConstPointer();
4555           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4556         }
4557       /*else if(mDim==2)
4558         {
4559           
4560         }*/
4561       else
4562         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4563     }
4564   else if(spaceDim==2)
4565     {
4566       if(mDim==2)
4567         {
4568           const double *coords=_coords->getConstPointer();
4569           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4570         }
4571       else
4572         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4573     }
4574   else if(spaceDim==1)
4575     {
4576       if(mDim==1)
4577         {
4578           const double *coords=_coords->getConstPointer();
4579           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4580         }
4581       else
4582         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4583     }
4584   else
4585     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4586 }
4587
4588 /*!
4589  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4590  * least two its edges intersect each other anywhere except their extremities. An
4591  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4592  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4593  *         cleared before filling in.
4594  *  \param [in] eps - precision.
4595  *  \throw If \a this->getMeshDimension() != 2.
4596  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4597  */
4598 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4599 {
4600   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4601   if(getMeshDimension()!=2)
4602     throw INTERP_KERNEL::Exception(msg);
4603   int spaceDim=getSpaceDimension();
4604   if(spaceDim!=2 && spaceDim!=3)
4605     throw INTERP_KERNEL::Exception(msg);
4606   const int *conn=_nodal_connec->getConstPointer();
4607   const int *connI=_nodal_connec_index->getConstPointer();
4608   int nbOfCells=getNumberOfCells();
4609   std::vector<double> cell2DinS2;
4610   for(int i=0;i<nbOfCells;i++)
4611     {
4612       int offset=connI[i];
4613       int nbOfNodesForCell=connI[i+1]-offset-1;
4614       if(nbOfNodesForCell<=3)
4615         continue;
4616       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4617       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4618       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4619         cells.push_back(i);
4620       cell2DinS2.clear();
4621     }
4622 }
4623
4624 /*!
4625  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4626  *
4627  * 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.
4628  * 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.
4629  * 
4630  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4631  * This convex envelop is computed using Jarvis march algorithm.
4632  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4633  * 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)
4634  * 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.
4635  *
4636  * @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.
4637  */
4638 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4639 {
4640   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4641     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4642   checkFullyDefined();
4643   const double *coords=getCoords()->getConstPointer();
4644   int nbOfCells=getNumberOfCells();
4645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4646   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4648   int *workIndexOut=nodalConnecIndexOut->getPointer();
4649   *workIndexOut=0;
4650   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4651   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4652   std::set<INTERP_KERNEL::NormalizedCellType> types;
4653   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4654   isChanged->alloc(0,1);
4655   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4656     {
4657       int pos=nodalConnecOut->getNumberOfTuples();
4658       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4659         isChanged->pushBackSilent(i);
4660       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4661       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4662     }
4663   if(isChanged->empty())
4664     return 0;
4665   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4666   _types=types;
4667   return isChanged.retn();
4668 }
4669
4670 /*!
4671  * This method is \b NOT const because it can modify 'this'.
4672  * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4673  * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4674  * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4675  * \b 1 for translation and rotation around point of 'mesh1D'.
4676  * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.  
4677  */
4678 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4679 {
4680   checkFullyDefined();
4681   mesh1D->checkFullyDefined();
4682   if(!mesh1D->isContiguous1D())
4683     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4684   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4685     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4686   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4687     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4688   if(mesh1D->getMeshDimension()!=1)
4689     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4690   bool isQuad=false;
4691   if(isPresenceOfQuadratic())
4692     {
4693       if(mesh1D->isFullyQuadratic())
4694         isQuad=true;
4695       else
4696         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4697     }
4698   zipCoords();
4699   int oldNbOfNodes=getNumberOfNodes();
4700   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4701   switch(policy)
4702     {
4703     case 0:
4704       {
4705         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4706         break;
4707       }
4708     case 1:
4709       {
4710         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4711         break;
4712       }
4713     default:
4714       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4715     }
4716   setCoords(newCoords);
4717   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4718   updateTime();
4719   return ret.retn();
4720 }
4721
4722 /*!
4723  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4724  * If it is not the case an exception will be thrown.
4725  * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4726  * intersection of plane defined by ('origin','vec').
4727  * This method has one in/out parameter : 'cut3DCurve'.
4728  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4729  * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4730  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4731  * This method will throw an exception if 'this' contains a non linear segment.
4732  */
4733 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4734 {
4735   checkFullyDefined();
4736   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4738   int ncells=getNumberOfCells();
4739   int nnodes=getNumberOfNodes();
4740   double vec2[3],vec3[3],vec4[3];
4741   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4742   if(normm<1e-6)
4743     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4744   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4745   const int *conn=_nodal_connec->getConstPointer();
4746   const int *connI=_nodal_connec_index->getConstPointer();
4747   const double *coo=_coords->getConstPointer();
4748   std::vector<double> addCoo;
4749   for(int i=0;i<ncells;i++)
4750     {
4751       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4752         {
4753           if(cut3DCurve[i]==-2)
4754             {
4755               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4756               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];
4757               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4758               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4759               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4760                 {
4761                   const double *st2=coo+3*st;
4762                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4763                   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]));
4764                   if(pos>eps && pos<1-eps)
4765                     {
4766                       int nNode=((int)addCoo.size())/3;
4767                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4768                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4769                       cut3DCurve[i]=nnodes+nNode;
4770                     }
4771                 }
4772             }
4773         }
4774       else
4775         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4776     }
4777   if(!addCoo.empty())
4778     {
4779       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4780       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4781       coo2->alloc(newNbOfNodes,3);
4782       double *tmp=coo2->getPointer();
4783       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4784       std::copy(addCoo.begin(),addCoo.end(),tmp);
4785       DataArrayDouble::SetArrayIn(coo2,_coords);
4786     }
4787 }
4788
4789 /*!
4790  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4791  * @param mesh1D is the input 1D mesh used for translation computation.
4792  * @return newCoords new coords filled by this method. 
4793  */
4794 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4795 {
4796   int oldNbOfNodes=getNumberOfNodes();
4797   int nbOf1DCells=mesh1D->getNumberOfCells();
4798   int spaceDim=getSpaceDimension();
4799   DataArrayDouble *ret=DataArrayDouble::New();
4800   std::vector<bool> isQuads;
4801   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4802   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4803   double *retPtr=ret->getPointer();
4804   const double *coords=getCoords()->getConstPointer();
4805   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4806   std::vector<int> v;
4807   std::vector<double> c;
4808   double vec[3];
4809   v.reserve(3);
4810   c.reserve(6);
4811   for(int i=0;i<nbOf1DCells;i++)
4812     {
4813       v.resize(0);
4814       mesh1D->getNodeIdsOfCell(i,v);
4815       c.resize(0);
4816       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4817       mesh1D->getCoordinatesOfNode(v[0],c);
4818       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4819       for(int j=0;j<oldNbOfNodes;j++)
4820         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4821       if(isQuad)
4822         {
4823           c.resize(0);
4824           mesh1D->getCoordinatesOfNode(v[1],c);
4825           mesh1D->getCoordinatesOfNode(v[0],c);
4826           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4827           for(int j=0;j<oldNbOfNodes;j++)
4828             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4829         }
4830     }
4831   ret->copyStringInfoFrom(*getCoords());
4832   return ret;
4833 }
4834
4835 /*!
4836  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4837  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4838  * @return newCoords new coords filled by this method. 
4839  */
4840 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4841 {
4842   if(mesh1D->getSpaceDimension()==2)
4843     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4844   if(mesh1D->getSpaceDimension()==3)
4845     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4846   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4847 }
4848
4849 /*!
4850  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4851  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4852  * @return newCoords new coords filled by this method. 
4853  */
4854 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4855 {
4856   if(isQuad)
4857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4858   int oldNbOfNodes=getNumberOfNodes();
4859   int nbOf1DCells=mesh1D->getNumberOfCells();
4860   if(nbOf1DCells<2)
4861     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4862   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4863   int nbOfLevsInVec=nbOf1DCells+1;
4864   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4865   double *retPtr=ret->getPointer();
4866   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4867   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4868   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4869   tmp->setCoords(tmp2);
4870   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4871   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4872   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4873   for(int i=1;i<nbOfLevsInVec;i++)
4874     {
4875       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4876       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4877       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4878       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4879       tmp->translate(vec);
4880       double tmp3[2],radius,alpha,alpha0;
4881       const double *p0=i+1<nbOfLevsInVec?begin:third;
4882       const double *p1=i+1<nbOfLevsInVec?end:begin;
4883       const double *p2=i+1<nbOfLevsInVec?third:end;
4884       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4885       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]);
4886       double angle=acos(cosangle/(radius*radius));
4887       tmp->rotate(end,0,angle);
4888       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4889     }
4890   return ret.retn();
4891 }
4892
4893 /*!
4894  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4895  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4896  * @return newCoords new coords filled by this method. 
4897  */
4898 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4899 {
4900   if(isQuad)
4901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4902   int oldNbOfNodes=getNumberOfNodes();
4903   int nbOf1DCells=mesh1D->getNumberOfCells();
4904   if(nbOf1DCells<2)
4905     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4906   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4907   int nbOfLevsInVec=nbOf1DCells+1;
4908   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4909   double *retPtr=ret->getPointer();
4910   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4911   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4912   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4913   tmp->setCoords(tmp2);
4914   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4915   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4916   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4917   for(int i=1;i<nbOfLevsInVec;i++)
4918     {
4919       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4920       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4921       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4922       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4923       tmp->translate(vec);
4924       double tmp3[2],radius,alpha,alpha0;
4925       const double *p0=i+1<nbOfLevsInVec?begin:third;
4926       const double *p1=i+1<nbOfLevsInVec?end:begin;
4927       const double *p2=i+1<nbOfLevsInVec?third:end;
4928       double vecPlane[3]={
4929         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4930         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4931         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4932       };
4933       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4934       if(norm>1.e-7)
4935         {
4936           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4937           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4938           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4939           double s2=norm2;
4940           double c2=cos(asin(s2));
4941           double m[3][3]={
4942             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4943             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4944             {-vec2[1]*s2, vec2[0]*s2, c2}
4945           };
4946           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]};
4947           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]};
4948           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]};
4949           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4950           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]);
4951           double angle=acos(cosangle/(radius*radius));
4952           tmp->rotate(end,vecPlane,angle);
4953           
4954         }
4955       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4956     }
4957   return ret.retn();
4958 }
4959
4960 /*!
4961  * This method is private because not easy to use for end user. This method is const contrary to
4962  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4963  * the coords sorted slice by slice.
4964  * @param isQuad specifies presence of quadratic cells.
4965  */
4966 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4967 {
4968   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4969   int nbOf2DCells=getNumberOfCells();
4970   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4971   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4972   const int *conn=_nodal_connec->getConstPointer();
4973   const int *connI=_nodal_connec_index->getConstPointer();
4974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4976   newConnI->alloc(nbOf3DCells+1,1);
4977   int *newConnIPtr=newConnI->getPointer();
4978   *newConnIPtr++=0;
4979   std::vector<int> newc;
4980   for(int j=0;j<nbOf2DCells;j++)
4981     {
4982       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4983       *newConnIPtr++=(int)newc.size();
4984     }
4985   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4986   int *newConnPtr=newConn->getPointer();
4987   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4988   newConnIPtr=newConnI->getPointer();
4989   for(int iz=0;iz<nbOf1DCells;iz++)
4990     {
4991       if(iz!=0)
4992         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4993       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4994         {
4995           int icell=(int)(iter-newc.begin());
4996           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4997             {
4998               if(*iter!=-1)
4999                 *newConnPtr=(*iter)+iz*deltaPerLev;
5000               else
5001                 *newConnPtr=-1;
5002             }
5003           else
5004             *newConnPtr=(*iter);
5005         }
5006     }
5007   ret->setConnectivity(newConn,newConnI,true);
5008   ret->setCoords(getCoords());
5009   return ret;
5010 }
5011
5012 /*!
5013  * Checks if \a this mesh is constituted by only quadratic cells.
5014  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5015  *  \throw If the coordinates array is not set.
5016  *  \throw If the nodal connectivity of cells is not defined.
5017  */
5018 bool MEDCouplingUMesh::isFullyQuadratic() const
5019 {
5020   checkFullyDefined();
5021   bool ret=true;
5022   int nbOfCells=getNumberOfCells();
5023   for(int i=0;i<nbOfCells && ret;i++)
5024     {
5025       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5026       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5027       ret=cm.isQuadratic();
5028     }
5029   return ret;
5030 }
5031
5032 /*!
5033  * Checks if \a this mesh includes any quadratic cell.
5034  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5035  *  \throw If the coordinates array is not set.
5036  *  \throw If the nodal connectivity of cells is not defined.
5037  */
5038 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5039 {
5040   checkFullyDefined();
5041   bool ret=false;
5042   int nbOfCells=getNumberOfCells();
5043   for(int i=0;i<nbOfCells && !ret;i++)
5044     {
5045       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5046       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5047       ret=cm.isQuadratic();
5048     }
5049   return ret;
5050 }
5051
5052 /*!
5053  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5054  * this mesh, it remains unchanged.
5055  *  \throw If the coordinates array is not set.
5056  *  \throw If the nodal connectivity of cells is not defined.
5057  */
5058 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
5059 {
5060   checkFullyDefined();
5061   int nbOfCells=getNumberOfCells();
5062   int delta=0;
5063   const int *iciptr=_nodal_connec_index->getConstPointer();
5064   for(int i=0;i<nbOfCells;i++)
5065     {
5066       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5067       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5068       if(cm.isQuadratic())
5069         {
5070           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5071           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5072           if(!cml.isDynamic())
5073             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5074           else
5075             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5076         }
5077     }
5078   if(delta==0)
5079     return ;
5080   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5081   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5082   const int *icptr=_nodal_connec->getConstPointer();
5083   newConn->alloc(getMeshLength()-delta,1);
5084   newConnI->alloc(nbOfCells+1,1);
5085   int *ocptr=newConn->getPointer();
5086   int *ociptr=newConnI->getPointer();
5087   *ociptr=0;
5088   _types.clear();
5089   for(int i=0;i<nbOfCells;i++,ociptr++)
5090     {
5091       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5092       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5093       if(!cm.isQuadratic())
5094         {
5095           _types.insert(type);
5096           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5097           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5098         }
5099       else
5100         {
5101           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5102           _types.insert(typel);
5103           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5104           int newNbOfNodes=cml.getNumberOfNodes();
5105           if(cml.isDynamic())
5106             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5107           *ocptr++=(int)typel;
5108           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5109           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5110         }
5111     }
5112   setConnectivity(newConn,newConnI,false);
5113 }
5114
5115 /*!
5116  * This method converts all linear cell in \a this to quadratic one.
5117  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5118  * 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)
5119  * 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.
5120  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5121  * end of the existing coordinates.
5122  * 
5123  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5124  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5125  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5126  * 
5127  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5128  *
5129  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5130  */
5131 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
5132 {
5133   DataArrayInt *conn=0,*connI=0;
5134   DataArrayDouble *coords=0;
5135   std::set<INTERP_KERNEL::NormalizedCellType> types;
5136   checkFullyDefined();
5137   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5138   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5139   int meshDim=getMeshDimension();
5140   switch(conversionType)
5141     {
5142     case 0:
5143       switch(meshDim)
5144         {
5145         case 1:
5146           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5147           connSafe=conn; connISafe=connI; coordsSafe=coords;
5148           break;
5149         case 2:
5150           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5151           connSafe=conn; connISafe=connI; coordsSafe=coords;
5152           break;
5153         case 3:
5154           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5155           connSafe=conn; connISafe=connI; coordsSafe=coords;
5156           break;
5157         default:
5158           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5159         }
5160       break;
5161     case 1:
5162       {
5163         switch(meshDim)
5164         {
5165         case 1:
5166           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5167           connSafe=conn; connISafe=connI; coordsSafe=coords;
5168           break;
5169         case 2:
5170           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5171           connSafe=conn; connISafe=connI; coordsSafe=coords;
5172           break;
5173         case 3:
5174           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5175           connSafe=conn; connISafe=connI; coordsSafe=coords;
5176           break;
5177         default:
5178           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5179         }
5180         break;
5181       }
5182     default:
5183       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5184     }
5185   setConnectivity(connSafe,connISafe,false);
5186   _types=types;
5187   setCoords(coordsSafe);
5188   return ret.retn();
5189 }
5190
5191 /*!
5192  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5193  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5194  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5195  */
5196 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5197 {
5198   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5202   int nbOfCells=getNumberOfCells();
5203   int nbOfNodes=getNumberOfNodes();
5204   const int *cPtr=_nodal_connec->getConstPointer();
5205   const int *icPtr=_nodal_connec_index->getConstPointer();
5206   int lastVal=0,offset=nbOfNodes;
5207   for(int i=0;i<nbOfCells;i++,icPtr++)
5208     {
5209       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5210       if(type==INTERP_KERNEL::NORM_SEG2)
5211         {
5212           types.insert(INTERP_KERNEL::NORM_SEG3);
5213           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5214           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5215           newConn->pushBackSilent(offset++);
5216           lastVal+=4;
5217           newConnI->pushBackSilent(lastVal);
5218           ret->pushBackSilent(i);
5219         }
5220       else
5221         {
5222           types.insert(type);
5223           lastVal+=(icPtr[1]-icPtr[0]);
5224           newConnI->pushBackSilent(lastVal);
5225           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5226         }
5227     }
5228   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5229   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5230   return ret.retn();
5231 }
5232
5233 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)
5234 {
5235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5238   //
5239   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5240   DataArrayInt *conn1D=0,*conn1DI=0;
5241   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5242   DataArrayDouble *coordsTmp=0;
5243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5244   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5245   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5246   const int *c1DPtr=conn1D->begin();
5247   const int *c1DIPtr=conn1DI->begin();
5248   int nbOfCells=getNumberOfCells();
5249   const int *cPtr=_nodal_connec->getConstPointer();
5250   const int *icPtr=_nodal_connec_index->getConstPointer();
5251   int lastVal=0;
5252   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5253     {
5254       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5255       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5256       if(!cm.isQuadratic())
5257         {
5258           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5259           types.insert(typ2); newConn->pushBackSilent(typ2);
5260           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5261           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5262             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5263           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5264           newConnI->pushBackSilent(lastVal);
5265           ret->pushBackSilent(i);
5266         }
5267       else
5268         {
5269           types.insert(typ);
5270           lastVal+=(icPtr[1]-icPtr[0]);
5271           newConnI->pushBackSilent(lastVal);
5272           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5273         }
5274     }
5275   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5276   return ret.retn();
5277 }
5278
5279 /*!
5280  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5281  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5282  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5283  */
5284 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5285 {
5286   
5287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5288   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5289   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5290 }
5291
5292 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5293 {
5294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5295   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5296   //
5297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5300   //
5301   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5302   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5303   DataArrayInt *conn1D=0,*conn1DI=0;
5304   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5305   DataArrayDouble *coordsTmp=0;
5306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5309   const int *c1DPtr=conn1D->begin();
5310   const int *c1DIPtr=conn1DI->begin();
5311   int nbOfCells=getNumberOfCells();
5312   const int *cPtr=_nodal_connec->getConstPointer();
5313   const int *icPtr=_nodal_connec_index->getConstPointer();
5314   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5315   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5316     {
5317       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5318       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5319       if(!cm.isQuadratic())
5320         {
5321           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5322           types.insert(typ2); newConn->pushBackSilent(typ2);
5323           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5324           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5325             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5326           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5327           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5328           newConnI->pushBackSilent(lastVal);
5329           ret->pushBackSilent(i);
5330         }
5331       else
5332         {
5333           types.insert(typ);
5334           lastVal+=(icPtr[1]-icPtr[0]);
5335           newConnI->pushBackSilent(lastVal);
5336           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5337         }
5338     }
5339   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5340   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5341   return ret.retn();
5342 }
5343
5344 /*!
5345  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5346  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5347  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5348  */
5349 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5350 {
5351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5352   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5353   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5354 }
5355
5356 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5357 {
5358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5359   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5361   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5362   //
5363   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5364   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5366   //
5367   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5368   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5369   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5370   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5371   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5374   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5376   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5378   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5379   int nbOfCells=getNumberOfCells();
5380   const int *cPtr=_nodal_connec->getConstPointer();
5381   const int *icPtr=_nodal_connec_index->getConstPointer();
5382   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5383   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5384     {
5385       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5386       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5387       if(!cm.isQuadratic())
5388         {
5389           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5390           if(typ2==INTERP_KERNEL::NORM_ERROR)
5391             {
5392               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5393               throw INTERP_KERNEL::Exception(oss.str().c_str());
5394             }
5395           types.insert(typ2); newConn->pushBackSilent(typ2);
5396           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5397           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5398             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5399           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5400             {
5401               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5402               int tmpPos=newConn->getNumberOfTuples();
5403               newConn->pushBackSilent(nodeId2);
5404               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5405             }
5406           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5407           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5408           newConnI->pushBackSilent(lastVal);
5409           ret->pushBackSilent(i);
5410         }
5411       else
5412         {
5413           types.insert(typ);
5414           lastVal+=(icPtr[1]-icPtr[0]);
5415           newConnI->pushBackSilent(lastVal);
5416           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5417         }
5418     }
5419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5420   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5421   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5422   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5423   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5424   int *c=newConn->getPointer();
5425   const int *cI(newConnI->begin());
5426   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5427     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5428   offset=coordsTmp2Safe->getNumberOfTuples();
5429   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5430     c[cI[(*elt)+1]-1]+=offset;
5431   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5432   return ret.retn();
5433 }
5434
5435 /*!
5436  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5437  * so that the number of cells remains the same. Quadratic faces are converted to
5438  * polygons. This method works only for 2D meshes in
5439  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5440  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5441  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5442  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5443  *         a polylinized edge constituting the input polygon.
5444  *  \throw If the coordinates array is not set.
5445  *  \throw If the nodal connectivity of cells is not defined.
5446  *  \throw If \a this->getMeshDimension() != 2.
5447  *  \throw If \a this->getSpaceDimension() != 2.
5448  */
5449 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5450 {
5451   checkFullyDefined();
5452   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5453     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5454   double epsa=fabs(eps);
5455   if(epsa<std::numeric_limits<double>::min())
5456     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 !");
5457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5461   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5462   revDesc1=0; revDescIndx1=0;
5463   mDesc->tessellate2DCurve(eps);
5464   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5465   setCoords(mDesc->getCoords());
5466 }
5467
5468 /*!
5469  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5470  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5471  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5472  *         a sub-divided edge.
5473  *  \throw If the coordinates array is not set.
5474  *  \throw If the nodal connectivity of cells is not defined.
5475  *  \throw If \a this->getMeshDimension() != 1.
5476  *  \throw If \a this->getSpaceDimension() != 2.
5477  */
5478 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5479 {
5480   checkFullyDefined();
5481   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5482     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5483   double epsa=fabs(eps);
5484   if(epsa<std::numeric_limits<double>::min())
5485     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 !");
5486   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5487   int nbCells=getNumberOfCells();
5488   int nbNodes=getNumberOfNodes();
5489   const int *conn=_nodal_connec->getConstPointer();
5490   const int *connI=_nodal_connec_index->getConstPointer();
5491   const double *coords=_coords->getConstPointer();
5492   std::vector<double> addCoo;
5493   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5494   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5495   newConnI->alloc(nbCells+1,1);
5496   int *newConnIPtr=newConnI->getPointer();
5497   *newConnIPtr=0;
5498   int tmp1[3];
5499   INTERP_KERNEL::Node *tmp2[3];
5500   std::set<INTERP_KERNEL::NormalizedCellType> types;
5501   for(int i=0;i<nbCells;i++,newConnIPtr++)
5502     {
5503       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5504       if(cm.isQuadratic())
5505         {//assert(connI[i+1]-connI[i]-1==3)
5506           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5507           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5508           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5509           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5510           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5511           if(eac)
5512             {
5513               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5514               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5515               delete eac;
5516               newConnIPtr[1]=(int)newConn.size();
5517             }
5518           else
5519             {
5520               types.insert(INTERP_KERNEL::NORM_SEG2);
5521               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5522               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5523               newConnIPtr[1]=newConnIPtr[0]+3;
5524             }
5525         }
5526       else
5527         {
5528           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5529           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5530           newConnIPtr[1]=newConnIPtr[0]+3;
5531         }
5532     }
5533   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5534     return ;
5535   _types=types;
5536   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5538   newConnArr->alloc((int)newConn.size(),1);
5539   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5540   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5541   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5542   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5543   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5544   std::copy(addCoo.begin(),addCoo.end(),work);
5545   DataArrayDouble::SetArrayIn(newCoords,_coords);
5546   updateTime();
5547 }
5548
5549 /*!
5550  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5551  * In addition, returns an array mapping new cells to old ones. <br>
5552  * This method typically increases the number of cells in \a this mesh
5553  * but the number of nodes remains \b unchanged.
5554  * That's why the 3D splitting policies
5555  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5556  *  \param [in] policy - specifies a pattern used for splitting.
5557  * The semantic of \a policy is:
5558  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5559  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5560  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5561  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5562  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5563  *          an id of old cell producing it. The caller is to delete this array using
5564  *         decrRef() as it is no more needed. 
5565  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5566  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5567  *          and \a this->getMeshDimension() != 3. 
5568  *  \throw If \a policy is not one of the four discussed above.
5569  *  \throw If the nodal connectivity of cells is not defined.
5570  */
5571 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5572 {
5573   switch(policy)
5574     {
5575     case 0:
5576       return simplexizePol0();
5577     case 1:
5578       return simplexizePol1();
5579     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5580       return simplexizePlanarFace5();
5581     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5582       return simplexizePlanarFace6();
5583     default:
5584       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)");
5585     }
5586 }
5587
5588 /*!
5589  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5590  * - 1D: INTERP_KERNEL::NORM_SEG2
5591  * - 2D: INTERP_KERNEL::NORM_TRI3
5592  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5593  *
5594  * This method is useful for users that need to use P1 field services as
5595  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5596  * All these methods need mesh support containing only simplex cells.
5597  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5598  *  \throw If the coordinates array is not set.
5599  *  \throw If the nodal connectivity of cells is not defined.
5600  *  \throw If \a this->getMeshDimension() < 1.
5601  */
5602 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5603 {
5604   checkFullyDefined();
5605   int mdim=getMeshDimension();
5606   if(mdim<1 || mdim>3)
5607     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5608   int nbCells=getNumberOfCells();
5609   const int *conn=_nodal_connec->getConstPointer();
5610   const int *connI=_nodal_connec_index->getConstPointer();
5611   for(int i=0;i<nbCells;i++)
5612     {
5613       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5614       if(!cm.isSimplex())
5615         return false;
5616     }
5617   return true;
5618 }
5619
5620 /*!
5621  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5622  */
5623 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5624 {
5625   checkConnectivityFullyDefined();
5626   if(getMeshDimension()!=2)
5627     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5628   int nbOfCells=getNumberOfCells();
5629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5630   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5631   ret->alloc(nbOfCells+nbOfCutCells,1);
5632   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5633   int *retPt=ret->getPointer();
5634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5636   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5637   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5638   int *pt=newConn->getPointer();
5639   int *ptI=newConnI->getPointer();
5640   ptI[0]=0;
5641   const int *oldc=_nodal_connec->getConstPointer();
5642   const int *ci=_nodal_connec_index->getConstPointer();
5643   for(int i=0;i<nbOfCells;i++,ci++)
5644     {
5645       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5646         {
5647           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5648                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5649           pt=std::copy(tmp,tmp+8,pt);
5650           ptI[1]=ptI[0]+4;
5651           ptI[2]=ptI[0]+8;
5652           *retPt++=i;
5653           *retPt++=i;
5654           ptI+=2;
5655         }
5656       else
5657         {
5658           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5659           ptI[1]=ptI[0]+ci[1]-ci[0];
5660           ptI++;
5661           *retPt++=i;
5662         }
5663     }
5664   _nodal_connec->decrRef();
5665   _nodal_connec=newConn.retn();
5666   _nodal_connec_index->decrRef();
5667   _nodal_connec_index=newConnI.retn();
5668   computeTypes();
5669   updateTime();
5670   return ret.retn();
5671 }
5672
5673 /*!
5674  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5675  */
5676 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5677 {
5678   checkConnectivityFullyDefined();
5679   if(getMeshDimension()!=2)
5680     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5681   int nbOfCells=getNumberOfCells();
5682   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5683   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5684   ret->alloc(nbOfCells+nbOfCutCells,1);
5685   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5686   int *retPt=ret->getPointer();
5687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5689   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5690   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5691   int *pt=newConn->getPointer();
5692   int *ptI=newConnI->getPointer();
5693   ptI[0]=0;
5694   const int *oldc=_nodal_connec->getConstPointer();
5695   const int *ci=_nodal_connec_index->getConstPointer();
5696   for(int i=0;i<nbOfCells;i++,ci++)
5697     {
5698       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5699         {
5700           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5701                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5702           pt=std::copy(tmp,tmp+8,pt);
5703           ptI[1]=ptI[0]+4;
5704           ptI[2]=ptI[0]+8;
5705           *retPt++=i;
5706           *retPt++=i;
5707           ptI+=2;
5708         }
5709       else
5710         {
5711           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5712           ptI[1]=ptI[0]+ci[1]-ci[0];
5713           ptI++;
5714           *retPt++=i;
5715         }
5716     }
5717   _nodal_connec->decrRef();
5718   _nodal_connec=newConn.retn();
5719   _nodal_connec_index->decrRef();
5720   _nodal_connec_index=newConnI.retn();
5721   computeTypes();
5722   updateTime();
5723   return ret.retn();
5724 }
5725
5726 /*!
5727  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5728  */
5729 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5730 {
5731   checkConnectivityFullyDefined();
5732   if(getMeshDimension()!=3)
5733     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5734   int nbOfCells=getNumberOfCells();
5735   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5736   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5737   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5738   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5739   int *retPt=ret->getPointer();
5740   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5741   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5742   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5743   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5744   int *pt=newConn->getPointer();
5745   int *ptI=newConnI->getPointer();
5746   ptI[0]=0;
5747   const int *oldc=_nodal_connec->getConstPointer();
5748   const int *ci=_nodal_connec_index->getConstPointer();
5749   for(int i=0;i<nbOfCells;i++,ci++)
5750     {
5751       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5752         {
5753           for(int j=0;j<5;j++,pt+=5,ptI++)
5754             {
5755               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5756               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];
5757               *retPt++=i;
5758               ptI[1]=ptI[0]+5;
5759             }
5760         }
5761       else
5762         {
5763           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5764           ptI[1]=ptI[0]+ci[1]-ci[0];
5765           ptI++;
5766           *retPt++=i;
5767         }
5768     }
5769   _nodal_connec->decrRef();
5770   _nodal_connec=newConn.retn();
5771   _nodal_connec_index->decrRef();
5772   _nodal_connec_index=newConnI.retn();
5773   computeTypes();
5774   updateTime();
5775   return ret.retn();
5776 }
5777
5778 /*!
5779  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5780  */
5781 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5782 {
5783   checkConnectivityFullyDefined();
5784   if(getMeshDimension()!=3)
5785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5786   int nbOfCells=getNumberOfCells();
5787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5788   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5789   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5790   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5791   int *retPt=ret->getPointer();
5792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5794   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5795   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5796   int *pt=newConn->getPointer();
5797   int *ptI=newConnI->getPointer();
5798   ptI[0]=0;
5799   const int *oldc=_nodal_connec->getConstPointer();
5800   const int *ci=_nodal_connec_index->getConstPointer();
5801   for(int i=0;i<nbOfCells;i++,ci++)
5802     {
5803       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5804         {
5805           for(int j=0;j<6;j++,pt+=5,ptI++)
5806             {
5807               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5808               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];
5809               *retPt++=i;
5810               ptI[1]=ptI[0]+5;
5811             }
5812         }
5813       else
5814         {
5815           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5816           ptI[1]=ptI[0]+ci[1]-ci[0];
5817           ptI++;
5818           *retPt++=i;
5819         }
5820     }
5821   _nodal_connec->decrRef();
5822   _nodal_connec=newConn.retn();
5823   _nodal_connec_index->decrRef();
5824   _nodal_connec_index=newConnI.retn();
5825   computeTypes();
5826   updateTime();
5827   return ret.retn();
5828 }
5829
5830 /*!
5831  * This private method is used to subdivide edges of a mesh with meshdim==2. If 'this' has no a meshdim equal to 2 an exception will be thrown.
5832  * This method completly ignore coordinates.
5833  * @param nodeSubdived is the nodal connectivity of subdivision of edges
5834  * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5835  * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5836  * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5837  */
5838 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5839 {
5840   checkFullyDefined();
5841   if(getMeshDimension()!=2)
5842     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5843   int nbOfCells=getNumberOfCells();
5844   int *connI=_nodal_connec_index->getPointer();
5845   int newConnLgth=0;
5846   for(int i=0;i<nbOfCells;i++,connI++)
5847     {
5848       int offset=descIndex[i];
5849       int nbOfEdges=descIndex[i+1]-offset;
5850       //
5851       bool ddirect=desc[offset+nbOfEdges-1]>0;
5852       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5853       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5854       for(int j=0;j<nbOfEdges;j++)
5855         {
5856           bool direct=desc[offset+j]>0;
5857           int edgeId=std::abs(desc[offset+j])-1;
5858           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5859             {
5860               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5861               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5862               int ref2=direct?id1:id2;
5863               if(ref==ref2)
5864                 {
5865                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5866                   newConnLgth+=nbOfSubNodes-1;
5867                   ref=direct?id2:id1;
5868                 }
5869               else
5870                 {
5871                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5872                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5873                 }
5874             }
5875           else
5876             {
5877               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5878             }
5879         }
5880       newConnLgth++;//+1 is for cell type
5881       connI[1]=newConnLgth;
5882     }
5883   //
5884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5885   newConn->alloc(newConnLgth,1);
5886   int *work=newConn->getPointer();
5887   for(int i=0;i<nbOfCells;i++)
5888     {
5889       *work++=INTERP_KERNEL::NORM_POLYGON;
5890       int offset=descIndex[i];
5891       int nbOfEdges=descIndex[i+1]-offset;
5892       for(int j=0;j<nbOfEdges;j++)
5893         {
5894           bool direct=desc[offset+j]>0;
5895           int edgeId=std::abs(desc[offset+j])-1;
5896           if(direct)
5897             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5898           else
5899             {
5900               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5901               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5902               work=std::copy(it,it+nbOfSubNodes-1,work);
5903             }
5904         }
5905     }
5906   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5907   _types.clear();
5908   if(nbOfCells>0)
5909     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5910 }
5911
5912 /*!
5913  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5914  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5915  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5916  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5917  * so it can be useful to call mergeNodes() before calling this method.
5918  *  \throw If \a this->getMeshDimension() <= 1.
5919  *  \throw If the coordinates array is not set.
5920  *  \throw If the nodal connectivity of cells is not defined.
5921  */
5922 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5923 {
5924   checkFullyDefined();
5925   if(getMeshDimension()<=1)
5926     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5927   int nbOfCells=getNumberOfCells();
5928   if(nbOfCells<1)
5929     return ;
5930   int initMeshLgth=getMeshLength();
5931   int *conn=_nodal_connec->getPointer();
5932   int *index=_nodal_connec_index->getPointer();
5933   int posOfCurCell=0;
5934   int newPos=0;
5935   int lgthOfCurCell;
5936   for(int i=0;i<nbOfCells;i++)
5937     {
5938       lgthOfCurCell=index[i+1]-posOfCurCell;
5939       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5940       int newLgth;
5941       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5942                                                                                                      conn+newPos+1,newLgth);
5943       conn[newPos]=newType;
5944       newPos+=newLgth+1;
5945       posOfCurCell=index[i+1];
5946       index[i+1]=newPos;
5947     }
5948   if(newPos!=initMeshLgth)
5949     _nodal_connec->reAlloc(newPos);
5950   computeTypes();
5951 }
5952
5953 /*!
5954  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5955  * A cell is considered to be oriented correctly if an angle between its
5956  * normal vector and a given vector is less than \c PI / \c 2.
5957  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5958  *         cells. 
5959  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5960  *         checked.
5961  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5962  *         is not cleared before filling in.
5963  *  \throw If \a this->getMeshDimension() != 2.
5964  *  \throw If \a this->getSpaceDimension() != 3.
5965  *
5966  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5967  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5968  */
5969 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5970 {
5971   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5972     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5973   int nbOfCells=getNumberOfCells();
5974   const int *conn=_nodal_connec->getConstPointer();
5975   const int *connI=_nodal_connec_index->getConstPointer();
5976   const double *coordsPtr=_coords->getConstPointer();
5977   for(int i=0;i<nbOfCells;i++)
5978     {
5979       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5980       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5981         {
5982           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5983           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5984             cells.push_back(i);
5985         }
5986     }
5987 }
5988
5989 /*!
5990  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5991  * considered to be oriented correctly if an angle between its normal vector and a
5992  * given vector is less than \c PI / \c 2. 
5993  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5994  *         cells. 
5995  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5996  *         checked.
5997  *  \throw If \a this->getMeshDimension() != 2.
5998  *  \throw If \a this->getSpaceDimension() != 3.
5999  *
6000  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6001  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6002  */
6003 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
6004 {
6005   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6006     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6007   int nbOfCells=getNumberOfCells();
6008   int *conn=_nodal_connec->getPointer();
6009   const int *connI=_nodal_connec_index->getConstPointer();
6010   const double *coordsPtr=_coords->getConstPointer();
6011   bool isModified=false;
6012   for(int i=0;i<nbOfCells;i++)
6013     {
6014       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6015       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6016         {
6017           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6018           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6019             {
6020               isModified=true;
6021               std::vector<int> tmp(connI[i+1]-connI[i]-2);
6022               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
6023               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
6024             }
6025         }
6026     }
6027   if(isModified)
6028     _nodal_connec->declareAsNew();
6029   updateTime();
6030 }
6031
6032 /*!
6033  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6034  * oriented facets. The normal vector of the facet should point out of the cell.
6035  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6036  *         is not cleared before filling in.
6037  *  \throw If \a this->getMeshDimension() != 3.
6038  *  \throw If \a this->getSpaceDimension() != 3.
6039  *  \throw If the coordinates array is not set.
6040  *  \throw If the nodal connectivity of cells is not defined.
6041  *
6042  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6043  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6044  */
6045 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
6046 {
6047   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6048     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6049   int nbOfCells=getNumberOfCells();
6050   const int *conn=_nodal_connec->getConstPointer();
6051   const int *connI=_nodal_connec_index->getConstPointer();
6052   const double *coordsPtr=_coords->getConstPointer();
6053   for(int i=0;i<nbOfCells;i++)
6054     {
6055       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6056       if(type==INTERP_KERNEL::NORM_POLYHED)
6057         {
6058           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6059             cells.push_back(i);
6060         }
6061     }
6062 }
6063
6064 /*!
6065  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6066  * out of the cell. 
6067  *  \throw If \a this->getMeshDimension() != 3.
6068  *  \throw If \a this->getSpaceDimension() != 3.
6069  *  \throw If the coordinates array is not set.
6070  *  \throw If the nodal connectivity of cells is not defined.
6071  *  \throw If the reparation fails.
6072  *
6073  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6074  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6075  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6076  */
6077 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
6078 {
6079   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6080     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6081   int nbOfCells=getNumberOfCells();
6082   int *conn=_nodal_connec->getPointer();
6083   const int *connI=_nodal_connec_index->getConstPointer();
6084   const double *coordsPtr=_coords->getConstPointer();
6085   for(int i=0;i<nbOfCells;i++)
6086     {
6087       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6088       if(type==INTERP_KERNEL::NORM_POLYHED)
6089         {
6090           try
6091             {
6092               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6093                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6094             }
6095           catch(INTERP_KERNEL::Exception& e)
6096             {
6097               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6098               throw INTERP_KERNEL::Exception(oss.str().c_str());
6099             }
6100         }
6101     }
6102   updateTime();
6103 }
6104
6105 /*!
6106  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6107  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6108  * according to which the first facet of the cell should be oriented to have the normal vector
6109  * pointing out of cell.
6110  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6111  *         cells. The caller is to delete this array using decrRef() as it is no more
6112  *         needed. 
6113  *  \throw If \a this->getMeshDimension() != 3.
6114  *  \throw If \a this->getSpaceDimension() != 3.
6115  *  \throw If the coordinates array is not set.
6116  *  \throw If the nodal connectivity of cells is not defined.
6117  *
6118  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6119  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6120  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6121  */
6122 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
6123 {
6124   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6125   if(getMeshDimension()!=3)
6126     throw INTERP_KERNEL::Exception(msg);
6127   int spaceDim=getSpaceDimension();
6128   if(spaceDim!=3)
6129     throw INTERP_KERNEL::Exception(msg);
6130   //
6131   int nbOfCells=getNumberOfCells();
6132   int *conn=_nodal_connec->getPointer();
6133   const int *connI=_nodal_connec_index->getConstPointer();
6134   const double *coo=getCoords()->getConstPointer();
6135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6136   for(int i=0;i<nbOfCells;i++)
6137     {
6138       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6139       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6140         {
6141           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6142             {
6143               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6144               cells->pushBackSilent(i);
6145             }
6146         }
6147     }
6148   return cells.retn();
6149 }
6150
6151 /*!
6152  * This method is a faster method to correct orientation of all 3D cells in \a this.
6153  * 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.
6154  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6155  * 
6156  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6157  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6158  */
6159 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
6160 {
6161   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6162     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6163   int nbOfCells=getNumberOfCells();
6164   int *conn=_nodal_connec->getPointer();
6165   const int *connI=_nodal_connec_index->getConstPointer();
6166   const double *coordsPtr=_coords->getConstPointer();
6167   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6168   for(int i=0;i<nbOfCells;i++)
6169     {
6170       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6171       switch(type)
6172         {
6173         case INTERP_KERNEL::NORM_TETRA4:
6174           {
6175             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6176               {
6177                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6178                 ret->pushBackSilent(i);
6179               }
6180             break;
6181           }
6182         case INTERP_KERNEL::NORM_PYRA5:
6183           {
6184             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6185               {
6186                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6187                 ret->pushBackSilent(i);
6188               }
6189             break;
6190           }
6191         case INTERP_KERNEL::NORM_PENTA6:
6192         case INTERP_KERNEL::NORM_HEXA8:
6193         case INTERP_KERNEL::NORM_HEXGP12:
6194           {
6195             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6196               {
6197                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6198                 ret->pushBackSilent(i);
6199               }
6200             break;
6201           }
6202         case INTERP_KERNEL::NORM_POLYHED:
6203           {
6204             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6205               {
6206                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6207                 ret->pushBackSilent(i);
6208               }
6209             break;
6210           }
6211         default:
6212           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 !");
6213         }
6214     }
6215   updateTime();
6216   return ret.retn();
6217 }
6218
6219 /*!
6220  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6221  * If it is not the case an exception will be thrown.
6222  * This method is fast because the first cell of 'this' is used to compute the plane.
6223  * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6224  * @param pos output of size at least 3 used to store a point owned of searched plane.
6225  */
6226 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
6227 {
6228   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6229     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6230   const int *conn=_nodal_connec->getConstPointer();
6231   const int *connI=_nodal_connec_index->getConstPointer();
6232   const double *coordsPtr=_coords->getConstPointer();
6233   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6234   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6235 }
6236
6237 /*!
6238  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6239  * cells. Currently cells of the following types are treated:
6240  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6241  * For a cell of other type an exception is thrown.
6242  * Space dimension of a 2D mesh can be either 2 or 3.
6243  * The Edge Ratio of a cell \f$t\f$ is: 
6244  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6245  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6246  *  the smallest edge lengths of \f$t\f$.
6247  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6248  *          cells and one time, lying on \a this mesh. The caller is to delete this
6249  *          field using decrRef() as it is no more needed. 
6250  *  \throw If the coordinates array is not set.
6251  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6252  *  \throw If the connectivity data array has more than one component.
6253  *  \throw If the connectivity data array has a named component.
6254  *  \throw If the connectivity index data array has more than one component.
6255  *  \throw If the connectivity index data array has a named component.
6256  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6257  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6258  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6259  */
6260 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
6261 {
6262   checkCoherency();
6263   int spaceDim=getSpaceDimension();
6264   int meshDim=getMeshDimension();
6265   if(spaceDim!=2 && spaceDim!=3)
6266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6267   if(meshDim!=2 && meshDim!=3)
6268     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6269   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6270   ret->setMesh(this);
6271   int nbOfCells=getNumberOfCells();
6272   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6273   arr->alloc(nbOfCells,1);
6274   double *pt=arr->getPointer();
6275   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6276   const int *conn=_nodal_connec->getConstPointer();
6277   const int *connI=_nodal_connec_index->getConstPointer();
6278   const double *coo=_coords->getConstPointer();
6279   double tmp[12];
6280   for(int i=0;i<nbOfCells;i++,pt++)
6281     {
6282       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6283       switch(t)
6284         {
6285           case INTERP_KERNEL::NORM_TRI3:
6286             {
6287               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6288               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6289               break;
6290             }
6291           case INTERP_KERNEL::NORM_QUAD4:
6292             {
6293               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6294               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6295               break;
6296             }
6297           case INTERP_KERNEL::NORM_TETRA4:
6298             {
6299               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6300               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6301               break;
6302             }
6303         default:
6304           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6305         }
6306       conn+=connI[i+1]-connI[i];
6307     }
6308   ret->setName("EdgeRatio");
6309   ret->synchronizeTimeWithSupport();
6310   return ret.retn();
6311 }
6312
6313 /*!
6314  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6315  * cells. Currently cells of the following types are treated:
6316  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6317  * For a cell of other type an exception is thrown.
6318  * Space dimension of a 2D mesh can be either 2 or 3.
6319  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6320  *          cells and one time, lying on \a this mesh. The caller is to delete this
6321  *          field using decrRef() as it is no more needed. 
6322  *  \throw If the coordinates array is not set.
6323  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6324  *  \throw If the connectivity data array has more than one component.
6325  *  \throw If the connectivity data array has a named component.
6326  *  \throw If the connectivity index data array has more than one component.
6327  *  \throw If the connectivity index data array has a named component.
6328  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6329  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6330  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6331  */
6332 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6333 {
6334   checkCoherency();
6335   int spaceDim=getSpaceDimension();
6336   int meshDim=getMeshDimension();
6337   if(spaceDim!=2 && spaceDim!=3)
6338     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6339   if(meshDim!=2 && meshDim!=3)
6340     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6341   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6342   ret->setMesh(this);
6343   int nbOfCells=getNumberOfCells();
6344   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6345   arr->alloc(nbOfCells,1);
6346   double *pt=arr->getPointer();
6347   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6348   const int *conn=_nodal_connec->getConstPointer();
6349   const int *connI=_nodal_connec_index->getConstPointer();
6350   const double *coo=_coords->getConstPointer();
6351   double tmp[12];
6352   for(int i=0;i<nbOfCells;i++,pt++)
6353     {
6354       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6355       switch(t)
6356         {
6357           case INTERP_KERNEL::NORM_TRI3:
6358             {
6359               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6360               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6361               break;
6362             }
6363           case INTERP_KERNEL::NORM_QUAD4:
6364             {
6365               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6366               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6367               break;
6368             }
6369           case INTERP_KERNEL::NORM_TETRA4:
6370             {
6371               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6372               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6373               break;
6374             }
6375         default:
6376           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6377         }
6378       conn+=connI[i+1]-connI[i];
6379     }
6380   ret->setName("AspectRatio");
6381   ret->synchronizeTimeWithSupport();
6382   return ret.retn();
6383 }
6384
6385 /*!
6386  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6387  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6388  * treated: INTERP_KERNEL::NORM_QUAD4.
6389  * For a cell of other type an exception is thrown.
6390  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6391  *          cells and one time, lying on \a this mesh. The caller is to delete this
6392  *          field using decrRef() as it is no more needed. 
6393  *  \throw If the coordinates array is not set.
6394  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6395  *  \throw If the connectivity data array has more than one component.
6396  *  \throw If the connectivity data array has a named component.
6397  *  \throw If the connectivity index data array has more than one component.
6398  *  \throw If the connectivity index data array has a named component.
6399  *  \throw If \a this->getMeshDimension() != 2.
6400  *  \throw If \a this->getSpaceDimension() != 3.
6401  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6402  */
6403 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6404 {
6405   checkCoherency();
6406   int spaceDim=getSpaceDimension();
6407   int meshDim=getMeshDimension();
6408   if(spaceDim!=3)
6409     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6410   if(meshDim!=2)
6411     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6412   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6413   ret->setMesh(this);
6414   int nbOfCells=getNumberOfCells();
6415   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6416   arr->alloc(nbOfCells,1);
6417   double *pt=arr->getPointer();
6418   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6419   const int *conn=_nodal_connec->getConstPointer();
6420   const int *connI=_nodal_connec_index->getConstPointer();
6421   const double *coo=_coords->getConstPointer();
6422   double tmp[12];
6423   for(int i=0;i<nbOfCells;i++,pt++)
6424     {
6425       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6426       switch(t)
6427         {
6428           case INTERP_KERNEL::NORM_QUAD4:
6429             {
6430               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6431               *pt=INTERP_KERNEL::quadWarp(tmp);
6432               break;
6433             }
6434         default:
6435           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6436         }
6437       conn+=connI[i+1]-connI[i];
6438     }
6439   ret->setName("Warp");
6440   ret->synchronizeTimeWithSupport();
6441   return ret.retn();
6442 }
6443
6444
6445 /*!
6446  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6447  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6448  * treated: INTERP_KERNEL::NORM_QUAD4.
6449  * For a cell of other type an exception is thrown.
6450  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6451  *          cells and one time, lying on \a this mesh. The caller is to delete this
6452  *          field using decrRef() as it is no more needed. 
6453  *  \throw If the coordinates array is not set.
6454  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6455  *  \throw If the connectivity data array has more than one component.
6456  *  \throw If the connectivity data array has a named component.
6457  *  \throw If the connectivity index data array has more than one component.
6458  *  \throw If the connectivity index data array has a named component.
6459  *  \throw If \a this->getMeshDimension() != 2.
6460  *  \throw If \a this->getSpaceDimension() != 3.
6461  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6462  */
6463 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6464 {
6465   checkCoherency();
6466   int spaceDim=getSpaceDimension();
6467   int meshDim=getMeshDimension();
6468   if(spaceDim!=3)
6469     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6470   if(meshDim!=2)
6471     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6472   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6473   ret->setMesh(this);
6474   int nbOfCells=getNumberOfCells();
6475   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6476   arr->alloc(nbOfCells,1);
6477   double *pt=arr->getPointer();
6478   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6479   const int *conn=_nodal_connec->getConstPointer();
6480   const int *connI=_nodal_connec_index->getConstPointer();
6481   const double *coo=_coords->getConstPointer();
6482   double tmp[12];
6483   for(int i=0;i<nbOfCells;i++,pt++)
6484     {
6485       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6486       switch(t)
6487         {
6488           case INTERP_KERNEL::NORM_QUAD4:
6489             {
6490               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6491               *pt=INTERP_KERNEL::quadSkew(tmp);
6492               break;
6493             }
6494         default:
6495           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6496         }
6497       conn+=connI[i+1]-connI[i];
6498     }
6499   ret->setName("Skew");
6500   ret->synchronizeTimeWithSupport();
6501   return ret.retn();
6502 }
6503
6504 /*!
6505  * This method aggregate the bbox of each cell and put it into bbox parameter.
6506  * @param bbox out parameter of size 2*spacedim*nbOfcells.
6507  */
6508 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6509 {
6510   int spaceDim=getSpaceDimension();
6511   int nbOfCells=getNumberOfCells();
6512   bbox.resize(2*nbOfCells*spaceDim);
6513   for(int i=0;i<nbOfCells*spaceDim;i++)
6514     {
6515       bbox[2*i]=std::numeric_limits<double>::max();
6516       bbox[2*i+1]=-std::numeric_limits<double>::max();
6517     }
6518   const double *coordsPtr=_coords->getConstPointer();
6519   const int *conn=_nodal_connec->getConstPointer();
6520   const int *connI=_nodal_connec_index->getConstPointer();
6521   for(int i=0;i<nbOfCells;i++)
6522     {
6523       int offset=connI[i]+1;
6524       int nbOfNodesForCell=connI[i+1]-offset;
6525       for(int j=0;j<nbOfNodesForCell;j++)
6526         {
6527           int nodeId=conn[offset+j];
6528           if(nodeId>=0)
6529             for(int k=0;k<spaceDim;k++)
6530               {
6531                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6532                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6533               }
6534         }
6535     }
6536 }
6537
6538 /// @cond INTERNAL
6539
6540 namespace ParaMEDMEMImpl
6541 {
6542   class ConnReader
6543   {
6544   public:
6545     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6546     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6547   private:
6548     const int *_conn;
6549     int _val;
6550   };
6551
6552   class ConnReader2
6553   {
6554   public:
6555     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6556     bool operator() (const int& pos) { return _conn[pos]==_val; }
6557   private:
6558     const int *_conn;
6559     int _val;
6560   };
6561 }
6562
6563 /// @endcond
6564
6565 /*!
6566  * This method expects that 'this' is sorted by types. If not an exception will be thrown.
6567  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6568  * 'this' is composed in cell types.
6569  * The returned array is of size 3*n where n is the number of different types present in 'this'. 
6570  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6571  * This parameter is kept only for compatibility with other methode listed above.
6572  */
6573 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6574 {
6575   checkConnectivityFullyDefined();
6576   const int *conn=_nodal_connec->getConstPointer();
6577   const int *connI=_nodal_connec_index->getConstPointer();
6578   const int *work=connI;
6579   int nbOfCells=getNumberOfCells();
6580   std::size_t n=getAllTypes().size();
6581   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6582   std::set<INTERP_KERNEL::NormalizedCellType> types;
6583   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6584     {
6585       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6586       if(types.find(typ)!=types.end())
6587         {
6588           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6589           oss << " is not contiguous !";
6590           throw INTERP_KERNEL::Exception(oss.str().c_str());
6591         }
6592       types.insert(typ);
6593       ret[3*i]=typ;
6594       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6595       ret[3*i+1]=(int)std::distance(work,work2);
6596       work=work2;
6597     }
6598   return ret;
6599 }
6600
6601 /*!
6602  * This method is used to check that this has contiguous cell type in same order than described in 'code'.
6603  * only for types cell, type node is not managed.
6604  * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
6605  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6606  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6607  * If 2 or more same geometric type is in 'code' and exception is thrown too.
6608  *
6609  * This method firstly checks
6610  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6611  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6612  * an exception is thrown too.
6613  * 
6614  * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
6615  * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown 
6616  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6617  */
6618 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6619 {
6620   if(code.empty())
6621     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6622   std::size_t sz=code.size();
6623   std::size_t n=sz/3;
6624   if(sz%3!=0)
6625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6626   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6627   int nb=0;
6628   for(std::size_t i=0;i<n;i++)
6629     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6630       {
6631         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6632         nb+=code[3*i+1];
6633         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6634           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6635       }
6636   if(types.size()!=n)
6637     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6638   if(idsPerType.empty())
6639     {
6640       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6641         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6642       if(types.size()==_types.size())
6643         return 0;
6644     }
6645   DataArrayInt *ret=DataArrayInt::New();
6646   ret->alloc(nb,1);
6647   int *retPtr=ret->getPointer();
6648   const int *connI=_nodal_connec_index->getConstPointer();
6649   const int *conn=_nodal_connec->getConstPointer();
6650   int nbOfCells=getNumberOfCells();
6651   const int *i=connI;
6652   int kk=0;
6653   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6654     {
6655       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6656       int offset=(int)std::distance(connI,i);
6657       if(code[3*kk+2]==-1)
6658         {
6659           const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6660           std::size_t pos2=std::distance(i,j);
6661           for(std::size_t k=0;k<pos2;k++)
6662             *retPtr++=(int)k+offset;
6663           i=j;
6664         }
6665       else
6666         {
6667           retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6668                                 retPtr,std::bind2nd(std::plus<int>(),offset));
6669         }
6670     }
6671   return ret;
6672 }
6673
6674 /*!
6675  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6676  * 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.
6677  * 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.
6678  * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
6679  * 
6680  * @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.
6681  * @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,
6682  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6683  * @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.
6684  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6685  * @throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
6686  */
6687 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6688 {
6689   if(profile->getNumberOfComponents()!=1)
6690     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6691   checkConnectivityFullyDefined();
6692   const int *conn=_nodal_connec->getConstPointer();
6693   const int *connI=_nodal_connec_index->getConstPointer();
6694   int nbOfCells=getNumberOfCells();
6695   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6696   std::vector<int> typeRangeVals(1);
6697   for(const int *i=connI;i!=connI+nbOfCells;)
6698     {
6699       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6700       if(std::find(types.begin(),types.end(),curType)!=types.end())
6701         {
6702           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6703         }
6704       types.push_back(curType);
6705       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6706       typeRangeVals.push_back((int)std::distance(connI,i));
6707     }
6708   //
6709   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6710   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6711   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6712   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6714   //
6715   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6716   code.resize(3*nbOfCastsFinal);
6717   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6718   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6719   for(int i=0;i<nbOfCastsFinal;i++)
6720     {
6721       int castId=castsPresent->getIJ(i,0);
6722       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6723       idsInPflPerType2.push_back(tmp3);
6724       code[3*i]=(int)types[castId];
6725       code[3*i+1]=tmp3->getNumberOfTuples();
6726       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6727       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6728         {
6729           tmp4->copyStringInfoFrom(*profile);
6730           idsPerType2.push_back(tmp4);
6731           code[3*i+2]=(int)idsPerType2.size()-1;
6732         }
6733       else
6734         {
6735           code[3*i+2]=-1;
6736         }
6737     }
6738   std::size_t sz2=idsInPflPerType2.size();
6739   idsInPflPerType.resize(sz2);
6740   for(std::size_t i=0;i<sz2;i++)
6741     {
6742       DataArrayInt *locDa=idsInPflPerType2[i];
6743       locDa->incrRef();
6744       idsInPflPerType[i]=locDa;
6745     }
6746   std::size_t sz=idsPerType2.size();
6747   idsPerType.resize(sz);
6748   for(std::size_t i=0;i<sz;i++)
6749     {
6750       DataArrayInt *locDa=idsPerType2[i];
6751       locDa->incrRef();
6752       idsPerType[i]=locDa;
6753     }
6754 }
6755
6756 /*!
6757  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6758  * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6759  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6760  * 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.
6761  */
6762 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6763 {
6764   checkFullyDefined();
6765   nM1LevMesh->checkFullyDefined();
6766   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6767     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6768   if(_coords!=nM1LevMesh->getCoords())
6769     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6771   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6772   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6773   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6774   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6775   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6776   tmp->setConnectivity(tmp0,tmp1);
6777   tmp->renumberCells(ret0->getConstPointer(),false);
6778   revDesc=tmp->getNodalConnectivity();
6779   revDescIndx=tmp->getNodalConnectivityIndex();
6780   DataArrayInt *ret=0;
6781   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6782     {
6783       int tmp2;
6784       ret->getMaxValue(tmp2);
6785       ret->decrRef();
6786       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6787       throw INTERP_KERNEL::Exception(oss.str().c_str());
6788     }
6789   nM1LevMeshIds=ret;
6790   //
6791   revDesc->incrRef();
6792   revDescIndx->incrRef();
6793   ret1->incrRef();
6794   ret0->incrRef();
6795   meshnM1Old2New=ret0;
6796   return ret1;
6797 }
6798
6799 /*!
6800  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6801  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6802  * in "Old to New" mode.
6803  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6804  *          this array using decrRef() as it is no more needed.
6805  *  \throw If the nodal connectivity of cells is not defined.
6806  */
6807 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6808 {
6809   checkConnectivityFullyDefined();
6810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6811   renumberCells(ret->getConstPointer(),false);
6812   return ret.retn();
6813 }
6814
6815 /*!
6816  * This methods checks that cells are sorted by their types.
6817  * This method makes asumption (no check) that connectivity is correctly set before calling.
6818  */
6819 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6820 {
6821   checkFullyDefined();
6822   const int *conn=_nodal_connec->getConstPointer();
6823   const int *connI=_nodal_connec_index->getConstPointer();
6824   int nbOfCells=getNumberOfCells();
6825   std::set<INTERP_KERNEL::NormalizedCellType> types;
6826   for(const int *i=connI;i!=connI+nbOfCells;)
6827     {
6828       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6829       if(types.find(curType)!=types.end())
6830         return false;
6831       types.insert(curType);
6832       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6833     }
6834   return true;
6835 }
6836
6837 /*!
6838  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6839  * The geometric type order is specified by MED file.
6840  * 
6841  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6842  */
6843 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6844 {
6845   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6846 }
6847
6848 /*!
6849  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6850  * that the order is specified in array defined by [orderBg,orderEnd).
6851  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6852  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6853  */
6854 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6855 {
6856   checkFullyDefined();
6857   const int *conn=_nodal_connec->getConstPointer();
6858   const int *connI=_nodal_connec_index->getConstPointer();
6859   int nbOfCells=getNumberOfCells();
6860   if(nbOfCells==0)
6861     return true;
6862   int lastPos=-1;
6863   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6864   for(const int *i=connI;i!=connI+nbOfCells;)
6865     {
6866       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6867       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6868       if(isTypeExists!=orderEnd)
6869         {
6870           int pos=(int)std::distance(orderBg,isTypeExists);
6871           if(pos<=lastPos)
6872             return false;
6873           lastPos=pos;
6874           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6875         }
6876       else
6877         {
6878           if(sg.find(curType)==sg.end())
6879             {
6880               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6881               sg.insert(curType);
6882             }
6883           else
6884             return false;
6885         }
6886     }
6887   return true;
6888 }
6889
6890 /*!
6891  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6892  * 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
6893  * 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'.
6894  */
6895 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6896 {
6897   checkConnectivityFullyDefined();
6898   int nbOfCells=getNumberOfCells();
6899   const int *conn=_nodal_connec->getConstPointer();
6900   const int *connI=_nodal_connec_index->getConstPointer();
6901   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6902   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6903   tmpa->alloc(nbOfCells,1);
6904   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6905   tmpb->fillWithZero();
6906   int *tmp=tmpa->getPointer();
6907   int *tmp2=tmpb->getPointer();
6908   for(const int *i=connI;i!=connI+nbOfCells;i++)
6909     {
6910       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6911       if(where!=orderEnd)
6912         {
6913           int pos=(int)std::distance(orderBg,where);
6914           tmp2[pos]++;
6915           tmp[std::distance(connI,i)]=pos;
6916         }
6917       else
6918         {
6919           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6920           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6921           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6922           throw INTERP_KERNEL::Exception(oss.str().c_str());
6923         }
6924     }
6925   nbPerType=tmpb.retn();
6926   return tmpa.retn();
6927 }
6928
6929 /*!
6930  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6931  *
6932  * \return a new object containing the old to new correspondance.
6933  *
6934  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6935  */
6936 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6937 {
6938   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6939 }
6940
6941 /*!
6942  * 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 'this'.
6943  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6944  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6945  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6946  */
6947 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6948 {
6949   DataArrayInt *nbPerType=0;
6950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6951   nbPerType->decrRef();
6952   return tmpa->buildPermArrPerLevel();
6953 }
6954
6955 /*!
6956  * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
6957  * The number of cells remains unchanged after the call of this method.
6958  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6959  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6960  *
6961  * @return the array giving the correspondance old to new.
6962  */
6963 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6964 {
6965   checkFullyDefined();
6966   computeTypes();
6967   const int *conn=_nodal_connec->getConstPointer();
6968   const int *connI=_nodal_connec_index->getConstPointer();
6969   int nbOfCells=getNumberOfCells();
6970   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6971   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6972     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6973       {
6974         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6975         types.push_back(curType);
6976         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6977       }
6978   DataArrayInt *ret=DataArrayInt::New();
6979   ret->alloc(nbOfCells,1);
6980   int *retPtr=ret->getPointer();
6981   std::fill(retPtr,retPtr+nbOfCells,-1);
6982   int newCellId=0;
6983   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6984     {
6985       for(const int *i=connI;i!=connI+nbOfCells;i++)
6986         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6987           retPtr[std::distance(connI,i)]=newCellId++;
6988     }
6989   renumberCells(retPtr,false);
6990   return ret;
6991 }
6992
6993 /*!
6994  * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
6995  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6996  * This method makes asumption that connectivity is correctly set before calling.
6997  */
6998 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6999 {
7000   checkFullyDefined();
7001   const int *conn=_nodal_connec->getConstPointer();
7002   const int *connI=_nodal_connec_index->getConstPointer();
7003   int nbOfCells=getNumberOfCells();
7004   std::vector<MEDCouplingUMesh *> ret;
7005   for(const int *i=connI;i!=connI+nbOfCells;)
7006     {
7007       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7008       int beginCellId=(int)std::distance(connI,i);
7009       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7010       int endCellId=(int)std::distance(connI,i);
7011       int sz=endCellId-beginCellId;
7012       int *cells=new int[sz];
7013       for(int j=0;j<sz;j++)
7014         cells[j]=beginCellId+j;
7015       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7016       delete [] cells;
7017       ret.push_back(m);
7018     }
7019   return ret;
7020 }
7021
7022 /*!
7023  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7024  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7025  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7026  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7027  * are not used here to avoid the build of big permutation array.
7028  *
7029  * \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
7030  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7031  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7032  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7033  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7034  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7035  * \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
7036  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7037  */
7038 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7039                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7040                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7041 {
7042   std::vector<const MEDCouplingUMesh *> ms2;
7043   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7044     if(*it)
7045       {
7046         (*it)->checkConnectivityFullyDefined();
7047         ms2.push_back(*it);
7048       }
7049   if(ms2.empty())
7050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7051   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7052   int meshDim=ms2[0]->getMeshDimension();
7053   std::vector<const MEDCouplingUMesh *> m1ssm;
7054   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7055   //
7056   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7057   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7058   int fake=0,rk=0;
7059   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7060   ret1->alloc(0,1); ret2->alloc(0,1);
7061   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7062     {
7063       if(meshDim!=(*it)->getMeshDimension())
7064         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7065       if(refCoo!=(*it)->getCoords())
7066         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7067       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7068       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7069       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7070       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7071         {
7072           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7073           m1ssmSingleAuto.push_back(singleCell);
7074           m1ssmSingle.push_back(singleCell);
7075           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7076         }
7077     }
7078   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7079   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7080   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7081   for(std::size_t i=0;i<m1ssm.size();i++)
7082     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7083   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7084   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7085   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7086   return ret0.retn();
7087 }
7088
7089 /*!
7090  * This method returns a newly created DataArrayInt instance.
7091  * This method retrieves cell ids in [begin,end) that have the type 'type'.
7092  */
7093 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
7094 {
7095   checkFullyDefined();
7096   const int *conn=_nodal_connec->getConstPointer();
7097   const int *connIndex=_nodal_connec_index->getConstPointer();
7098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7099   for(const int *w=begin;w!=end;w++)
7100     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7101       ret->pushBackSilent(*w);
7102   return ret.retn();
7103 }
7104
7105 /*!
7106  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7107  * are in [0:getNumberOfCells())
7108  */
7109 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
7110 {
7111   checkFullyDefined();
7112   const int *conn=_nodal_connec->getConstPointer();
7113   const int *connI=_nodal_connec_index->getConstPointer();
7114   int nbOfCells=getNumberOfCells();
7115   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
7116   int *tmp=new int[nbOfCells];
7117   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7118     {
7119       int j=0;
7120       for(const int *i=connI;i!=connI+nbOfCells;i++)
7121         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7122           tmp[std::distance(connI,i)]=j++;
7123     }
7124   DataArrayInt *ret=DataArrayInt::New();
7125   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7126   ret->copyStringInfoFrom(*da);
7127   int *retPtr=ret->getPointer();
7128   const int *daPtr=da->getConstPointer();
7129   int nbOfElems=da->getNbOfElems();
7130   for(int k=0;k<nbOfElems;k++)
7131     retPtr[k]=tmp[daPtr[k]];
7132   delete [] tmp;
7133   return ret;
7134 }
7135
7136 /*!
7137  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7138  * This method \b works \b for mesh sorted by type.
7139  * cells whose ids is in 'idsPerGeoType' array.
7140  * This method conserves coords and name of mesh.
7141  */
7142 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7143 {
7144   std::vector<int> code=getDistributionOfTypes();
7145   std::size_t nOfTypesInThis=code.size()/3;
7146   int sz=0,szOfType=0;
7147   for(std::size_t i=0;i<nOfTypesInThis;i++)
7148     {
7149       if(code[3*i]!=type)
7150         sz+=code[3*i+1];
7151       else
7152         szOfType=code[3*i+1];
7153     }
7154   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7155     if(*work<0 || *work>=szOfType)
7156       {
7157         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7158         oss << ". It should be in [0," << szOfType << ") !";
7159         throw INTERP_KERNEL::Exception(oss.str().c_str());
7160       }
7161   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7162   int *idsPtr=idsTokeep->getPointer();
7163   int offset=0;
7164   for(std::size_t i=0;i<nOfTypesInThis;i++)
7165     {
7166       if(code[3*i]!=type)
7167         for(int j=0;j<code[3*i+1];j++)
7168           *idsPtr++=offset+j;
7169       else
7170         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7171       offset+=code[3*i+1];
7172     }
7173   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7174   ret->copyTinyInfoFrom(this);
7175   return ret.retn();
7176 }
7177
7178 /*!
7179  * This method returns a vector of size 'this->getNumberOfCells()'.
7180  * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
7181  */
7182 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7183 {
7184   int ncell=getNumberOfCells();
7185   std::vector<bool> ret(ncell);
7186   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7187   const int *c=getNodalConnectivity()->getConstPointer();
7188   for(int i=0;i<ncell;i++)
7189     {
7190       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7191       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7192       ret[i]=cm.isQuadratic();
7193     }
7194   return ret;
7195 }
7196
7197 /*!
7198  * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
7199  */
7200 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7201 {
7202   if(other->getType()!=UNSTRUCTURED)
7203     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7204   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7205   return MergeUMeshes(this,otherC);
7206 }
7207
7208 /*!
7209  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7210  * computed by averaging coordinates of cell nodes, so this method is not a right
7211  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7212  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7213  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7214  *          components. The caller is to delete this array using decrRef() as it is
7215  *          no more needed.
7216  *  \throw If the coordinates array is not set.
7217  *  \throw If the nodal connectivity of cells is not defined.
7218  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7219  */
7220 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7221 {
7222   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7223   int spaceDim=getSpaceDimension();
7224   int nbOfCells=getNumberOfCells();
7225   ret->alloc(nbOfCells,spaceDim);
7226   ret->copyStringInfoFrom(*getCoords());
7227   double *ptToFill=ret->getPointer();
7228   const int *nodal=_nodal_connec->getConstPointer();
7229   const int *nodalI=_nodal_connec_index->getConstPointer();
7230   const double *coor=_coords->getConstPointer();
7231   for(int i=0;i<nbOfCells;i++)
7232     {
7233       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7234       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7235       ptToFill+=spaceDim;
7236     }
7237   return ret.retn();
7238 }
7239
7240 /*!
7241  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7242  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7243  * 
7244  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7245  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7246  * 
7247  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7248  * \throw If \a this is not fully defined (coordinates and connectivity)
7249  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7250  */
7251 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7252 {
7253   checkFullyDefined();
7254   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7255   int spaceDim=getSpaceDimension();
7256   int nbOfCells=getNumberOfCells();
7257   int nbOfNodes=getNumberOfNodes();
7258   ret->alloc(nbOfCells,spaceDim);
7259   double *ptToFill=ret->getPointer();
7260   const int *nodal=_nodal_connec->getConstPointer();
7261   const int *nodalI=_nodal_connec_index->getConstPointer();
7262   const double *coor=_coords->getConstPointer();
7263   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7264     {
7265       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7266       std::fill(ptToFill,ptToFill+spaceDim,0.);
7267       if(type!=INTERP_KERNEL::NORM_POLYHED)
7268         {
7269           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7270             {
7271               if(*conn>=0 && *conn<nbOfNodes)
7272                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7273               else
7274                 {
7275                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7276                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7277                 }
7278             }
7279           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7280           if(nbOfNodesInCell>0)
7281             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7282           else
7283             {
7284               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7285               throw INTERP_KERNEL::Exception(oss.str().c_str());
7286             }
7287         }
7288       else
7289         {
7290           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7291           s.erase(-1);
7292           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7293             {
7294               if(*it>=0 && *it<nbOfNodes)
7295                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7296               else
7297                 {
7298                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7299                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7300                 }
7301             }
7302           if(!s.empty())
7303             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7304           else
7305             {
7306               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7307               throw INTERP_KERNEL::Exception(oss.str().c_str());
7308             }
7309         }
7310     }
7311   return ret.retn();
7312 }
7313
7314 /*!
7315  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7316  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7317  * are specified via an array of cell ids. 
7318  *  \warning Validity of the specified cell ids is not checked! 
7319  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7320  *  \param [in] begin - an array of cell ids of interest.
7321  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7322  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7323  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7324  *          caller is to delete this array using decrRef() as it is no more needed. 
7325  *  \throw If the coordinates array is not set.
7326  *  \throw If the nodal connectivity of cells is not defined.
7327  *
7328  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7329  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7330  */
7331 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7332 {
7333   DataArrayDouble *ret=DataArrayDouble::New();
7334   int spaceDim=getSpaceDimension();
7335   int nbOfTuple=(int)std::distance(begin,end);
7336   ret->alloc(nbOfTuple,spaceDim);
7337   double *ptToFill=ret->getPointer();
7338   double *tmp=new double[spaceDim];
7339   const int *nodal=_nodal_connec->getConstPointer();
7340   const int *nodalI=_nodal_connec_index->getConstPointer();
7341   const double *coor=_coords->getConstPointer();
7342   for(const int *w=begin;w!=end;w++)
7343     {
7344       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7345       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7346       ptToFill+=spaceDim;
7347     }
7348   delete [] tmp;
7349   return ret;
7350 }
7351
7352 /*!
7353  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7354  * 
7355  */
7356 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7357 {
7358   if(!da)
7359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7360   da->checkAllocated();
7361   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7362   ret->setCoords(da);
7363   int nbOfTuples=da->getNumberOfTuples();
7364   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7366   c->alloc(2*nbOfTuples,1);
7367   cI->alloc(nbOfTuples+1,1);
7368   int *cp=c->getPointer();
7369   int *cip=cI->getPointer();
7370   *cip++=0;
7371   for(int i=0;i<nbOfTuples;i++)
7372     {
7373       *cp++=INTERP_KERNEL::NORM_POINT1;
7374       *cp++=i;
7375       *cip++=2*(i+1);
7376     }
7377   ret->setConnectivity(c,cI,true);
7378   return ret.retn();
7379 }
7380 /*!
7381  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7382  * Cells and nodes of
7383  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7384  *  \param [in] mesh1 - the first mesh.
7385  *  \param [in] mesh2 - the second mesh.
7386  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7387  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7388  *          is no more needed.
7389  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7390  *  \throw If the coordinates array is not set in none of the meshes.
7391  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7392  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7393  */
7394 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7395 {
7396   std::vector<const MEDCouplingUMesh *> tmp(2);
7397   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7398   return MergeUMeshes(tmp);
7399 }
7400
7401 /*!
7402  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7403  * Cells and nodes of
7404  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7405  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7406  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7407  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7408  *          is no more needed.
7409  *  \throw If \a a.size() == 0.
7410  *  \throw If \a a[ *i* ] == NULL.
7411  *  \throw If the coordinates array is not set in none of the meshes.
7412  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7413  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7414 */
7415 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7416 {
7417   std::size_t sz=a.size();
7418   if(sz==0)
7419     return MergeUMeshesLL(a);
7420   for(std::size_t ii=0;ii<sz;ii++)
7421     if(!a[ii])
7422       {
7423         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7424         throw INTERP_KERNEL::Exception(oss.str().c_str());
7425       }
7426   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7427   std::vector< const MEDCouplingUMesh * > aa(sz);
7428   int spaceDim=-3;
7429   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7430     {
7431       const MEDCouplingUMesh *cur=a[i];
7432       const DataArrayDouble *coo=cur->getCoords();
7433       if(coo)
7434         spaceDim=coo->getNumberOfComponents();
7435     }
7436   if(spaceDim==-3)
7437     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7438   for(std::size_t i=0;i<sz;i++)
7439     {
7440       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7441       aa[i]=bb[i];
7442     }
7443   return MergeUMeshesLL(aa);
7444 }
7445
7446 /// @cond INTERNAL
7447
7448 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7449 {
7450   if(a.empty())
7451     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7452   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7453   int meshDim=(*it)->getMeshDimension();
7454   int nbOfCells=(*it)->getNumberOfCells();
7455   int meshLgth=(*it++)->getMeshLength();
7456   for(;it!=a.end();it++)
7457     {
7458       if(meshDim!=(*it)->getMeshDimension())
7459         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7460       nbOfCells+=(*it)->getNumberOfCells();
7461       meshLgth+=(*it)->getMeshLength();
7462     }
7463   std::vector<const MEDCouplingPointSet *> aps(a.size());
7464   std::copy(a.begin(),a.end(),aps.begin());
7465   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7466   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7467   ret->setCoords(pts);
7468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7469   c->alloc(meshLgth,1);
7470   int *cPtr=c->getPointer();
7471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7472   cI->alloc(nbOfCells+1,1);
7473   int *cIPtr=cI->getPointer();
7474   *cIPtr++=0;
7475   int offset=0;
7476   int offset2=0;
7477   for(it=a.begin();it!=a.end();it++)
7478     {
7479       int curNbOfCell=(*it)->getNumberOfCells();
7480       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7481       const int *curC=(*it)->_nodal_connec->getConstPointer();
7482       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7483       for(int j=0;j<curNbOfCell;j++)
7484         {
7485           const int *src=curC+curCI[j];
7486           *cPtr++=*src++;
7487           for(;src!=curC+curCI[j+1];src++,cPtr++)
7488             {
7489               if(*src!=-1)
7490                 *cPtr=*src+offset2;
7491               else
7492                 *cPtr=-1;
7493             }
7494         }
7495       offset+=curCI[curNbOfCell];
7496       offset2+=(*it)->getNumberOfNodes();
7497     }
7498   //
7499   ret->setConnectivity(c,cI,true);
7500   return ret.retn();
7501 }
7502
7503 /// @endcond
7504
7505 /*!
7506  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7507  * dimension and sharing the node coordinates array.
7508  * All cells of the first mesh precede all cells of the second mesh
7509  * within the result mesh. 
7510  *  \param [in] mesh1 - the first mesh.
7511  *  \param [in] mesh2 - the second mesh.
7512  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7513  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7514  *          is no more needed.
7515  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7516  *  \throw If the meshes do not share the node coordinates array.
7517  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7518  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7519  */
7520 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7521 {
7522   std::vector<const MEDCouplingUMesh *> tmp(2);
7523   tmp[0]=mesh1; tmp[1]=mesh2;
7524   return MergeUMeshesOnSameCoords(tmp);
7525 }
7526
7527 /*!
7528  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7529  * dimension and sharing the node coordinates array.
7530  * All cells of the *i*-th mesh precede all cells of the
7531  * (*i*+1)-th mesh within the result mesh.
7532  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7533  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7534  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7535  *          is no more needed.
7536  *  \throw If \a a.size() == 0.
7537  *  \throw If \a a[ *i* ] == NULL.
7538  *  \throw If the meshes do not share the node coordinates array.
7539  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7540  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7541  */
7542 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7543 {
7544   if(meshes.empty())
7545     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7546   for(std::size_t ii=0;ii<meshes.size();ii++)
7547     if(!meshes[ii])
7548       {
7549         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7550         throw INTERP_KERNEL::Exception(oss.str().c_str());
7551       }
7552   const DataArrayDouble *coords=meshes.front()->getCoords();
7553   int meshDim=meshes.front()->getMeshDimension();
7554   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7555   int meshLgth=0;
7556   int meshIndexLgth=0;
7557   for(;iter!=meshes.end();iter++)
7558     {
7559       if(coords!=(*iter)->getCoords())
7560         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7561       if(meshDim!=(*iter)->getMeshDimension())
7562         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7563       meshLgth+=(*iter)->getMeshLength();
7564       meshIndexLgth+=(*iter)->getNumberOfCells();
7565     }
7566   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7567   nodal->alloc(meshLgth,1);
7568   int *nodalPtr=nodal->getPointer();
7569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7570   nodalIndex->alloc(meshIndexLgth+1,1);
7571   int *nodalIndexPtr=nodalIndex->getPointer();
7572   int offset=0;
7573   for(iter=meshes.begin();iter!=meshes.end();iter++)
7574     {
7575       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7576       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7577       int nbOfCells=(*iter)->getNumberOfCells();
7578       int meshLgth2=(*iter)->getMeshLength();
7579       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7580       if(iter!=meshes.begin())
7581         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7582       else
7583         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7584       offset+=meshLgth2;
7585     }
7586   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7587   ret->setName("merge");
7588   ret->setMeshDimension(meshDim);
7589   ret->setConnectivity(nodal,nodalIndex,true);
7590   ret->setCoords(coords);
7591   return ret;
7592 }
7593
7594 /*!
7595  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7596  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7597  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7598  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7599  * New" mode are returned for each input mesh.
7600  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7601  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7602  *          valid values [0,1,2], see zipConnectivityTraducer().
7603  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7604  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7605  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7606  *          no more needed.
7607  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7608  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7609  *          is no more needed.
7610  *  \throw If \a meshes.size() == 0.
7611  *  \throw If \a meshes[ *i* ] == NULL.
7612  *  \throw If the meshes do not share the node coordinates array.
7613  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7614  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7615  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7616  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7617  */
7618 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7619 {
7620   //All checks are delegated to MergeUMeshesOnSameCoords
7621   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7622   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7623   corr.resize(meshes.size());
7624   std::size_t nbOfMeshes=meshes.size();
7625   int offset=0;
7626   const int *o2nPtr=o2n->getConstPointer();
7627   for(std::size_t i=0;i<nbOfMeshes;i++)
7628     {
7629       DataArrayInt *tmp=DataArrayInt::New();
7630       int curNbOfCells=meshes[i]->getNumberOfCells();
7631       tmp->alloc(curNbOfCells,1);
7632       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7633       offset+=curNbOfCells;
7634       tmp->setName(meshes[i]->getName());
7635       corr[i]=tmp;
7636     }
7637   return ret.retn();
7638 }
7639
7640 /*!
7641  * Makes all given meshes share the nodal connectivity array. The common connectivity
7642  * array is created by concatenating the connectivity arrays of all given meshes. All
7643  * the given meshes must be of the same space dimension but dimension of cells **can
7644  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7645  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7646  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7647  *  \param [in,out] meshes - a vector of meshes to update.
7648  *  \throw If any of \a meshes is NULL.
7649  *  \throw If the coordinates array is not set in any of \a meshes.
7650  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7651  *  \throw If \a meshes are of different space dimension.
7652  */
7653 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7654 {
7655   std::size_t sz=meshes.size();
7656   if(sz==0 || sz==1)
7657     return;
7658   std::vector< const DataArrayDouble * > coords(meshes.size());
7659   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7660   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7661     {
7662       if((*it))
7663         {
7664           (*it)->checkConnectivityFullyDefined();
7665           const DataArrayDouble *coo=(*it)->getCoords();
7666           if(coo)
7667             *it2=coo;
7668           else
7669             {
7670               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7671               oss << " has no coordinate array defined !";
7672               throw INTERP_KERNEL::Exception(oss.str().c_str());
7673             }
7674         }
7675       else
7676         {
7677           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7678           oss << " is null !";
7679           throw INTERP_KERNEL::Exception(oss.str().c_str());
7680         }
7681     }
7682   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7683   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7684   int offset=(*it)->getNumberOfNodes();
7685   (*it++)->setCoords(res);
7686   for(;it!=meshes.end();it++)
7687     {
7688       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7689       (*it)->setCoords(res);
7690       (*it)->shiftNodeNumbersInConn(offset);
7691       offset+=oldNumberOfNodes;
7692     }
7693 }
7694
7695 /*!
7696  * Merges nodes coincident with a given precision within all given meshes that share
7697  * the nodal connectivity array. The given meshes **can be of different** mesh
7698  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7699  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7700  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7701  *  \param [in,out] meshes - a vector of meshes to update.
7702  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7703  *  \throw If any of \a meshes is NULL.
7704  *  \throw If the \a meshes do not share the same node coordinates array.
7705  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7706  */
7707 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7708 {
7709   if(meshes.empty())
7710     return ;
7711   std::set<const DataArrayDouble *> s;
7712   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7713     {
7714       if(*it)
7715         s.insert((*it)->getCoords());
7716       else
7717         {
7718           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 !";
7719           throw INTERP_KERNEL::Exception(oss.str().c_str());
7720         }
7721     }
7722   if(s.size()!=1)
7723     {
7724       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 !";
7725       throw INTERP_KERNEL::Exception(oss.str().c_str());
7726     }
7727   const DataArrayDouble *coo=*(s.begin());
7728   if(!coo)
7729     return;
7730   //
7731   DataArrayInt *comm,*commI;
7732   coo->findCommonTuples(eps,-1,comm,commI);
7733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7734   int oldNbOfNodes=coo->getNumberOfTuples();
7735   int newNbOfNodes;
7736   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7737   if(oldNbOfNodes==newNbOfNodes)
7738     return ;
7739   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7740   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7741     {
7742       (*it)->renumberNodesInConn(o2n->getConstPointer());
7743       (*it)->setCoords(newCoords);
7744     } 
7745 }
7746
7747 /*!
7748  * 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.
7749  * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7750  * @param isQuad specifies the policy of connectivity.
7751  * @ret in/out parameter in which the result will be append
7752  */
7753 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7754 {
7755   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7756   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7757   ret.push_back(cm.getExtrudedType());
7758   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7759   switch(flatType)
7760     {
7761     case INTERP_KERNEL::NORM_POINT1:
7762       {
7763         ret.push_back(connBg[1]);
7764         ret.push_back(connBg[1]+nbOfNodesPerLev);
7765         break;
7766       }
7767     case INTERP_KERNEL::NORM_SEG2:
7768       {
7769         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7770         ret.insert(ret.end(),conn,conn+4);
7771         break;
7772       }
7773     case INTERP_KERNEL::NORM_SEG3:
7774       {
7775         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7776         ret.insert(ret.end(),conn,conn+8);
7777         break;
7778       }
7779     case INTERP_KERNEL::NORM_QUAD4:
7780       {
7781         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7782         ret.insert(ret.end(),conn,conn+8);
7783         break;
7784       }
7785     case INTERP_KERNEL::NORM_TRI3:
7786       {
7787         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7788         ret.insert(ret.end(),conn,conn+6);
7789         break;
7790       }
7791     case INTERP_KERNEL::NORM_TRI6:
7792       {
7793         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,
7794                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7795         ret.insert(ret.end(),conn,conn+15);
7796         break;
7797       }
7798     case INTERP_KERNEL::NORM_QUAD8:
7799       {
7800         int conn[20]={
7801           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7802           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7803           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7804         };
7805         ret.insert(ret.end(),conn,conn+20);
7806         break;
7807       }
7808     case INTERP_KERNEL::NORM_POLYGON:
7809       {
7810         std::back_insert_iterator< std::vector<int> > ii(ret);
7811         std::copy(connBg+1,connEnd,ii);
7812         *ii++=-1;
7813         std::reverse_iterator<const int *> rConnBg(connEnd);
7814         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7815         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7816         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7817         for(std::size_t i=0;i<nbOfRadFaces;i++)
7818           {
7819             *ii++=-1;
7820             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7821             std::copy(conn,conn+4,ii);
7822           }
7823         break;
7824       }
7825     default:
7826       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7827     }
7828 }
7829
7830 /*!
7831  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
7832  */
7833 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7834 {
7835   double v[3]={0.,0.,0.};
7836   std::size_t sz=std::distance(begin,end);
7837   if(isQuadratic)
7838     sz/=2;
7839   for(std::size_t i=0;i<sz;i++)
7840     {
7841       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];
7842       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7843       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7844     }
7845   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7846 }
7847
7848 /*!
7849  * The polyhedron is specfied by its connectivity nodes in [begin,end).
7850  */
7851 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7852 {
7853   std::vector<std::pair<int,int> > edges;
7854   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7855   const int *bgFace=begin;
7856   for(std::size_t i=0;i<nbOfFaces;i++)
7857     {
7858       const int *endFace=std::find(bgFace+1,end,-1);
7859       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7860       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7861         {
7862           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7863           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7864             return false;
7865           edges.push_back(p1);
7866         }
7867       bgFace=endFace+1;
7868     }
7869   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7870 }
7871
7872 /*!
7873  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
7874  */
7875 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7876 {
7877   double vec0[3],vec1[3];
7878   std::size_t sz=std::distance(begin,end);
7879   if(sz%2!=0)
7880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7881   int nbOfNodes=(int)sz/2;
7882   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7883   const double *pt0=coords+3*begin[0];
7884   const double *pt1=coords+3*begin[nbOfNodes];
7885   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7886   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7887 }
7888
7889 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7890 {
7891   std::size_t sz=std::distance(begin,end);
7892   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7893   std::size_t nbOfNodes(sz/2);
7894   std::copy(begin,end,(int *)tmp);
7895   for(std::size_t j=1;j<nbOfNodes;j++)
7896     {
7897       begin[j]=tmp[nbOfNodes-j];
7898       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7899     }
7900 }
7901
7902 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7903 {
7904   std::size_t sz=std::distance(begin,end);
7905   if(sz!=4)
7906     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7907   double vec0[3],vec1[3];
7908   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7909   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]; 
7910   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;
7911 }
7912
7913 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7914 {
7915   std::size_t sz=std::distance(begin,end);
7916   if(sz!=5)
7917     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7918   double vec0[3];
7919   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7920   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7921   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7922 }
7923
7924 /*!
7925  * 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) 
7926  * 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
7927  * a 2D space.
7928  *
7929  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7930  * \param [in] coords the coordinates with nb of components exactly equal to 3
7931  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7932  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7933  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7934  */
7935 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7936 {
7937   int nbFaces=std::count(begin+1,end,-1)+1;
7938   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7939   double *vPtr=v->getPointer();
7940   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7941   double *pPtr=p->getPointer();
7942   const int *stFaceConn=begin+1;
7943   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7944     {
7945       const int *endFaceConn=std::find(stFaceConn,end,-1);
7946       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7947       stFaceConn=endFaceConn+1;
7948     }
7949   pPtr=p->getPointer(); vPtr=v->getPointer();
7950   DataArrayInt *comm1=0,*commI1=0;
7951   v->findCommonTuples(eps,-1,comm1,commI1);
7952   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7953   const int *comm1Ptr=comm1->getConstPointer();
7954   const int *commI1Ptr=commI1->getConstPointer();
7955   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7956   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7957   //
7958   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7959   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7960   mm->finishInsertingCells();
7961   //
7962   for(int i=0;i<nbOfGrps1;i++)
7963     {
7964       int vecId=comm1Ptr[commI1Ptr[i]];
7965       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7966       DataArrayInt *comm2=0,*commI2=0;
7967       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7968       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7969       const int *comm2Ptr=comm2->getConstPointer();
7970       const int *commI2Ptr=commI2->getConstPointer();
7971       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7972       for(int j=0;j<nbOfGrps2;j++)
7973         {
7974           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7975             {
7976               res->insertAtTheEnd(begin,end);
7977               res->pushBackSilent(-1);
7978             }
7979           else
7980             {
7981               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7982               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7983               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7984               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7985               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7986               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7987               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7988               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7989               const int *idsNodePtr=idsNode->getConstPointer();
7990               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];
7991               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7992               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7993               if(std::abs(norm)>eps)
7994                 {
7995                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7996                   mm3->rotate(center,vec,angle);
7997                 }
7998               mm3->changeSpaceDimension(2);
7999               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8000               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8001               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8002               int nbOfCells=mm4->getNumberOfCells();
8003               for(int k=0;k<nbOfCells;k++)
8004                 {
8005                   int l=0;
8006                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8007                     res->pushBackSilent(idsNodePtr[*work]);
8008                   res->pushBackSilent(-1);
8009                 }
8010             }
8011         }
8012     }
8013   res->popBackSilent();
8014 }
8015
8016 /*!
8017  * 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
8018  * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
8019  * 
8020  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8021  * \param [in] coords coordinates expected to have 3 components.
8022  * \param [in] begin start of the nodal connectivity of the face.
8023  * \param [in] end end of the nodal connectivity (excluded) of the face.
8024  * \param [out] v the normalized vector of size 3
8025  * \param [out] p the pos of plane
8026  */
8027 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
8028 {
8029   std::size_t nbPoints=std::distance(begin,end);
8030   if(nbPoints<3)
8031     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8032   double vec[3]={0.,0.,0.};
8033   std::size_t j=0;
8034   bool refFound=false;
8035   for(;j<nbPoints-1 && !refFound;j++)
8036     {
8037       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8038       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8039       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8040       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8041       if(norm>eps)
8042         {
8043           refFound=true;
8044           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8045         }
8046     }
8047   for(std::size_t i=j;i<nbPoints-1;i++)
8048     {
8049       double curVec[3];
8050       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8051       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8052       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8053       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8054       if(norm<eps)
8055         continue;
8056       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8057       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];
8058       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8059       if(norm>eps)
8060         {
8061           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8062           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8063           return ;
8064         }
8065     }
8066   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8067 }
8068
8069 /*!
8070  * This method tries to obtain a well oriented polyhedron.
8071  * If the algorithm fails, an exception will be thrown.
8072  */
8073 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
8074 {
8075   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8076   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8077   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8078   isPerm[0]=true;
8079   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8080   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8081   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8082   //
8083   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8084     {
8085       bgFace=begin;
8086       std::size_t smthChanged=0;
8087       for(std::size_t i=0;i<nbOfFaces;i++)
8088         {
8089           endFace=std::find(bgFace+1,end,-1);
8090           nbOfEdgesInFace=std::distance(bgFace,endFace);
8091           if(!isPerm[i])
8092             {
8093               bool b;
8094               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8095                 {
8096                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8097                   std::pair<int,int> p2(p1.second,p1.first);
8098                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8099                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8100                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8101                 }
8102               if(isPerm[i])
8103                 { 
8104                   if(!b)
8105                     std::reverse(bgFace+1,endFace);
8106                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8107                     {
8108                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8109                       std::pair<int,int> p2(p1.second,p1.first);
8110                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8111                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8112                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8113                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8114                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8115                       if(it!=edgesOK.end())
8116                         {
8117                           edgesOK.erase(it);
8118                           edgesFinished.push_back(p1);
8119                         }
8120                       else
8121                         edgesOK.push_back(p1);
8122                     }
8123                 }
8124             }
8125           bgFace=endFace+1;
8126         }
8127       if(smthChanged==0)
8128         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8129     }
8130   if(!edgesOK.empty())
8131     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8132   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8133     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8134       bgFace=begin;
8135       for(std::size_t i=0;i<nbOfFaces;i++)
8136         {
8137           endFace=std::find(bgFace+1,end,-1);
8138           std::reverse(bgFace+1,endFace);
8139           bgFace=endFace+1;
8140         }
8141     }
8142 }
8143
8144 /*!
8145  * This method makes the assumption spacedimension == meshdimension == 2.
8146  * This method works only for linear cells.
8147  * 
8148  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8149  */
8150 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
8151 {
8152   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8154   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8155   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8156   int nbOfNodesExpected=m->getNumberOfNodes();
8157   if(m->getNumberOfCells()!=nbOfNodesExpected)
8158     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8159   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8160   const int *n2oPtr=n2o->getConstPointer();
8161   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8162   m->getReverseNodalConnectivity(revNodal,revNodalI);
8163   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8164   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8165   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8166   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8167   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
8168   if(nbOfNodesExpected<1)
8169     return ret.retn();
8170   int prevCell=0;
8171   int prevNode=nodalPtr[nodalIPtr[0]+1];
8172   *work++=n2oPtr[prevNode];
8173   for(int i=1;i<nbOfNodesExpected;i++)
8174     {
8175       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8176         {
8177           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8178           conn.erase(prevNode);
8179           if(conn.size()==1)
8180             {
8181               int curNode=*(conn.begin());
8182               *work++=n2oPtr[curNode];
8183               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8184               shar.erase(prevCell);
8185               if(shar.size()==1)
8186                 {
8187                   prevCell=*(shar.begin());
8188                   prevNode=curNode;
8189                 }
8190               else
8191                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8192             }
8193           else
8194             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8195         }
8196       else
8197         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8198     }
8199   return ret.retn();
8200 }
8201
8202 /*!
8203  * This method makes the assumption spacedimension == meshdimension == 3.
8204  * This method works only for linear cells.
8205  * 
8206  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8207  */
8208 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8209 {
8210   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8211     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8212   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8213   const int *conn=m->getNodalConnectivity()->getConstPointer();
8214   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8215   int nbOfCells=m->getNumberOfCells();
8216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8217   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8218   if(nbOfCells<1)
8219     return ret.retn();
8220   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8221   for(int i=1;i<nbOfCells;i++)
8222     {
8223       *work++=-1;
8224       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8225     }
8226   return ret.retn();
8227 }
8228
8229 /*!
8230  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8231  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8232  */
8233 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8234 {
8235   double *w=zipFrmt;
8236   if(spaceDim==3)
8237     for(int i=0;i<nbOfNodesInCell;i++)
8238       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8239   else if(spaceDim==2)
8240     {
8241       for(int i=0;i<nbOfNodesInCell;i++)
8242         {
8243           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8244           *w++=0.;
8245         }
8246     }
8247   else
8248     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8249 }
8250
8251 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8252 {
8253   int nbOfCells=getNumberOfCells();
8254   if(nbOfCells<=0)
8255     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8256   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};
8257   ofs << "  <" << getVTKDataSetType() << ">\n";
8258   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8259   ofs << "      <PointData>\n" << pointData << std::endl;
8260   ofs << "      </PointData>\n";
8261   ofs << "      <CellData>\n" << cellData << std::endl;
8262   ofs << "      </CellData>\n";
8263   ofs << "      <Points>\n";
8264   if(getSpaceDimension()==3)
8265     _coords->writeVTK(ofs,8,"Points");
8266   else
8267     {
8268       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8269       coo->writeVTK(ofs,8,"Points");
8270     }
8271   ofs << "      </Points>\n";
8272   ofs << "      <Cells>\n";
8273   const int *cPtr=_nodal_connec->getConstPointer();
8274   const int *cIPtr=_nodal_connec_index->getConstPointer();
8275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8279   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8280   int szFaceOffsets=0,szConn=0;
8281   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8282     {
8283       *w2=cPtr[cIPtr[i]];
8284       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8285         {
8286           *w1=-1;
8287           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8288           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8289         }
8290       else
8291         {
8292           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8293           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8294           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8295           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8296           w4=std::copy(c.begin(),c.end(),w4);
8297         }
8298     }
8299   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8300   types->writeVTK(ofs,8,"UInt8","types");
8301   offsets->writeVTK(ofs,8,"Int32","offsets");
8302   if(szFaceOffsets!=0)
8303     {//presence of Polyhedra
8304       connectivity->reAlloc(szConn);
8305       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8306       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8307       w1=faces->getPointer();
8308       for(int i=0;i<nbOfCells;i++)
8309         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8310           {
8311             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8312             *w1++=nbFaces;
8313             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8314             for(int j=0;j<nbFaces;j++)
8315               {
8316                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8317                 *w1++=(int)std::distance(w6,w5);
8318                 w1=std::copy(w6,w5,w1);
8319                 w6=w5+1;
8320               }
8321           }
8322       faces->writeVTK(ofs,8,"Int32","faces");
8323     }
8324   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8325   ofs << "      </Cells>\n";
8326   ofs << "    </Piece>\n";
8327   ofs << "  </" << getVTKDataSetType() << ">\n";
8328 }
8329
8330 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8331 {
8332   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8333   if(_mesh_dim==-2)
8334     { stream << " Not set !"; return ; }
8335   stream << " Mesh dimension : " << _mesh_dim << ".";
8336   if(_mesh_dim==-1)
8337     return ;
8338   if(!_coords)
8339     { stream << " No coordinates set !"; return ; }
8340   if(!_coords->isAllocated())
8341     { stream << " Coordinates set but not allocated !"; return ; }
8342   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8343   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8344   if(!_nodal_connec_index)
8345     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8346   if(!_nodal_connec_index->isAllocated())
8347     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8348   int lgth=_nodal_connec_index->getNumberOfTuples();
8349   int cpt=_nodal_connec_index->getNumberOfComponents();
8350   if(cpt!=1 || lgth<1)
8351     return ;
8352   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8353 }
8354
8355 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8356 {
8357   return std::string("UnstructuredGrid");
8358 }
8359
8360 /*!
8361  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8362  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8363  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8364  * meshes.
8365  *  \param [in] m1 - the first input mesh which is a partitioned object.
8366  *  \param [in] m2 - the second input mesh which is a partition tool.
8367  *  \param [in] eps - precision used to detect coincident mesh entities.
8368  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8369  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8370  *         this array using decrRef() as it is no more needed.
8371  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8372  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8373  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8374  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8375  *         it is no more needed.  
8376  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8377  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8378  *         is no more needed.  
8379  *  \throw If the coordinates array is not set in any of the meshes.
8380  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8381  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8382  */
8383 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8384 {
8385   m1->checkFullyDefined();
8386   m2->checkFullyDefined();
8387   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8388     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8389   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8390   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8391   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8392   std::vector<double> addCoo,addCoordsQuadratic;
8393   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8394   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8395   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8396                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8397   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8399   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8400   std::vector< std::vector<int> > intersectEdge2;
8401   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8402   subDiv2.clear(); dd5=0; dd6=0;
8403   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8404   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8405   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8406                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8407   //
8408   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8409   addCooDa->alloc((int)(addCoo.size())/2,2);
8410   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8411   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8412   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8413   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8414   std::vector<const DataArrayDouble *> coordss(4);
8415   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8416   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8417   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8420   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8422   ret->setConnectivity(conn,connI,true);
8423   ret->setCoords(coo);
8424   cellNb1=c1.retn(); cellNb2=c2.retn();
8425   return ret.retn();
8426 }
8427
8428 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8429                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8430                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8431                                                          const std::vector<double>& addCoords,
8432                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8433 {
8434   static const int SPACEDIM=2;
8435   std::vector<double> bbox1,bbox2;
8436   const double *coo1=m1->getCoords()->getConstPointer();
8437   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8438   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8439   int offset1=m1->getNumberOfNodes();
8440   const double *coo2=m2->getCoords()->getConstPointer();
8441   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8442   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8443   int offset2=offset1+m2->getNumberOfNodes();
8444   int offset3=offset2+((int)addCoords.size())/2;
8445   m1->getBoundingBoxForBBTree(bbox1);
8446   m2->getBoundingBoxForBBTree(bbox2);
8447   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8448   int ncell1=m1->getNumberOfCells();
8449   crI.push_back(0);
8450   for(int i=0;i<ncell1;i++)
8451     {
8452       std::vector<int> candidates2;
8453       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8454       std::map<INTERP_KERNEL::Node *,int> mapp;
8455       std::map<int,INTERP_KERNEL::Node *> mappRev;
8456       INTERP_KERNEL::QuadraticPolygon pol1;
8457       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8458       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8459       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8460       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8461                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8462       //
8463       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
8464       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8465       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8466       for(it1.first();!it1.finished();it1.next())
8467         edges1.insert(it1.current()->getPtr());
8468       //
8469       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8470       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8471       int ii=0;
8472       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8473         {
8474           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8475           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8476           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8477           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8478                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8479         }
8480       ii=0;
8481       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8482         {
8483           pol1.initLocationsWithOther(pol2s[ii]);
8484           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8485           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8486           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8487         }
8488       if(!edges1.empty())
8489         {
8490           try
8491             {
8492               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8493             }
8494           catch(INTERP_KERNEL::Exception& e)
8495             {
8496               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();
8497               throw INTERP_KERNEL::Exception(oss.str().c_str());
8498             }
8499         }
8500       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8501         (*it).second->decrRef();
8502     }
8503 }
8504
8505 /*!
8506  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8507  * 
8508  */
8509 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8510                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8511                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8512                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8513                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8514 {
8515   static const int SPACEDIM=2;
8516   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8517   desc2=DataArrayInt::New();
8518   descIndx2=DataArrayInt::New();
8519   revDesc2=DataArrayInt::New();
8520   revDescIndx2=DataArrayInt::New();
8521   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8522   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8523   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8524   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8525   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8526   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8527   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8528   std::vector<double> bbox1,bbox2;
8529   m1Desc->getBoundingBoxForBBTree(bbox1);
8530   m2Desc->getBoundingBoxForBBTree(bbox2);
8531   int ncell1=m1Desc->getNumberOfCells();
8532   int ncell2=m2Desc->getNumberOfCells();
8533   intersectEdge1.resize(ncell1);
8534   colinear2.resize(ncell2);
8535   subDiv2.resize(ncell2);
8536   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8537   std::vector<int> candidates1(1);
8538   int offset1=m1->getNumberOfNodes();
8539   int offset2=offset1+m2->getNumberOfNodes();
8540   for(int i=0;i<ncell1;i++)
8541     {
8542       std::vector<int> candidates2;
8543       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8544       if(!candidates2.empty())
8545         {
8546           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8547           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8548           candidates1[0]=i;
8549           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8550           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8551           delete pol2;
8552           delete pol1;
8553         }
8554       else
8555         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8556     }
8557   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8558   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8559 }
8560
8561 /*!
8562  * This method performs the 2nd step of Partition of 2D mesh.
8563  * This method has 4 inputs :
8564  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8565  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8566  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8567  * 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'
8568  * @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'
8569  * @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.
8570  * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8571  */
8572 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)
8573 {
8574   int offset1=m1->getNumberOfNodes();
8575   int ncell=m2->getNumberOfCells();
8576   const int *c=m2->getNodalConnectivity()->getConstPointer();
8577   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8578   const double *coo=m2->getCoords()->getConstPointer();
8579   const double *cooBis=m1->getCoords()->getConstPointer();
8580   int offset2=offset1+m2->getNumberOfNodes();
8581   intersectEdge.resize(ncell);
8582   for(int i=0;i<ncell;i++,cI++)
8583     {
8584       const std::vector<int>& divs=subDiv[i];
8585       int nnode=cI[1]-cI[0]-1;
8586       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8587       std::map<INTERP_KERNEL::Node *, int> mapp22;
8588       for(int j=0;j<nnode;j++)
8589         {
8590           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8591           int nnid=c[(*cI)+j+1];
8592           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8593           mapp22[nn]=nnid+offset1;
8594         }
8595       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8596       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8597         ((*it).second.first)->decrRef();
8598       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8599       std::map<INTERP_KERNEL::Node *,int> mapp3;
8600       for(std::size_t j=0;j<divs.size();j++)
8601         {
8602           int id=divs[j];
8603           INTERP_KERNEL::Node *tmp=0;
8604           if(id<offset1)
8605             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8606           else if(id<offset2)
8607             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8608           else
8609             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8610           addNodes[j]=tmp;
8611           mapp3[tmp]=id;
8612         }
8613       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8614       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8615         (*it)->decrRef();
8616       e->decrRef();
8617     }
8618 }
8619
8620 /*!
8621  * 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).
8622  * 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
8623  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8624  * @param cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8625  * @param nodesOnPlane, returns all the nodes that are on the plane.
8626  * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
8627  * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8628  * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
8629  * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8630  * @param desc is the descending connectivity 3DSurf->3DCurve
8631  * @param descIndx is the descending connectivity index 3DSurf->3DCurve
8632  * @param cut3DSuf input/output param.
8633  */
8634 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8635                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8636                                                    const int *desc, const int *descIndx, 
8637                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8638 {
8639   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8640   int nbOf3DSurfCell=(int)cut3DSurf.size();
8641   for(int i=0;i<nbOf3DSurfCell;i++)
8642     {
8643       std::vector<int> res;
8644       int offset=descIndx[i];
8645       int nbOfSeg=descIndx[i+1]-offset;
8646       for(int j=0;j<nbOfSeg;j++)
8647         {
8648           int edgeId=desc[offset+j];
8649           int status=cut3DCurve[edgeId];
8650           if(status!=-2)
8651             {
8652               if(status>-1)
8653                 res.push_back(status);
8654               else
8655                 {
8656                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8657                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8658                 }
8659             }
8660         }
8661       switch(res.size())
8662         {
8663         case 2:
8664           {
8665             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8666             break;
8667           }
8668         case 1:
8669         case 0:
8670           {
8671             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8672             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8673             if(res.size()==2)
8674               {
8675                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8676               }
8677             else
8678               {
8679                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8680               }
8681             break;
8682           }
8683         default:
8684           {// case when plane is on a multi colinear edge of a polyhedron
8685             if((int)res.size()==2*nbOfSeg)
8686               {
8687                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8688               }
8689             else
8690               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8691           }
8692         }
8693     }
8694 }
8695
8696 /*!
8697  * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8698  * 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).
8699  * 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
8700  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8701  * @param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8702  * @param desc is the descending connectivity 3D->3DSurf
8703  * @param descIndx is the descending connectivity index 3D->3DSurf
8704  */
8705 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8706                                                   const int *desc, const int *descIndx,
8707                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8708 {
8709   checkFullyDefined();
8710   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8712   const int *nodal3D=_nodal_connec->getConstPointer();
8713   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8714   int nbOfCells=getNumberOfCells();
8715   for(int i=0;i<nbOfCells;i++)
8716     {
8717       std::map<int, std::set<int> > m;
8718       int offset=descIndx[i];
8719       int nbOfFaces=descIndx[i+1]-offset;
8720       int start=-1;
8721       int end=-1;
8722       for(int j=0;j<nbOfFaces;j++)
8723         {
8724           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8725           if(p.first!=-1 && p.second!=-1)
8726             {
8727               if(p.first!=-2)
8728                 {
8729                   start=p.first; end=p.second;
8730                   m[p.first].insert(p.second);
8731                   m[p.second].insert(p.first);
8732                 }
8733               else
8734                 {
8735                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8736                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8737                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8738                   INTERP_KERNEL::NormalizedCellType cmsId;
8739                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8740                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8741                   for(unsigned k=0;k<nbOfNodesSon;k++)
8742                     {
8743                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8744                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8745                     }
8746                 }
8747             }
8748         }
8749       if(m.empty())
8750         continue;
8751       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8752       int prev=end;
8753       while(end!=start)
8754         {
8755           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8756           const std::set<int>& s=(*it).second;
8757           std::set<int> s2; s2.insert(prev);
8758           std::set<int> s3;
8759           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8760           if(s3.size()==1)
8761             {
8762               int val=*s3.begin();
8763               conn.push_back(start);
8764               prev=start;
8765               start=val;
8766             }
8767           else
8768             start=end;
8769         }
8770       conn.push_back(end);
8771       if(conn.size()>3)
8772         {
8773           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8774           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8775           cellIds->pushBackSilent(i);
8776         }
8777     }
8778 }
8779
8780 /*!
8781  * 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
8782  * 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
8783  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8784  * 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
8785  * 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.
8786  * 
8787  * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8788  */
8789 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8790 {
8791   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8792   if(sz>=4)
8793     {
8794       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8795       if(cm.getDimension()==2)
8796         {
8797           const int *node=nodalConnBg+1;
8798           int startNode=*node++;
8799           double refX=coords[2*startNode];
8800           for(;node!=nodalConnEnd;node++)
8801             {
8802               if(coords[2*(*node)]<refX)
8803                 {
8804                   startNode=*node;
8805                   refX=coords[2*startNode];
8806                 }
8807             }
8808           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8809           refX=1e300;
8810           double tmp1;
8811           double tmp2[2];
8812           double angle0=-M_PI/2;
8813           //
8814           int nextNode=-1;
8815           int prevNode=-1;
8816           double resRef;
8817           double angleNext=0.;
8818           while(nextNode!=startNode)
8819             {
8820               nextNode=-1;
8821               resRef=1e300;
8822               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8823                 {
8824                   if(*node!=tmpOut.back() && *node!=prevNode)
8825                     {
8826                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8827                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8828                       double res;
8829                       if(angleM<=angle0)
8830                         res=angle0-angleM;
8831                       else
8832                         res=angle0-angleM+2.*M_PI;
8833                       if(res<resRef)
8834                         {
8835                           nextNode=*node;
8836                           resRef=res;
8837                           angleNext=angleM;
8838                         }
8839                     }
8840                 }
8841               if(nextNode!=startNode)
8842                 {
8843                   angle0=angleNext-M_PI;
8844                   if(angle0<-M_PI)
8845                     angle0+=2*M_PI;
8846                   prevNode=tmpOut.back();
8847                   tmpOut.push_back(nextNode);
8848                 }
8849             }
8850           std::vector<int> tmp3(2*(sz-1));
8851           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8852           std::copy(nodalConnBg+1,nodalConnEnd,it);
8853           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8854             {
8855               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8856               return false;
8857             }
8858           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8859             {
8860               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8861               return false;
8862             }
8863           else
8864             {
8865               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8866               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8867               return true;
8868             }
8869         }
8870       else
8871         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8872     }
8873   else
8874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8875 }
8876
8877 /*!
8878  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8879  * 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.
8880  * 
8881  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8882  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8883  * \param [in,out] arr array in which the remove operation will be done.
8884  * \param [in,out] arrIndx array in the remove operation will modify
8885  * \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])
8886  * \return true if \b arr and \b arrIndx have been modified, false if not.
8887  */
8888 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8889 {
8890   if(!arrIndx || !arr)
8891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8892   if(offsetForRemoval<0)
8893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8894   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8895   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8896   int *arrIPtr=arrIndx->getPointer();
8897   *arrIPtr++=0;
8898   int previousArrI=0;
8899   const int *arrPtr=arr->getConstPointer();
8900   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8901   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8902     {
8903       if(*arrIPtr-previousArrI>offsetForRemoval)
8904         {
8905           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8906             {
8907               if(s.find(*work)==s.end())
8908                 arrOut.push_back(*work);
8909             }
8910         }
8911       previousArrI=*arrIPtr;
8912       *arrIPtr=(int)arrOut.size();
8913     }
8914   if(arr->getNumberOfTuples()==(int)arrOut.size())
8915     return false;
8916   arr->alloc((int)arrOut.size(),1);
8917   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8918   return true;
8919 }
8920
8921 /*!
8922  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8923  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8924  * The selection of extraction is done standardly in new2old format.
8925  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8926  *
8927  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8928  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8929  * \param [in] arrIn arr origin array from which the extraction will be done.
8930  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8931  * \param [out] arrOut the resulting array
8932  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8933  */
8934 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8935                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8936 {
8937   if(!arrIn || !arrIndxIn)
8938     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8939   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8940   const int *arrInPtr=arrIn->getConstPointer();
8941   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8942   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8943   int maxSizeOfArr=arrIn->getNumberOfTuples();
8944   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8945   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8946   arrIo->alloc((int)(sz+1),1);
8947   const int *idsIt=idsOfSelectBg;
8948   int *work=arrIo->getPointer();
8949   *work++=0;
8950   int lgth=0;
8951   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8952     {
8953       if(*idsIt>=0 && *idsIt<nbOfGrps)
8954         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8955       else
8956         {
8957           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8958           throw INTERP_KERNEL::Exception(oss.str().c_str());
8959         }
8960       if(lgth>=work[-1])
8961         *work=lgth;
8962       else
8963         {
8964           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8965           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8966           throw INTERP_KERNEL::Exception(oss.str().c_str());
8967         }
8968     }
8969   arro->alloc(lgth,1);
8970   work=arro->getPointer();
8971   idsIt=idsOfSelectBg;
8972   for(std::size_t i=0;i<sz;i++,idsIt++)
8973     {
8974       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8975         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8976       else
8977         {
8978           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8979           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8980           throw INTERP_KERNEL::Exception(oss.str().c_str());
8981         }
8982     }
8983   arrOut=arro.retn();
8984   arrIndexOut=arrIo.retn();
8985 }
8986
8987 /*!
8988  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8989  * 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
8990  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8991  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8992  *
8993  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8994  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8995  * \param [in] arrIn arr origin array from which the extraction will be done.
8996  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8997  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8998  * \param [in] srcArrIndex index array of \b srcArr
8999  * \param [out] arrOut the resulting array
9000  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9001  * 
9002  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9003  */
9004 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9005                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9006                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9007 {
9008   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9009     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9010   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9011   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9012   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9013   std::vector<bool> v(nbOfTuples,true);
9014   int offset=0;
9015   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9016   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9017   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9018     {
9019       if(*it>=0 && *it<nbOfTuples)
9020         {
9021           v[*it]=false;
9022           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9023         }
9024       else
9025         {
9026           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9027           throw INTERP_KERNEL::Exception(oss.str().c_str());
9028         }
9029     }
9030   srcArrIndexPtr=srcArrIndex->getConstPointer();
9031   arrIo->alloc(nbOfTuples+1,1);
9032   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9033   const int *arrInPtr=arrIn->getConstPointer();
9034   const int *srcArrPtr=srcArr->getConstPointer();
9035   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9036   int *arroPtr=arro->getPointer();
9037   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9038     {
9039       if(v[ii])
9040         {
9041           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9042           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9043         }
9044       else
9045         {
9046           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9047           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9048           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9049         }
9050     }
9051   arrOut=arro.retn();
9052   arrIndexOut=arrIo.retn();
9053 }
9054
9055 /*!
9056  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9057  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9058  *
9059  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9060  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9061  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9062  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9063  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9064  * \param [in] srcArrIndex index array of \b srcArr
9065  * 
9066  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9067  */
9068 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9069                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9070 {
9071   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9073   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9074   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9075   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9076   int *arrInOutPtr=arrInOut->getPointer();
9077   const int *srcArrPtr=srcArr->getConstPointer();
9078   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9079     {
9080       if(*it>=0 && *it<nbOfTuples)
9081         {
9082           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9083             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9084           else
9085             {
9086               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] !";
9087               throw INTERP_KERNEL::Exception(oss.str().c_str());
9088             }
9089         }
9090       else
9091         {
9092           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9093           throw INTERP_KERNEL::Exception(oss.str().c_str());
9094         }
9095     }
9096 }
9097
9098 /*!
9099  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9100  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9101  * 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]].
9102  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9103  * A negative value in \b arrIn means that it is ignored.
9104  * 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.
9105  * 
9106  * \param [in] arrIn arr origin array from which the extraction will be done.
9107  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9108  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9109  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9110  */
9111 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9112 {
9113   int seed=0,nbOfDepthPeelingPerformed=0;
9114   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9115 }
9116
9117 /*!
9118  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9119  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9120  * 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]].
9121  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9122  * A negative value in \b arrIn means that it is ignored.
9123  * 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.
9124  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9125  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9126  * \param [in] arrIn arr origin array from which the extraction will be done.
9127  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9128  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9129  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9130  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9131  * \sa MEDCouplingUMesh::partitionBySpreadZone
9132  */
9133 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9134 {
9135   nbOfDepthPeelingPerformed=0;
9136   if(!arrIndxIn)
9137     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9138   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9139   if(nbOfTuples<=0)
9140     {
9141       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9142       return ret;
9143     }
9144   //
9145   std::vector<bool> fetched(nbOfTuples,false);
9146   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9147 }
9148
9149 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)
9150 {
9151   nbOfDepthPeelingPerformed=0;
9152   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9154   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9155   std::vector<bool> fetched2(nbOfTuples,false);
9156   int i=0;
9157   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9158     {
9159       if(*seedElt>=0 && *seedElt<nbOfTuples)
9160         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9161       else
9162         { 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()); }
9163     }
9164   const int *arrInPtr=arrIn->getConstPointer();
9165   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9166   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9167   std::vector<int> idsToFetch1(seedBg,seedEnd);
9168   std::vector<int> idsToFetch2;
9169   std::vector<int> *idsToFetch=&idsToFetch1;
9170   std::vector<int> *idsToFetchOther=&idsToFetch2;
9171   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9172     {
9173       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9174         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9175           if(!fetched[*it2])
9176             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9177       std::swap(idsToFetch,idsToFetchOther);
9178       idsToFetchOther->clear();
9179       nbOfDepthPeelingPerformed++;
9180     }
9181   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9182   i=0;
9183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9184   int *retPtr=ret->getPointer();
9185   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9186     if(*it)
9187       *retPtr++=i;
9188   return ret.retn();
9189 }
9190
9191 /*!
9192  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9193  * 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
9194  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9195  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9196  *
9197  * \param [in] start begin of set of ids of the input extraction (included)
9198  * \param [in] end end of set of ids of the input extraction (excluded)
9199  * \param [in] step step of the set of ids in range mode.
9200  * \param [in] arrIn arr origin array from which the extraction will be done.
9201  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9202  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9203  * \param [in] srcArrIndex index array of \b srcArr
9204  * \param [out] arrOut the resulting array
9205  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9206  * 
9207  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9208  */
9209 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9210                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9211                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9212 {
9213   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9217   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9218   int offset=0;
9219   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9220   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9221   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9222   int it=start;
9223   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9224     {
9225       if(it>=0 && it<nbOfTuples)
9226         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9227       else
9228         {
9229           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9230           throw INTERP_KERNEL::Exception(oss.str().c_str());
9231         }
9232     }
9233   srcArrIndexPtr=srcArrIndex->getConstPointer();
9234   arrIo->alloc(nbOfTuples+1,1);
9235   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9236   const int *arrInPtr=arrIn->getConstPointer();
9237   const int *srcArrPtr=srcArr->getConstPointer();
9238   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9239   int *arroPtr=arro->getPointer();
9240   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9241     {
9242       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9243       if(pos<0)
9244         {
9245           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9246           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9247         }
9248       else
9249         {
9250           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9251           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9252         }
9253     }
9254   arrOut=arro.retn();
9255   arrIndexOut=arrIo.retn();
9256 }
9257
9258 /*!
9259  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9260  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9261  *
9262  * \param [in] start begin of set of ids of the input extraction (included)
9263  * \param [in] end end of set of ids of the input extraction (excluded)
9264  * \param [in] step step of the set of ids in range mode.
9265  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9266  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9267  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9268  * \param [in] srcArrIndex index array of \b srcArr
9269  * 
9270  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9271  */
9272 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9273                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9274 {
9275   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9276     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9277   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9278   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9279   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9280   int *arrInOutPtr=arrInOut->getPointer();
9281   const int *srcArrPtr=srcArr->getConstPointer();
9282   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9283   int it=start;
9284   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9285     {
9286       if(it>=0 && it<nbOfTuples)
9287         {
9288           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9289             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9290           else
9291             {
9292               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9293               throw INTERP_KERNEL::Exception(oss.str().c_str());
9294             }
9295         }
9296       else
9297         {
9298           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9299           throw INTERP_KERNEL::Exception(oss.str().c_str());
9300         }
9301     }
9302 }
9303
9304 /*!
9305  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9306  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9307  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9308  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9309  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9310  * 
9311  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9312  */
9313 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9314 {
9315   checkFullyDefined();
9316   int mdim=getMeshDimension();
9317   int spaceDim=getSpaceDimension();
9318   if(mdim!=spaceDim)
9319     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9320   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9321   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9322   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9323   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9324   ret->setCoords(getCoords());
9325   ret->allocateCells((int)partition.size());
9326   //
9327   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9328     {
9329       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9330       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9331       switch(mdim)
9332         {
9333         case 2:
9334           cell=tmp->buildUnionOf2DMesh();
9335           break;
9336         case 3:
9337           cell=tmp->buildUnionOf3DMesh();
9338           break;
9339         default:
9340           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9341         }
9342       
9343       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9344     }
9345   //
9346   ret->finishInsertingCells();
9347   return ret.retn();
9348 }
9349
9350 /*!
9351  * This method partitions \b this into contiguous zone.
9352  * This method only needs a well defined connectivity. Coordinates are not considered here.
9353  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9354  */
9355 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9356 {
9357   //#if 0
9358   int nbOfCellsCur=getNumberOfCells();
9359   std::vector<DataArrayInt *> ret;
9360   if(nbOfCellsCur<=0)
9361     return ret;
9362   DataArrayInt *neigh=0,*neighI=0;
9363   computeNeighborsOfCells(neigh,neighI);
9364   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9365   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9366   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9367   int seed=0;
9368   while(seed<nbOfCellsCur)
9369     {
9370       int nbOfPeelPerformed=0;
9371       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9372       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9373     }
9374   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9375     ret.push_back((*it).retn());
9376   return ret;
9377   //#endif
9378 #if 0
9379   int nbOfCellsCur=getNumberOfCells();
9380   DataArrayInt *neigh=0,*neighI=0;
9381   computeNeighborsOfCells(neigh,neighI);
9382   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9384   std::vector<DataArrayInt *> ret;
9385   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9386   while(nbOfCellsCur>0)
9387     {
9388       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9389       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9390       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9391       ret2.push_back(tmp2);  ret.push_back(tmp2);
9392       nbOfCellsCur=tmp3->getNumberOfTuples();
9393       if(nbOfCellsCur>0)
9394         {
9395           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9396           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9397           neighAuto=neigh;
9398           neighIAuto=neighI;
9399           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9400           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9401         }
9402     }
9403   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9404     (*it)->incrRef();
9405   return ret;
9406 #endif
9407 }
9408
9409 /*!
9410  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9411  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9412  *
9413  * \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.
9414  * \return a newly allocated DataArrayInt to be managed by the caller.
9415  * \throw In case of \a code has not the right format (typically of size 3*n)
9416  */
9417 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9418 {
9419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9420   std::size_t nb=code.size()/3;
9421   if(code.size()%3!=0)
9422     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9423   ret->alloc((int)nb,2);
9424   int *retPtr=ret->getPointer();
9425   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9426     {
9427       retPtr[0]=code[3*i+2];
9428       retPtr[1]=code[3*i+2]+code[3*i+1];
9429     }
9430   return ret.retn();
9431 }
9432
9433 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9434                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9435 {
9436   if(mesh)
9437     {
9438       mesh->incrRef();
9439       _nb_cell=mesh->getNumberOfCells();
9440     }
9441 }
9442
9443 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9444 {
9445   if(_mesh)
9446     _mesh->decrRef();
9447   if(_own_cell)
9448     delete _cell;
9449 }
9450
9451 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9452                                                                                                                                _own_cell(false),_cell_id(bg-1),
9453                                                                                                                                _nb_cell(end)
9454 {
9455   if(mesh)
9456     mesh->incrRef();
9457 }
9458
9459 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9460 {
9461   _cell_id++;
9462   if(_cell_id<_nb_cell)
9463     {
9464       _cell->next();
9465       return _cell;
9466     }
9467   else
9468     return 0;
9469 }
9470
9471 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9472 {
9473   if(_mesh)
9474     _mesh->incrRef();
9475 }
9476
9477 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9478 {
9479   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9480 }
9481
9482 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9483 {
9484   if(_mesh)
9485     _mesh->decrRef();
9486 }
9487
9488 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9489                                                                                                                                                                   _itc(itc),
9490                                                                                                                                                                   _bg(bg),_end(end)
9491 {
9492   if(_mesh)
9493     _mesh->incrRef();
9494 }
9495
9496 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9497 {
9498   if(_mesh)
9499     _mesh->decrRef();
9500 }
9501
9502 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9503 {
9504   return _type;
9505 }
9506
9507 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9508 {
9509   return _end-_bg;
9510 }
9511
9512 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9513 {
9514   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9515 }
9516
9517 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9518 {
9519   if(mesh)
9520     {
9521       mesh->incrRef();
9522       _nb_cell=mesh->getNumberOfCells();
9523     }
9524 }
9525
9526 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9527 {
9528   if(_mesh)
9529     _mesh->decrRef();
9530   delete _cell;
9531 }
9532
9533 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9534 {
9535   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9536   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9537   if(_cell_id<_nb_cell)
9538     {
9539       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9540       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9541       int startId=_cell_id;
9542       _cell_id+=nbOfElems;
9543       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9544     }
9545   else
9546     return 0;
9547 }
9548
9549 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9550 {
9551   if(mesh)
9552     {
9553       _conn=mesh->getNodalConnectivity()->getPointer();
9554       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9555     }
9556 }
9557
9558 void MEDCouplingUMeshCell::next()
9559 {
9560   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9561     {
9562       _conn+=_conn_lgth;
9563       _conn_indx++;
9564     }
9565   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9566 }
9567
9568 std::string MEDCouplingUMeshCell::repr() const
9569 {
9570   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9571     {
9572       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9573       oss << " : ";
9574       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9575       return oss.str();
9576     }
9577   else
9578     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9579 }
9580
9581 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9582 {
9583   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9584     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9585   else
9586     return INTERP_KERNEL::NORM_ERROR;
9587 }
9588
9589 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9590 {
9591   lgth=_conn_lgth;
9592   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9593     return _conn;
9594   else
9595     return 0;
9596 }