Salome HOME
44c34fd200c13cfa679631162e68f44e0cc61d23
[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 "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 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 };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
128   if(_nodal_connec)
129     ret.push_back(_nodal_connec);
130   if(_nodal_connec_index)
131     ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
247         {
248           int nodeId=*w;
249           if(nodeId>=0)
250             {
251               if(nodeId>=nbOfNodes)
252                 {
253                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254                   throw INTERP_KERNEL::Exception(oss.str().c_str());
255                 }
256             }
257           else if(nodeId<-1)
258             {
259               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260               throw INTERP_KERNEL::Exception(oss.str().c_str());
261             }
262           else
263             {
264               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267                   throw INTERP_KERNEL::Exception(oss.str().c_str());
268                 }
269             }
270         }
271     }
272 }
273
274
275 /*!
276  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277  * then \a this mesh is most probably is writable, exchangeable and available for all
278  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
279  *  \param [in] eps - a not used parameter.
280  *  \throw If the mesh dimension is not set.
281  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
282  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283  *  \throw If the connectivity data array has more than one component.
284  *  \throw If the connectivity data array has a named component.
285  *  \throw If the connectivity index data array has more than one component.
286  *  \throw If the connectivity index data array has a named component.
287  *  \throw If number of nodes defining an element does not correspond to the type of element.
288  *  \throw If the nodal connectivity includes an invalid node id.
289  */
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 {
292   checkCoherency1(eps);
293 }
294
295 /*!
296  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297  * elements contained in the mesh. For more info on the mesh dimension see
298  * \ref MEDCouplingUMeshPage.
299  *  \param [in] meshDim - a new mesh dimension.
300  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301  */
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 {
304   if(meshDim<-1 || meshDim>3)
305     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
306   _mesh_dim=meshDim;
307   declareAsNew();
308 }
309
310 /*!
311  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314  *
315  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316  *
317  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
318  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
319  */
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
321 {
322   if(nbOfCells<0)
323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324   if(_nodal_connec_index)
325     {
326       _nodal_connec_index->decrRef();
327     }
328   if(_nodal_connec)
329     {
330       _nodal_connec->decrRef();
331     }
332   _nodal_connec_index=DataArrayInt::New();
333   _nodal_connec_index->reserve(nbOfCells+1);
334   _nodal_connec_index->pushBackSilent(0);
335   _nodal_connec=DataArrayInt::New();
336   _nodal_connec->reserve(2*nbOfCells);
337   _types.clear();
338   declareAsNew();
339 }
340
341 /*!
342  * Appends a cell to the connectivity array. For deeper understanding what is
343  * happening see \ref MEDCouplingUMeshNodalConnectivity.
344  *  \param [in] type - type of cell to add.
345  *  \param [in] size - number of nodes constituting this cell.
346  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
347  * 
348  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
349  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
350  */
351 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
352 {
353   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
354   if(_nodal_connec_index==0)
355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
356   if((int)cm.getDimension()==_mesh_dim)
357     {
358       if(!cm.isDynamic())
359         if(size!=(int)cm.getNumberOfNodes())
360           {
361             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
362             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
363             throw INTERP_KERNEL::Exception(oss.str().c_str());
364           }
365       int idx=_nodal_connec_index->back();
366       int val=idx+size+1;
367       _nodal_connec_index->pushBackSilent(val);
368       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
369       _types.insert(type);
370     }
371   else
372     {
373       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
374       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
375       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
376       throw INTERP_KERNEL::Exception(oss.str().c_str());
377     }
378 }
379
380 /*!
381  * Compacts data arrays to release unused memory. This method is to be called after
382  * finishing cell insertion using \a this->insertNextCell().
383  * 
384  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
385  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
386  */
387 void MEDCouplingUMesh::finishInsertingCells()
388 {
389   _nodal_connec->pack();
390   _nodal_connec_index->pack();
391   _nodal_connec->declareAsNew();
392   _nodal_connec_index->declareAsNew();
393   updateTime();
394 }
395
396 /*!
397  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
398  * Useful for python users.
399  */
400 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
401 {
402   return new MEDCouplingUMeshCellIterator(this);
403 }
404
405 /*!
406  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
407  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
408  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
409  * Useful for python users.
410  */
411 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
412 {
413   if(!checkConsecutiveCellTypes())
414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
415   return new MEDCouplingUMeshCellByTypeEntry(this);
416 }
417
418 /*!
419  * Returns a set of all cell types available in \a this mesh.
420  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
421  * \warning this method does not throw any exception even if \a this is not defined.
422  */
423 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
424 {
425   return _types;
426 }
427
428 /*!
429  * This method is a method that compares \a this and \a other.
430  * This method compares \b all attributes, even names and component names.
431  */
432 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
433 {
434   if(!other)
435     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
436   std::ostringstream oss; oss.precision(15);
437   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
438   if(!otherC)
439     {
440       reason="mesh given in input is not castable in MEDCouplingUMesh !";
441       return false;
442     }
443   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
444     return false;
445   if(_mesh_dim!=otherC->_mesh_dim)
446     {
447       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
448       reason=oss.str();
449       return false;
450     }
451   if(_types!=otherC->_types)
452     {
453       oss << "umesh geometric type mismatch :\nThis geometric types are :";
454       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
455         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
456       oss << "\nOther geometric types are :";
457       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
458         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
459       reason=oss.str();
460       return false;
461     }
462   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
463     if(_nodal_connec==0 || otherC->_nodal_connec==0)
464       {
465         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
466         return false;
467       }
468   if(_nodal_connec!=otherC->_nodal_connec)
469     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
470       {
471         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
472         return false;
473       }
474   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
475     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
476       {
477         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
478         return false;
479       }
480   if(_nodal_connec_index!=otherC->_nodal_connec_index)
481     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
482       {
483         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
484         return false;
485       }
486   return true;
487 }
488
489 /*!
490  * Checks if data arrays of this mesh (node coordinates, nodal
491  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
492  * not considered.
493  *  \param [in] other - the mesh to compare with.
494  *  \param [in] prec - precision value used to compare node coordinates.
495  *  \return bool - \a true if the two meshes are same.
496  */
497 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
498 {
499   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
500   if(!otherC)
501     return false;
502   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
503     return false;
504   if(_mesh_dim!=otherC->_mesh_dim)
505     return false;
506   if(_types!=otherC->_types)
507     return false;
508   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
509     if(_nodal_connec==0 || otherC->_nodal_connec==0)
510       return false;
511   if(_nodal_connec!=otherC->_nodal_connec)
512     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
513       return false;
514   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
515     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
516       return false;
517   if(_nodal_connec_index!=otherC->_nodal_connec_index)
518     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
519       return false;
520   return true;
521 }
522
523 /*!
524  * Checks if \a this and \a other meshes are geometrically equivalent with high
525  * probability, else an exception is thrown. The meshes are considered equivalent if
526  * (1) meshes contain the same number of nodes and the same number of elements of the
527  * same types (2) three cells of the two meshes (first, last and middle) are based
528  * on coincident nodes (with a specified precision).
529  *  \param [in] other - the mesh to compare with.
530  *  \param [in] prec - the precision used to compare nodes of the two meshes.
531  *  \throw If the two meshes do not match.
532  */
533 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
534 {
535  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
536  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
537   if(!otherC)
538     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
539 }
540
541 /*!
542  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
543  * cells each node belongs to.
544  * \warning For speed reasons, this method does not check if node ids in the nodal
545  *          connectivity correspond to the size of node coordinates array.
546  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
547  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
548  *        dividing cell ids in \a revNodal into groups each referring to one
549  *        node. Its every element (except the last one) is an index pointing to the
550  *         first id of a group of cells. For example cells sharing the node #1 are 
551  *        described by following range of indices: 
552  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
553  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
554  *        Number of cells sharing the *i*-th node is
555  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
556  * \throw If the coordinates array is not set.
557  * \throw If the nodal connectivity of cells is not defined.
558  * 
559  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
560  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
561  */
562 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
563 {
564   checkFullyDefined();
565   int nbOfNodes=getNumberOfNodes();
566   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
567   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
568   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
569   const int *conn=_nodal_connec->getConstPointer();
570   const int *connIndex=_nodal_connec_index->getConstPointer();
571   int nbOfCells=getNumberOfCells();
572   int nbOfEltsInRevNodal=0;
573   for(int eltId=0;eltId<nbOfCells;eltId++)
574     {
575       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
576       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
577       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
578         if(*iter>=0)//for polyhedrons
579           {
580             nbOfEltsInRevNodal++;
581             revNodalIndxPtr[(*iter)+1]++;
582           }
583     }
584   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
585   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
586   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
587   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
588   for(int eltId=0;eltId<nbOfCells;eltId++)
589     {
590       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
591       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
592       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
593         if(*iter>=0)//for polyhedrons
594           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
595     }
596 }
597
598 /// @cond INTERNAL
599
600 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
601 {
602   return id;
603 }
604
605 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
606 {
607   if(!compute)
608     return id+1;
609   else
610     {
611       if(cm.getOrientationStatus(nb,conn1,conn2))
612         return id+1;
613       else
614         return -(id+1);
615     }
616 }
617
618 class MinusOneSonsGenerator
619 {
620 public:
621   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
622   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
623   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
624   static const int DELTA=1;
625 private:
626   const INTERP_KERNEL::CellModel& _cm;
627 };
628
629 class MinusOneSonsGeneratorBiQuadratic
630 {
631 public:
632   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
633   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
634   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
635   static const int DELTA=1;
636 private:
637   const INTERP_KERNEL::CellModel& _cm;
638 };
639
640 class MinusTwoSonsGenerator
641 {
642 public:
643   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
644   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
645   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
646   static const int DELTA=2;
647 private:
648   const INTERP_KERNEL::CellModel& _cm;
649 };
650
651 /// @endcond
652
653 /*!
654  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
655  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
656  * describing correspondence between cells of \a this and the result meshes are
657  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
658  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
659  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
660  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
661  * \warning For speed reasons, this method does not check if node ids in the nodal
662  *          connectivity correspond to the size of node coordinates array.
663  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
664  *          to write this mesh to the MED file, its cells must be sorted using
665  *          sortCellsInMEDFileFrmt().
666  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
667  *         each cell of \a this mesh.
668  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
669  *        dividing cell ids in \a desc into groups each referring to one
670  *        cell of \a this mesh. Its every element (except the last one) is an index
671  *        pointing to the first id of a group of cells. For example cells of the
672  *        result mesh bounding the cell #1 of \a this mesh are described by following
673  *        range of indices:
674  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
675  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
676  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
677  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
678  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
679  *         by each cell of the result mesh.
680  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
681  *        in the result mesh,
682  *        dividing cell ids in \a revDesc into groups each referring to one
683  *        cell of the result mesh the same way as \a descIndx divides \a desc.
684  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
685  *        delete this mesh using decrRef() as it is no more needed.
686  *  \throw If the coordinates array is not set.
687  *  \throw If the nodal connectivity of cells is node defined.
688  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
689  *         revDescIndx == NULL.
690  * 
691  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
692  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
693  * \sa buildDescendingConnectivity2()
694  */
695 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
696 {
697   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
698 }
699
700 /*!
701  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
702  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
703  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
704  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
705  * \sa MEDCouplingUMesh::buildDescendingConnectivity
706  */
707 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
708 {
709   checkFullyDefined();
710   if(getMeshDimension()!=3)
711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
712   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
713 }
714
715 /*!
716  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
717  * this->getMeshDimension(), that bound cells of \a this mesh. In
718  * addition arrays describing correspondence between cells of \a this and the result
719  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
720  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
721  *  mesh. This method differs from buildDescendingConnectivity() in that apart
722  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
723  * result meshes. So a positive id means that order of nodes in corresponding cells
724  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
725  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
726  * i.e. cell ids are one-based.
727  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
728  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
729  * \warning For speed reasons, this method does not check if node ids in the nodal
730  *          connectivity correspond to the size of node coordinates array.
731  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
732  *          to write this mesh to the MED file, its cells must be sorted using
733  *          sortCellsInMEDFileFrmt().
734  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
735  *         each cell of \a this mesh.
736  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
737  *        dividing cell ids in \a desc into groups each referring to one
738  *        cell of \a this mesh. Its every element (except the last one) is an index
739  *        pointing to the first id of a group of cells. For example cells of the
740  *        result mesh bounding the cell #1 of \a this mesh are described by following
741  *        range of indices:
742  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
743  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
744  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
745  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
746  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
747  *         by each cell of the result mesh.
748  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
749  *        in the result mesh,
750  *        dividing cell ids in \a revDesc into groups each referring to one
751  *        cell of the result mesh the same way as \a descIndx divides \a desc.
752  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
753  *        shares the node coordinates array with \a this mesh. The caller is to
754  *        delete this mesh using decrRef() as it is no more needed.
755  *  \throw If the coordinates array is not set.
756  *  \throw If the nodal connectivity of cells is node defined.
757  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
758  *         revDescIndx == NULL.
759  * 
760  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
761  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
762  * \sa buildDescendingConnectivity()
763  */
764 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
765 {
766   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
767 }
768
769 /*!
770  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
771  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
772  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
773  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
774  *
775  * \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
776  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
777  * \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.
778  */
779 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
780 {
781   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
782   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
785   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
786   meshDM1=0;
787   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
788 }
789
790 /*!
791  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
792  * 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,
793  * excluding a set of meshdim-1 cells in input descending connectivity.
794  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
795  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
796  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
797  *
798  * \param [in] desc descending connectivity array.
799  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
800  * \param [in] revDesc reverse descending connectivity array.
801  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
802  * \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
803  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
804  * \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.
805  */
806 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
807                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
808 {
809   if(!desc || !descIndx || !revDesc || !revDescIndx)
810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
811   const int *descPtr=desc->getConstPointer();
812   const int *descIPtr=descIndx->getConstPointer();
813   const int *revDescPtr=revDesc->getConstPointer();
814   const int *revDescIPtr=revDescIndx->getConstPointer();
815   //
816   int nbCells=descIndx->getNumberOfTuples()-1;
817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
819   int *out1Ptr=out1->getPointer();
820   *out1Ptr++=0;
821   out0->reserve(desc->getNumberOfTuples());
822   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
823     {
824       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
825         {
826           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
827           s.erase(i);
828           out0->insertAtTheEnd(s.begin(),s.end());
829         }
830       *out1Ptr=out0->getNumberOfTuples();
831     }
832   neighbors=out0.retn();
833   neighborsIndx=out1.retn();
834 }
835
836 /// @cond INTERNAL
837
838 /*!
839  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
840  * For speed reasons no check of this will be done.
841  */
842 template<class SonsGenerator>
843 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
844 {
845   if(!desc || !descIndx || !revDesc || !revDescIndx)
846     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
847   checkConnectivityFullyDefined();
848   int nbOfCells=getNumberOfCells();
849   int nbOfNodes=getNumberOfNodes();
850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
851   int *revNodalIndxPtr=revNodalIndx->getPointer();
852   const int *conn=_nodal_connec->getConstPointer();
853   const int *connIndex=_nodal_connec_index->getConstPointer();
854   std::string name="Mesh constituent of "; name+=getName();
855   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
856   ret->setCoords(getCoords());
857   ret->allocateCells(2*nbOfCells);
858   descIndx->alloc(nbOfCells+1,1);
859   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
860   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
861   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
862     {
863       int pos=connIndex[eltId];
864       int posP1=connIndex[eltId+1];
865       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
866       SonsGenerator sg(cm);
867       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
868       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
869       for(unsigned i=0;i<nbOfSons;i++)
870         {
871           INTERP_KERNEL::NormalizedCellType cmsId;
872           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
873           for(unsigned k=0;k<nbOfNodesSon;k++)
874             if(tmp[k]>=0)
875               revNodalIndxPtr[tmp[k]+1]++;
876           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
877           revDesc2->pushBackSilent(eltId);
878         }
879       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
880     }
881   int nbOfCellsM1=ret->getNumberOfCells();
882   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
884   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
885   int *revNodalPtr=revNodal->getPointer();
886   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
887   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
888   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
889     {
890       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
891       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
892       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
893         if(*iter>=0)//for polyhedrons
894           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
895     }
896   //
897   DataArrayInt *commonCells=0,*commonCellsI=0;
898   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
899   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
900   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
901   int newNbOfCellsM1=-1;
902   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
903                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
904   std::vector<bool> isImpacted(nbOfCellsM1,false);
905   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
906     for(int work2=work[0];work2!=work[1];work2++)
907       isImpacted[commonCellsPtr[work2]]=true;
908   const int *o2nM1Ptr=o2nM1->getConstPointer();
909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
910   const int *n2oM1Ptr=n2oM1->getConstPointer();
911   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
912   ret2->copyTinyInfoFrom(this);
913   desc->alloc(descIndx->back(),1);
914   int *descPtr=desc->getPointer();
915   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
916   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
917     {
918       if(!isImpacted[i])
919         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
920       else
921         {
922           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
923             {
924               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
925               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
926             }
927           else
928             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
929         }
930     }
931   revDesc->reserve(newNbOfCellsM1);
932   revDescIndx->alloc(newNbOfCellsM1+1,1);
933   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
934   const int *revDesc2Ptr=revDesc2->getConstPointer();
935   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
936     {
937       int oldCellIdM1=n2oM1Ptr[i];
938       if(!isImpacted[oldCellIdM1])
939         {
940           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
941           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
942         }
943       else
944         {
945           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
946             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
947           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
948           commonCellsIPtr++;
949         }
950     }
951   //
952   return ret2.retn();
953 }
954
955 struct MEDCouplingAccVisit
956 {
957   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
958   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
959   int _new_nb_of_nodes;
960 };
961
962 /// @endcond
963
964 /*!
965  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
966  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
967  * array of cell ids. Pay attention that after conversion all algorithms work slower
968  * with \a this mesh than before conversion. <br> If an exception is thrown during the
969  * conversion due presence of invalid ids in the array of cells to convert, as a
970  * result \a this mesh contains some already converted elements. In this case the 2D
971  * mesh remains valid but 3D mesh becomes \b inconsistent!
972  *  \warning This method can significantly modify the order of geometric types in \a this,
973  *          hence, to write this mesh to the MED file, its cells must be sorted using
974  *          sortCellsInMEDFileFrmt().
975  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
976  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
977  *         cellIdsToConvertBg.
978  *  \throw If the coordinates array is not set.
979  *  \throw If the nodal connectivity of cells is node defined.
980  *  \throw If dimension of \a this mesh is not either 2 or 3.
981  *
982  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
983  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
984  */
985 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
986 {
987   checkFullyDefined();
988   int dim=getMeshDimension();
989   if(dim<2 || dim>3)
990     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
991   int nbOfCells=getNumberOfCells();
992   if(dim==2)
993     {
994       const int *connIndex=_nodal_connec_index->getConstPointer();
995       int *conn=_nodal_connec->getPointer();
996       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
997         {
998           if(*iter>=0 && *iter<nbOfCells)
999             {
1000               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1001               if(!cm.isQuadratic())
1002                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1003               else
1004                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1005             }
1006           else
1007             {
1008               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1009               oss << " in range [0," << nbOfCells << ") !";
1010               throw INTERP_KERNEL::Exception(oss.str().c_str());
1011             }
1012         }
1013     }
1014   else
1015     {
1016       int *connIndex=_nodal_connec_index->getPointer();
1017       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1018       const int *connOld=_nodal_connec->getConstPointer();
1019       int connOldLgth=_nodal_connec->getNbOfElems();
1020       std::vector<int> connNew(connOld,connOld+connOldLgth);
1021       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1022         {
1023           if(*iter>=0 && *iter<nbOfCells)
1024             {
1025               int pos=connIndex[*iter];
1026               int posP1=connIndex[(*iter)+1];
1027               int lgthOld=posP1-pos-1;
1028               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1029               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1030               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1031               int *tmp=new int[nbOfFaces*lgthOld];
1032               int *work=tmp;
1033               for(int j=0;j<(int)nbOfFaces;j++)
1034                 {
1035                   INTERP_KERNEL::NormalizedCellType type;
1036                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1037                   work+=offset;
1038                   *work++=-1;
1039                 }
1040               std::size_t newLgth=std::distance(tmp,work)-1;
1041               std::size_t delta=newLgth-lgthOld;
1042               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1043               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1044               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1045               delete [] tmp;
1046             }
1047           else
1048             {
1049               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1050               oss << " in range [0," << nbOfCells << ") !";
1051               throw INTERP_KERNEL::Exception(oss.str().c_str());
1052             }
1053         }
1054       _nodal_connec->alloc((int)connNew.size(),1);
1055       int *newConnPtr=_nodal_connec->getPointer();
1056       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1057     }
1058   computeTypes();
1059 }
1060
1061 /*!
1062  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1063  * polyhedrons (if \a this is a 3D mesh).
1064  *  \warning As this method is purely for user-friendliness and no optimization is
1065  *          done to avoid construction of a useless vector, this method can be costly
1066  *          in memory.
1067  *  \throw If the coordinates array is not set.
1068  *  \throw If the nodal connectivity of cells is node defined.
1069  *  \throw If dimension of \a this mesh is not either 2 or 3.
1070  */
1071 void MEDCouplingUMesh::convertAllToPoly()
1072 {
1073   int nbOfCells=getNumberOfCells();
1074   std::vector<int> cellIds(nbOfCells);
1075   for(int i=0;i<nbOfCells;i++)
1076     cellIds[i]=i;
1077   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1078 }
1079
1080 /*!
1081  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1082  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1083  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1084  * base facet of the volume and the second half of nodes describes an opposite facet
1085  * having the same number of nodes as the base one. This method converts such
1086  * connectivity to a valid polyhedral format where connectivity of each facet is
1087  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1088  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1089  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1090  * a correct orientation of the first facet of a polyhedron, else orientation of a
1091  * corrected cell is reverse.<br>
1092  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1093  * it releases the user from boring description of polyhedra connectivity in the valid
1094  * format.
1095  *  \throw If \a this->getMeshDimension() != 3.
1096  *  \throw If \a this->getSpaceDimension() != 3.
1097  *  \throw If the nodal connectivity of cells is not defined.
1098  *  \throw If the coordinates array is not set.
1099  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1100  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1101  *
1102  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1103  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1104  */
1105 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1106 {
1107   checkFullyDefined();
1108   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1109     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1110   int nbOfCells=getNumberOfCells();
1111   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1112   newCi->alloc(nbOfCells+1,1);
1113   int *newci=newCi->getPointer();
1114   const int *ci=_nodal_connec_index->getConstPointer();
1115   const int *c=_nodal_connec->getConstPointer();
1116   newci[0]=0;
1117   for(int i=0;i<nbOfCells;i++)
1118     {
1119       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1120       if(type==INTERP_KERNEL::NORM_POLYHED)
1121         {
1122           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1123             {
1124               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1125               throw INTERP_KERNEL::Exception(oss.str().c_str());
1126             }
1127           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1128           if(n2%2!=0)
1129             {
1130               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 !";
1131               throw INTERP_KERNEL::Exception(oss.str().c_str());
1132             }
1133           int n1=(int)(n2/2);
1134           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)
1135         }
1136       else
1137         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1138     }
1139   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1140   newC->alloc(newci[nbOfCells],1);
1141   int *newc=newC->getPointer();
1142   for(int i=0;i<nbOfCells;i++)
1143     {
1144       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1145       if(type==INTERP_KERNEL::NORM_POLYHED)
1146         {
1147           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1148           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1149           *newc++=-1;
1150           for(std::size_t j=0;j<n1;j++)
1151             {
1152               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1153               newc[n1+5*j]=-1;
1154               newc[n1+5*j+1]=c[ci[i]+1+j];
1155               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1156               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1157               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1158             }
1159           newc+=n1*6;
1160         }
1161       else
1162         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1163     }
1164   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1165   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1166 }
1167
1168
1169 /*!
1170  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1171  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1172  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1173  *          to write this mesh to the MED file, its cells must be sorted using
1174  *          sortCellsInMEDFileFrmt().
1175  * \return \c true if at least one cell has been converted, \c false else. In the
1176  *         last case the nodal connectivity remains unchanged.
1177  * \throw If the coordinates array is not set.
1178  * \throw If the nodal connectivity of cells is not defined.
1179  * \throw If \a this->getMeshDimension() < 0.
1180  */
1181 bool MEDCouplingUMesh::unPolyze()
1182 {
1183   checkFullyDefined();
1184   int mdim=getMeshDimension();
1185   if(mdim<0)
1186     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1187   if(mdim<=1)
1188     return false;
1189   int nbOfCells=getNumberOfCells();
1190   if(nbOfCells<1)
1191     return false;
1192   int initMeshLgth=getMeshLength();
1193   int *conn=_nodal_connec->getPointer();
1194   int *index=_nodal_connec_index->getPointer();
1195   int posOfCurCell=0;
1196   int newPos=0;
1197   int lgthOfCurCell;
1198   bool ret=false;
1199   for(int i=0;i<nbOfCells;i++)
1200     {
1201       lgthOfCurCell=index[i+1]-posOfCurCell;
1202       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1203       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1204       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1205       int newLgth;
1206       if(cm.isDynamic())
1207         {
1208           switch(cm.getDimension())
1209             {
1210             case 2:
1211               {
1212                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1213                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1214                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1215                 break;
1216               }
1217             case 3:
1218               {
1219                 int nbOfFaces,lgthOfPolyhConn;
1220                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1221                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1222                 break;
1223               }
1224             case 1:
1225               {
1226                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1227                 break;
1228               }
1229             }
1230           ret=ret || (newType!=type);
1231           conn[newPos]=newType;
1232           newPos+=newLgth+1;
1233           posOfCurCell=index[i+1];
1234           index[i+1]=newPos;
1235         }
1236       else
1237         {
1238           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1239           newPos+=lgthOfCurCell;
1240           posOfCurCell+=lgthOfCurCell;
1241           index[i+1]=newPos;
1242         }
1243     }
1244   if(newPos!=initMeshLgth)
1245     _nodal_connec->reAlloc(newPos);
1246   if(ret)
1247     computeTypes();
1248   return ret;
1249 }
1250
1251 /*!
1252  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1253  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1254  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1255  *
1256  * \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 
1257  *             precision.
1258  */
1259 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1260 {
1261   checkFullyDefined();
1262   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1263     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1264   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1265   coords->recenterForMaxPrecision(eps);
1266   //
1267   int nbOfCells=getNumberOfCells();
1268   const int *conn=_nodal_connec->getConstPointer();
1269   const int *index=_nodal_connec_index->getConstPointer();
1270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1271   connINew->alloc(nbOfCells+1,1);
1272   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1274   bool changed=false;
1275   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1276     {
1277       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1278         {
1279           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1280           changed=true;
1281         }
1282       else
1283         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1284       *connINewPtr=connNew->getNumberOfTuples();
1285     }
1286   if(changed)
1287     setConnectivity(connNew,connINew,false);
1288 }
1289
1290 /*!
1291  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1292  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1293  * the format of returned DataArrayInt instance.
1294  * 
1295  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1296  * \sa MEDCouplingUMesh::getNodeIdsInUse
1297  */
1298 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1299 {
1300   checkConnectivityFullyDefined();
1301   int nbOfCells=getNumberOfCells();
1302   const int *connIndex=_nodal_connec_index->getConstPointer();
1303   const int *conn=_nodal_connec->getConstPointer();
1304   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1305   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1306   std::vector<bool> retS(maxElt,false);
1307   for(int i=0;i<nbOfCells;i++)
1308     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1309       if(conn[j]>=0)
1310         retS[conn[j]]=true;
1311   int sz=0;
1312   for(int i=0;i<maxElt;i++)
1313     if(retS[i])
1314       sz++;
1315   DataArrayInt *ret=DataArrayInt::New();
1316   ret->alloc(sz,1);
1317   int *retPtr=ret->getPointer();
1318   for(int i=0;i<maxElt;i++)
1319     if(retS[i])
1320       *retPtr++=i;
1321   return ret;
1322 }
1323
1324 /*!
1325  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1326  * \sa MEDCouplingUMesh::getNodeIdsInUse
1327  */
1328 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1329 {
1330   int nbOfNodes=(int)nodeIdsInUse.size();
1331   int nbOfCells=getNumberOfCells();
1332   const int *connIndex=_nodal_connec_index->getConstPointer();
1333   const int *conn=_nodal_connec->getConstPointer();
1334   for(int i=0;i<nbOfCells;i++)
1335     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1336       if(conn[j]>=0)
1337         {
1338           if(conn[j]<nbOfNodes)
1339             nodeIdsInUse[conn[j]]=true;
1340           else
1341             {
1342               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1343               throw INTERP_KERNEL::Exception(oss.str().c_str());
1344             }
1345         }
1346 }
1347
1348 /*!
1349  * Finds nodes not used in any cell and returns an array giving a new id to every node
1350  * by excluding the unused nodes, for which the array holds -1. The result array is
1351  * a mapping in "Old to New" mode. 
1352  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1353  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1354  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1355  *          if the node is unused or a new id else. The caller is to delete this
1356  *          array using decrRef() as it is no more needed.  
1357  *  \throw If the coordinates array is not set.
1358  *  \throw If the nodal connectivity of cells is not defined.
1359  *  \throw If the nodal connectivity includes an invalid id.
1360  *
1361  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1362  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1363  * \sa computeNodeIdsAlg()
1364  */
1365 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1366 {
1367   nbrOfNodesInUse=-1;
1368   int nbOfNodes=getNumberOfNodes();
1369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1370   ret->alloc(nbOfNodes,1);
1371   int *traducer=ret->getPointer();
1372   std::fill(traducer,traducer+nbOfNodes,-1);
1373   int nbOfCells=getNumberOfCells();
1374   const int *connIndex=_nodal_connec_index->getConstPointer();
1375   const int *conn=_nodal_connec->getConstPointer();
1376   for(int i=0;i<nbOfCells;i++)
1377     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1378       if(conn[j]>=0)
1379         {
1380           if(conn[j]<nbOfNodes)
1381             traducer[conn[j]]=1;
1382           else
1383             {
1384               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1385               throw INTERP_KERNEL::Exception(oss.str().c_str());
1386             }
1387         }
1388   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1389   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1390   return ret.retn();
1391 }
1392
1393 /*!
1394  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1395  * For each cell in \b this the number of nodes constituting cell is computed.
1396  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1397  * So for pohyhedrons some nodes can be counted several times in the returned result.
1398  * 
1399  * \return a newly allocated array
1400  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1401  */
1402 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1403 {
1404   checkConnectivityFullyDefined();
1405   int nbOfCells=getNumberOfCells();
1406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1407   ret->alloc(nbOfCells,1);
1408   int *retPtr=ret->getPointer();
1409   const int *conn=getNodalConnectivity()->getConstPointer();
1410   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1411   for(int i=0;i<nbOfCells;i++,retPtr++)
1412     {
1413       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1414         *retPtr=connI[i+1]-connI[i]-1;
1415       else
1416         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1417     }
1418   return ret.retn();
1419 }
1420
1421 /*!
1422  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1423  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1424  *
1425  * \return DataArrayInt * - new object to be deallocated by the caller.
1426  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1427  */
1428 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1429 {
1430   checkConnectivityFullyDefined();
1431   int nbOfCells=getNumberOfCells();
1432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1433   ret->alloc(nbOfCells,1);
1434   int *retPtr=ret->getPointer();
1435   const int *conn=getNodalConnectivity()->getConstPointer();
1436   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1437   for(int i=0;i<nbOfCells;i++,retPtr++)
1438     {
1439       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1440       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1441         *retPtr=(int)s.size();
1442       else
1443         {
1444           s.erase(-1);
1445           *retPtr=(int)s.size();
1446         }
1447     }
1448   return ret.retn();
1449 }
1450
1451 /*!
1452  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1453  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1454  * 
1455  * \return a newly allocated array
1456  */
1457 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1458 {
1459   checkConnectivityFullyDefined();
1460   int nbOfCells=getNumberOfCells();
1461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1462   ret->alloc(nbOfCells,1);
1463   int *retPtr=ret->getPointer();
1464   const int *conn=getNodalConnectivity()->getConstPointer();
1465   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1466   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1467     {
1468       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1469       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1470     }
1471   return ret.retn();
1472 }
1473
1474 /*!
1475  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1476  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1477  * array mean that the corresponding old node is no more used. 
1478  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1479  *           this->getNumberOfNodes() before call of this method. The caller is to
1480  *           delete this array using decrRef() as it is no more needed. 
1481  *  \throw If the coordinates array is not set.
1482  *  \throw If the nodal connectivity of cells is not defined.
1483  *  \throw If the nodal connectivity includes an invalid id.
1484  *
1485  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1486  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1487  */
1488 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1489 {
1490   return MEDCouplingPointSet::zipCoordsTraducer();
1491 }
1492
1493 /*!
1494  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1495  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1496  */
1497 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1498 {
1499   switch(compType)
1500     {
1501     case 0:
1502       return AreCellsEqual0(conn,connI,cell1,cell2);
1503     case 1:
1504       return AreCellsEqual1(conn,connI,cell1,cell2);
1505     case 2:
1506       return AreCellsEqual2(conn,connI,cell1,cell2);
1507     case 3:
1508       return AreCellsEqual3(conn,connI,cell1,cell2);
1509     case 7:
1510       return AreCellsEqual7(conn,connI,cell1,cell2);
1511     }
1512   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1513 }
1514
1515 /*!
1516  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1517  */
1518 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1519 {
1520   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1521     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1522   return 0;
1523 }
1524
1525 /*!
1526  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1527  */
1528 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1529 {
1530   int sz=connI[cell1+1]-connI[cell1];
1531   if(sz==connI[cell2+1]-connI[cell2])
1532     {
1533       if(conn[connI[cell1]]==conn[connI[cell2]])
1534         {
1535           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1536           unsigned dim=cm.getDimension();
1537           if(dim!=3)
1538             {
1539               if(dim!=1)
1540                 {
1541                   int sz1=2*(sz-1);
1542                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1543                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1544                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1545                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1546                   return work!=tmp+sz1?1:0;
1547                 }
1548               else
1549                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1550             }
1551           else
1552             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1553         }
1554     }
1555   return 0;
1556 }
1557
1558 /*!
1559  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1560  */
1561 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1562 {
1563   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1564     {
1565       if(conn[connI[cell1]]==conn[connI[cell2]])
1566         {
1567           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1568           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1569           return s1==s2?1:0;
1570         }
1571     }
1572   return 0;
1573 }
1574
1575 /*!
1576  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1577  */
1578 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1579 {
1580   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1581     {
1582       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1583       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1584       return s1==s2?1:0;
1585     }
1586   return 0;
1587 }
1588
1589 /*!
1590  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1591  */
1592 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1593 {
1594   int sz=connI[cell1+1]-connI[cell1];
1595   if(sz==connI[cell2+1]-connI[cell2])
1596     {
1597       if(conn[connI[cell1]]==conn[connI[cell2]])
1598         {
1599           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1600           unsigned dim=cm.getDimension();
1601           if(dim!=3)
1602             {
1603               if(dim!=1)
1604                 {
1605                   int sz1=2*(sz-1);
1606                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1607                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1608                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1609                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1610                   if(work!=tmp+sz1)
1611                     return 1;
1612                   else
1613                     {
1614                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1615                       std::reverse_iterator<int *> it2((int *)tmp);
1616                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1617                         return 2;
1618                       else
1619                         return 0;
1620                     }
1621                   
1622                   return work!=tmp+sz1?1:0;
1623                 }
1624               else
1625                 {//case of SEG2 and SEG3
1626                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1627                     return 1;
1628                   if(!cm.isQuadratic())
1629                     {
1630                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1631                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1632                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1633                         return 2;
1634                       return 0;
1635                     }
1636                   else
1637                     {
1638                       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])
1639                         return 2;
1640                       return 0;
1641                     }
1642                 }
1643             }
1644           else
1645             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1646         }
1647     }
1648   return 0;
1649 }
1650
1651 /*!
1652  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1653  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1654  * and result remains unchanged.
1655  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1656  * If in 'candidates' pool -1 value is considered as an empty value.
1657  * WARNING this method returns only ONE set of result !
1658  */
1659 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1660 {
1661   if(candidates.size()<1)
1662     return false;
1663   bool ret=false;
1664   std::vector<int>::const_iterator iter=candidates.begin();
1665   int start=(*iter++);
1666   for(;iter!=candidates.end();iter++)
1667     {
1668       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1669       if(status!=0)
1670         {
1671           if(!ret)
1672             {
1673               result->pushBackSilent(start);
1674               ret=true;
1675             }
1676           if(status==1)
1677             result->pushBackSilent(*iter);
1678           else
1679             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1680         }
1681     }
1682   return ret;
1683 }
1684
1685 /*!
1686  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1687  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1688  *
1689  * \param [in] compType input specifying the technique used to compare cells each other.
1690  *   - 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.
1691  *   - 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)
1692  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1693  *   - 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
1694  * can be used for users not sensitive to orientation of cell
1695  * \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.
1696  * \param [out] commonCells
1697  * \param [out] commonCellsI
1698  * \return the correspondance array old to new in a newly allocated array.
1699  * 
1700  */
1701 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1702 {
1703   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1704   getReverseNodalConnectivity(revNodal,revNodalI);
1705   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1706 }
1707
1708 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1709                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1710 {
1711   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1712   int nbOfCells=nodalI->getNumberOfTuples()-1;
1713   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1714   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1715   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1716   std::vector<bool> isFetched(nbOfCells,false);
1717   if(startCellId==0)
1718     {
1719       for(int i=0;i<nbOfCells;i++)
1720         {
1721           if(!isFetched[i])
1722             {
1723               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1724               std::vector<int> v,v2;
1725               if(connOfNode!=connPtr+connIPtr[i+1])
1726                 {
1727                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1728                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1729                   connOfNode++;
1730                 }
1731               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1732                 if(*connOfNode>=0)
1733                   {
1734                     v=v2;
1735                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1736                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1737                     v2.resize(std::distance(v2.begin(),it));
1738                   }
1739               if(v2.size()>1)
1740                 {
1741                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1742                     {
1743                       int pos=commonCellsI->back();
1744                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1745                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1746                         isFetched[*it]=true;
1747                     }
1748                 }
1749             }
1750         }
1751     }
1752   else
1753     {
1754       for(int i=startCellId;i<nbOfCells;i++)
1755         {
1756           if(!isFetched[i])
1757             {
1758               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1759               std::vector<int> v,v2;
1760               if(connOfNode!=connPtr+connIPtr[i+1])
1761                 {
1762                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1763                   connOfNode++;
1764                 }
1765               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1766                 if(*connOfNode>=0)
1767                   {
1768                     v=v2;
1769                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1770                     v2.resize(std::distance(v2.begin(),it));
1771                   }
1772               if(v2.size()>1)
1773                 {
1774                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1775                     {
1776                       int pos=commonCellsI->back();
1777                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1778                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1779                         isFetched[*it]=true;
1780                     }
1781                 }
1782             }
1783         }
1784     }
1785   commonCellsArr=commonCells.retn();
1786   commonCellsIArr=commonCellsI.retn();
1787 }
1788
1789 /*!
1790  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1791  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1792  * than \a other->getNumberOfCells() in the returned array means that there is no
1793  * corresponding cell in \a this mesh.
1794  * It is expected that \a this and \a other meshes share the same node coordinates
1795  * array, if it is not so an exception is thrown. 
1796  *  \param [in] other - the mesh to compare with.
1797  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1798  *         valid values [0,1,2], see zipConnectivityTraducer().
1799  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1800  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1801  *         values. The caller is to delete this array using
1802  *         decrRef() as it is no more needed.
1803  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1804  *         mesh.
1805  *
1806  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1807  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1808  *  \sa checkDeepEquivalOnSameNodesWith()
1809  *  \sa checkGeoEquivalWith()
1810  */
1811 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1812 {
1813   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1814   int nbOfCells=getNumberOfCells();
1815   static const int possibleCompType[]={0,1,2};
1816   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1817     {
1818       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1819       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1820       oss << " !";
1821       throw INTERP_KERNEL::Exception(oss.str().c_str());
1822     }
1823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1824   arr=o2n->substr(nbOfCells);
1825   arr->setName(other->getName().c_str());
1826   int tmp;
1827   if(other->getNumberOfCells()==0)
1828     return true;
1829   return arr->getMaxValue(tmp)<nbOfCells;
1830 }
1831
1832 /*!
1833  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1834  * This method tries to determine if \b other is fully included in \b this.
1835  * The main difference is that this method is not expected to throw exception.
1836  * This method has two outputs :
1837  *
1838  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1839  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1840  */
1841 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1842 {
1843   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1844   DataArrayInt *commonCells=0,*commonCellsI=0;
1845   int thisNbCells=getNumberOfCells();
1846   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1847   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1848   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1849   int otherNbCells=other->getNumberOfCells();
1850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1851   arr2->alloc(otherNbCells,1);
1852   arr2->fillWithZero();
1853   int *arr2Ptr=arr2->getPointer();
1854   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1855   for(int i=0;i<nbOfCommon;i++)
1856     {
1857       int start=commonCellsPtr[commonCellsIPtr[i]];
1858       if(start<thisNbCells)
1859         {
1860           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1861             {
1862               int sig=commonCellsPtr[j]>0?1:-1;
1863               int val=std::abs(commonCellsPtr[j])-1;
1864               if(val>=thisNbCells)
1865                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1866             }
1867         }
1868     }
1869   arr2->setName(other->getName().c_str());
1870   if(arr2->presenceOfValue(0))
1871     return false;
1872   arr=arr2.retn();
1873   return true;
1874 }
1875
1876 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1877 {
1878   if(!other)
1879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1880   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1881   if(!otherC)
1882     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1883   std::vector<const MEDCouplingUMesh *> ms(2);
1884   ms[0]=this;
1885   ms[1]=otherC;
1886   return MergeUMeshesOnSameCoords(ms);
1887 }
1888
1889 /*!
1890  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1891  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1892  * cellIds is not given explicitely but by a range python like.
1893  * 
1894  * \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.
1895  * \return a newly allocated
1896  * 
1897  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1898  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1899  */
1900 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1901 {
1902   if(getMeshDimension()!=-1)
1903     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1904   else
1905     {
1906       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1907       if(newNbOfCells!=1)
1908         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1909       if(start!=0)
1910         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1911       incrRef();
1912       return const_cast<MEDCouplingUMesh *>(this);
1913     }
1914 }
1915
1916 /*!
1917  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1918  * The result mesh shares or not the node coordinates array with \a this mesh depending
1919  * on \a keepCoords parameter.
1920  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1921  *           to write this mesh to the MED file, its cells must be sorted using
1922  *           sortCellsInMEDFileFrmt().
1923  *  \param [in] begin - an array of cell ids to include to the new mesh.
1924  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1925  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1926  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1927  *         by calling zipCoords().
1928  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1929  *         to delete this mesh using decrRef() as it is no more needed. 
1930  *  \throw If the coordinates array is not set.
1931  *  \throw If the nodal connectivity of cells is not defined.
1932  *  \throw If any cell id in the array \a begin is not valid.
1933  *
1934  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1935  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1936  */
1937 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1938 {
1939   if(getMeshDimension()!=-1)
1940     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1941   else
1942     {
1943       if(end-begin!=1)
1944         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1945       if(begin[0]!=0)
1946         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1947       incrRef();
1948       return const_cast<MEDCouplingUMesh *>(this);
1949     }
1950 }
1951
1952 /*!
1953  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1954  *
1955  * 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.
1956  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1957  * The number of cells of \b this will remain the same with this method.
1958  *
1959  * \param [in] begin begin of cell ids (included) of cells in this to assign
1960  * \param [in] end end of cell ids (excluded) of cells in this to assign
1961  * \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 ).
1962  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1963  */
1964 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1965 {
1966   checkConnectivityFullyDefined();
1967   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1968   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1970   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1971     {
1972       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1973       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1974       throw INTERP_KERNEL::Exception(oss.str().c_str());
1975     }
1976   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1977   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1978     {
1979       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1980       throw INTERP_KERNEL::Exception(oss.str().c_str());
1981     }
1982   int nbOfCells=getNumberOfCells();
1983   bool easyAssign=true;
1984   const int *connI=_nodal_connec_index->getConstPointer();
1985   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1986   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1987     {
1988       if(*it>=0 && *it<nbOfCells)
1989         {
1990           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1991         }
1992       else
1993         {
1994           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1995           throw INTERP_KERNEL::Exception(oss.str().c_str());
1996         }
1997     }
1998   if(easyAssign)
1999     {
2000       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2001       computeTypes();
2002     }
2003   else
2004     {
2005       DataArrayInt *arrOut=0,*arrIOut=0;
2006       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2007                                                arrOut,arrIOut);
2008       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2009       setConnectivity(arrOut,arrIOut,true);
2010     }
2011 }
2012
2013 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2014 {
2015   checkConnectivityFullyDefined();
2016   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2017   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2018     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2019   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2020     {
2021       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2022       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2023       throw INTERP_KERNEL::Exception(oss.str().c_str());
2024     }
2025   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2026   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2027     {
2028       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2029       throw INTERP_KERNEL::Exception(oss.str().c_str());
2030     }
2031   int nbOfCells=getNumberOfCells();
2032   bool easyAssign=true;
2033   const int *connI=_nodal_connec_index->getConstPointer();
2034   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2035   int it=start;
2036   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2037     {
2038       if(it>=0 && it<nbOfCells)
2039         {
2040           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2041         }
2042       else
2043         {
2044           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2045           throw INTERP_KERNEL::Exception(oss.str().c_str());
2046         }
2047     }
2048   if(easyAssign)
2049     {
2050       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2051       computeTypes();
2052     }
2053   else
2054     {
2055       DataArrayInt *arrOut=0,*arrIOut=0;
2056       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2057                                                 arrOut,arrIOut);
2058       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2059       setConnectivity(arrOut,arrIOut,true);
2060     }
2061 }                      
2062
2063 /*!
2064  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2065  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2066  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2067  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2068  *
2069  * \param [in] begin input start of array of node ids.
2070  * \param [in] end input end of array of node ids.
2071  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2072  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2073  */
2074 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2075 {
2076   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2077   checkConnectivityFullyDefined();
2078   int tmp=-1;
2079   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2080   std::vector<bool> fastFinder(sz,false);
2081   for(const int *work=begin;work!=end;work++)
2082     if(*work>=0 && *work<sz)
2083       fastFinder[*work]=true;
2084   int nbOfCells=getNumberOfCells();
2085   const int *conn=getNodalConnectivity()->getConstPointer();
2086   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2087   for(int i=0;i<nbOfCells;i++)
2088     {
2089       int ref=0,nbOfHit=0;
2090       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2091         if(*work2>=0)
2092           {
2093             ref++;
2094             if(fastFinder[*work2])
2095               nbOfHit++;
2096           }
2097       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2098         cellIdsKept->pushBackSilent(i);
2099     }
2100   cellIdsKeptArr=cellIdsKept.retn();
2101 }
2102
2103 /*!
2104  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2105  * this->getMeshDimension(), that bound some cells of \a this mesh.
2106  * The cells of lower dimension to include to the result mesh are selected basing on
2107  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2108  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2109  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2110  * created mesh shares the node coordinates array with \a this mesh. 
2111  *  \param [in] begin - the array of node ids.
2112  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2113  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2114  *         array \a begin are added, else cells whose any node is in the
2115  *         array \a begin are added.
2116  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2117  *         to delete this mesh using decrRef() as it is no more needed. 
2118  *  \throw If the coordinates array is not set.
2119  *  \throw If the nodal connectivity of cells is not defined.
2120  *  \throw If any node id in \a begin is not valid.
2121  *
2122  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2123  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2124  */
2125 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2126 {
2127   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2128   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2129   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2130   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2131   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2132 }
2133
2134 /*!
2135  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2136  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2137  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2138  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2139  *         by calling zipCoords().
2140  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2141  *         to delete this mesh using decrRef() as it is no more needed. 
2142  *  \throw If the coordinates array is not set.
2143  *  \throw If the nodal connectivity of cells is not defined.
2144  *
2145  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2146  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2147  */
2148 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2149 {
2150   DataArrayInt *desc=DataArrayInt::New();
2151   DataArrayInt *descIndx=DataArrayInt::New();
2152   DataArrayInt *revDesc=DataArrayInt::New();
2153   DataArrayInt *revDescIndx=DataArrayInt::New();
2154   //
2155   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2156   revDesc->decrRef();
2157   desc->decrRef();
2158   descIndx->decrRef();
2159   int nbOfCells=meshDM1->getNumberOfCells();
2160   const int *revDescIndxC=revDescIndx->getConstPointer();
2161   std::vector<int> boundaryCells;
2162   for(int i=0;i<nbOfCells;i++)
2163     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2164       boundaryCells.push_back(i);
2165   revDescIndx->decrRef();
2166   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2167   return ret;
2168 }
2169
2170 /*!
2171  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2172  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2173  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2174  */
2175 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2176 {
2177   checkFullyDefined();
2178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2182   //
2183   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2184   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2185   //
2186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2188   const int *revDescPtr=revDesc->getConstPointer();
2189   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2190   int nbOfCells=getNumberOfCells();
2191   std::vector<bool> ret1(nbOfCells,false);
2192   int sz=0;
2193   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2194     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2195       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2196   //
2197   DataArrayInt *ret2=DataArrayInt::New();
2198   ret2->alloc(sz,1);
2199   int *ret2Ptr=ret2->getPointer();
2200   sz=0;
2201   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2202     if(*it)
2203       *ret2Ptr++=sz;
2204   ret2->setName("BoundaryCells");
2205   return ret2;
2206 }
2207
2208 /*!
2209  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2210  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2211  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2212  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2213  *
2214  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2215  * This method method returns cells ids set s = s1 + s2 where :
2216  * 
2217  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2218  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2219  *
2220  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2221  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2222  *
2223  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2224  * \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
2225  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2226  */
2227 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2228 {
2229   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2230     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2231   checkConnectivityFullyDefined();
2232   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2233   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2234     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2237   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2239   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2240   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2241   DataArrayInt *idsOtherInConsti=0;
2242   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2244   if(!b)
2245     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2246   std::set<int> s1;
2247   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2248     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2249   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2251   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2252   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2254   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2255   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2256   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2257   neighThisPartAuto=0;
2258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2259   const int li[2]={0,1};
2260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2261   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2263   s_renum1->sort();
2264   //
2265   cellIdsRk0=s0arr.retn();
2266   cellIdsRk1=s_renum1.retn();
2267 }
2268
2269 /*!
2270  * 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
2271  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2272  * 
2273  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2274  */
2275 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2276 {
2277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2281   //
2282   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2283   revDesc=0; desc=0; descIndx=0;
2284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2286   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2287 }
2288
2289 /*!
2290  * Finds nodes lying on the boundary of \a this mesh.
2291  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2292  *          nodes. The caller is to delete this array using decrRef() as it is no
2293  *          more needed.
2294  *  \throw If the coordinates array is not set.
2295  *  \throw If the nodal connectivity of cells is node defined.
2296  *
2297  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2298  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2299  */
2300 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2301 {
2302   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2303   return skin->computeFetchedNodeIds();
2304 }
2305
2306 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2307 {
2308   incrRef();
2309   return const_cast<MEDCouplingUMesh *>(this);
2310 }
2311
2312 /*!
2313  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2314  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2315  * 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.
2316  * 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.
2317  * 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.
2318  *
2319  * \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
2320  *             parameter is altered during the call.
2321  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2322  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2323  * \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.
2324  *
2325  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2326  */
2327 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2328                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2329 {
2330   checkFullyDefined();
2331   otherDimM1OnSameCoords.checkFullyDefined();
2332   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2334   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2335     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2336   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2337   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2340   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2341   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2345   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2346   //
2347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2349   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2350   DataArrayInt *idsTmp=0;
2351   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2353   if(!b)
2354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2355   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2356   DataArrayInt *tmp0=0,*tmp1=0;
2357   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2362   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2363   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2364   //
2365   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2366   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2367   nodeIdsToDuplicate=s3.retn();
2368 }
2369
2370 /*!
2371  * This method operates a modification of the connectivity and coords in \b this.
2372  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2373  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2374  * 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
2375  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2376  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2377  * 
2378  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2379  * 
2380  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2381  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2382  */
2383 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2384 {
2385   int nbOfNodes=getNumberOfNodes();
2386   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2387   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2388 }
2389
2390 /*!
2391  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2392  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2393  * This method is a generalization of shiftNodeNumbersInConn().
2394  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2395  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2396  *         this->getNumberOfNodes(), in "Old to New" mode. 
2397  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2398  *  \throw If the nodal connectivity of cells is not defined.
2399  *
2400  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2401  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2402  */
2403 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2404 {
2405   checkConnectivityFullyDefined();
2406   int *conn=getNodalConnectivity()->getPointer();
2407   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2408   int nbOfCells=getNumberOfCells();
2409   for(int i=0;i<nbOfCells;i++)
2410     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2411       {
2412         int& node=conn[iconn];
2413         if(node>=0)//avoid polyhedron separator
2414           {
2415             node=newNodeNumbersO2N[node];
2416           }
2417       }
2418   _nodal_connec->declareAsNew();
2419   updateTime();
2420 }
2421
2422 /*!
2423  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2424  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2425  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2426  * 
2427  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2428  */
2429 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2430 {
2431   checkConnectivityFullyDefined();
2432   int *conn=getNodalConnectivity()->getPointer();
2433   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2434   int nbOfCells=getNumberOfCells();
2435   for(int i=0;i<nbOfCells;i++)
2436     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2437       {
2438         int& node=conn[iconn];
2439         if(node>=0)//avoid polyhedron separator
2440           {
2441             node+=delta;
2442           }
2443       }
2444   _nodal_connec->declareAsNew();
2445   updateTime();
2446 }
2447
2448 /*!
2449  * This method operates a modification of the connectivity in \b this.
2450  * 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.
2451  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2452  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2453  * 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
2454  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2455  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2456  * 
2457  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2458  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2459  * 
2460  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2461  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2462  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2463  */
2464 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2465 {
2466   checkConnectivityFullyDefined();
2467   std::map<int,int> m;
2468   int val=offset;
2469   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2470     m[*work]=val;
2471   int *conn=getNodalConnectivity()->getPointer();
2472   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2473   int nbOfCells=getNumberOfCells();
2474   for(int i=0;i<nbOfCells;i++)
2475     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2476       {
2477         int& node=conn[iconn];
2478         if(node>=0)//avoid polyhedron separator
2479           {
2480             std::map<int,int>::iterator it=m.find(node);
2481             if(it!=m.end())
2482               node=(*it).second;
2483           }
2484       }
2485   updateTime();
2486 }
2487
2488 /*!
2489  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2490  *
2491  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2492  * After the call of this method the number of cells remains the same as before.
2493  *
2494  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2495  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2496  * be strictly in [0;this->getNumberOfCells()).
2497  *
2498  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2499  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2500  * should be contained in[0;this->getNumberOfCells()).
2501  * 
2502  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2503  */
2504 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2505 {
2506   checkConnectivityFullyDefined();
2507   int nbCells=getNumberOfCells();
2508   const int *array=old2NewBg;
2509   if(check)
2510     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2511   //
2512   const int *conn=_nodal_connec->getConstPointer();
2513   const int *connI=_nodal_connec_index->getConstPointer();
2514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2516   const int *n2oPtr=n2o->begin();
2517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2518   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2519   newConn->copyStringInfoFrom(*_nodal_connec);
2520   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2521   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2522   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2523   //
2524   int *newC=newConn->getPointer();
2525   int *newCI=newConnI->getPointer();
2526   int loc=0;
2527   newCI[0]=loc;
2528   for(int i=0;i<nbCells;i++)
2529     {
2530       int pos=n2oPtr[i];
2531       int nbOfElts=connI[pos+1]-connI[pos];
2532       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2533       loc+=nbOfElts;
2534       newCI[i+1]=loc;
2535     }
2536   //
2537   setConnectivity(newConn,newConnI);
2538   if(check)
2539     free(const_cast<int *>(array));
2540 }
2541
2542 /*!
2543  * Finds cells whose bounding boxes intersect a given bounding box.
2544  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2545  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2546  *         zMax (if in 3D). 
2547  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2548  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2549  *         extent of the bounding box of cell to produce an addition to this bounding box.
2550  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2551  *         cells. The caller is to delete this array using decrRef() as it is no more
2552  *         needed. 
2553  *  \throw If the coordinates array is not set.
2554  *  \throw If the nodal connectivity of cells is not defined.
2555  *
2556  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2557  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2558  */
2559 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2560 {
2561   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2562   if(getMeshDimension()==-1)
2563     {
2564       elems->pushBackSilent(0);
2565       return elems.retn();
2566     }
2567   int dim=getSpaceDimension();
2568   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2569   const int* conn      = getNodalConnectivity()->getConstPointer();
2570   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2571   const double* coords = getCoords()->getConstPointer();
2572   int nbOfCells=getNumberOfCells();
2573   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2574     {
2575       for (int i=0; i<dim; i++)
2576         {
2577           elem_bb[i*2]=std::numeric_limits<double>::max();
2578           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2579         }
2580
2581       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2582         {
2583           int node= conn[inode];
2584           if(node>=0)//avoid polyhedron separator
2585             {
2586               for (int idim=0; idim<dim; idim++)
2587                 {
2588                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2589                     {
2590                       elem_bb[idim*2] = coords[node*dim+idim] ;
2591                     }
2592                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2593                     {
2594                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2595                     }
2596                 }
2597             }
2598         }
2599       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2600         elems->pushBackSilent(ielem);
2601     }
2602   return elems.retn();
2603 }
2604
2605 /*!
2606  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2607  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2608  * added in 'elems' parameter.
2609  */
2610 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2611 {
2612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2613   if(getMeshDimension()==-1)
2614     {
2615       elems->pushBackSilent(0);
2616       return elems.retn();
2617     }
2618   int dim=getSpaceDimension();
2619   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2620   const int* conn      = getNodalConnectivity()->getConstPointer();
2621   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2622   const double* coords = getCoords()->getConstPointer();
2623   int nbOfCells=getNumberOfCells();
2624   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2625     {
2626       for (int i=0; i<dim; i++)
2627         {
2628           elem_bb[i*2]=std::numeric_limits<double>::max();
2629           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2630         }
2631
2632       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2633         {
2634           int node= conn[inode];
2635           if(node>=0)//avoid polyhedron separator
2636             {
2637               for (int idim=0; idim<dim; idim++)
2638                 {
2639                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2640                     {
2641                       elem_bb[idim*2] = coords[node*dim+idim] ;
2642                     }
2643                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2644                     {
2645                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2646                     }
2647                 }
2648             }
2649         }
2650       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2651         elems->pushBackSilent(ielem);
2652     }
2653   return elems.retn();
2654 }
2655
2656 /*!
2657  * Returns a type of a cell by its id.
2658  *  \param [in] cellId - the id of the cell of interest.
2659  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2660  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2661  */
2662 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2663 {
2664   const int *ptI=_nodal_connec_index->getConstPointer();
2665   const int *pt=_nodal_connec->getConstPointer();
2666   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2667     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2668   else
2669     {
2670       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2671       throw INTERP_KERNEL::Exception(oss.str().c_str());
2672     }
2673 }
2674
2675 /*!
2676  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2677  * This method does not throw exception if geometric type \a type is not in \a this.
2678  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2679  * The coordinates array is not considered here.
2680  *
2681  * \param [in] type the geometric type
2682  * \return cell ids in this having geometric type \a type.
2683  */
2684 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2685 {
2686   
2687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2688   ret->alloc(0,1);
2689   checkConnectivityFullyDefined();
2690   int nbCells=getNumberOfCells();
2691   int mdim=getMeshDimension();
2692   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2693   if(mdim!=(int)cm.getDimension())
2694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2695   const int *ptI=_nodal_connec_index->getConstPointer();
2696   const int *pt=_nodal_connec->getConstPointer();
2697   for(int i=0;i<nbCells;i++)
2698     {
2699       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2700         ret->pushBackSilent(i);
2701     }
2702   return ret.retn();
2703 }
2704
2705 /*!
2706  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2707  */
2708 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2709 {
2710   const int *ptI=_nodal_connec_index->getConstPointer();
2711   const int *pt=_nodal_connec->getConstPointer();
2712   int nbOfCells=getNumberOfCells();
2713   int ret=0;
2714   for(int i=0;i<nbOfCells;i++)
2715     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2716       ret++;
2717   return ret;
2718 }
2719
2720 /*!
2721  * Returns the nodal connectivity of a given cell.
2722  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2723  * all returned node ids can be used in getCoordinatesOfNode().
2724  *  \param [in] cellId - an id of the cell of interest.
2725  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2726  *         cleared before the appending.
2727  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2728  */
2729 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2730 {
2731   const int *ptI=_nodal_connec_index->getConstPointer();
2732   const int *pt=_nodal_connec->getConstPointer();
2733   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2734     if(*w>=0)
2735       conn.push_back(*w);
2736 }
2737
2738 std::string MEDCouplingUMesh::simpleRepr() const
2739 {
2740   static const char msg0[]="No coordinates specified !";
2741   std::ostringstream ret;
2742   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2743   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2744   int tmpp1,tmpp2;
2745   double tt=getTime(tmpp1,tmpp2);
2746   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2747   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2748   if(_mesh_dim>=-1)
2749     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2750   else
2751     { ret << " Mesh dimension has not been set or is invalid !"; }
2752   if(_coords!=0)
2753     {
2754       const int spaceDim=getSpaceDimension();
2755       ret << spaceDim << "\nInfo attached on space dimension : ";
2756       for(int i=0;i<spaceDim;i++)
2757         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2758       ret << "\n";
2759     }
2760   else
2761     ret << msg0 << "\n";
2762   ret << "Number of nodes : ";
2763   if(_coords!=0)
2764     ret << getNumberOfNodes() << "\n";
2765   else
2766     ret << msg0 << "\n";
2767   ret << "Number of cells : ";
2768   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2769     ret << getNumberOfCells() << "\n";
2770   else
2771     ret << "No connectivity specified !" << "\n";
2772   ret << "Cell types present : ";
2773   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2774     {
2775       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2776       ret << cm.getRepr() << " ";
2777     }
2778   ret << "\n";
2779   return ret.str();
2780 }
2781
2782 std::string MEDCouplingUMesh::advancedRepr() const
2783 {
2784   std::ostringstream ret;
2785   ret << simpleRepr();
2786   ret << "\nCoordinates array : \n___________________\n\n";
2787   if(_coords)
2788     _coords->reprWithoutNameStream(ret);
2789   else
2790     ret << "No array set !\n";
2791   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2792   reprConnectivityOfThisLL(ret);
2793   return ret.str();
2794 }
2795
2796 /*!
2797  * This method returns a C++ code that is a dump of \a this.
2798  * This method will throw if this is not fully defined.
2799  */
2800 std::string MEDCouplingUMesh::cppRepr() const
2801 {
2802   static const char coordsName[]="coords";
2803   static const char connName[]="conn";
2804   static const char connIName[]="connI";
2805   checkFullyDefined();
2806   std::ostringstream ret; ret << "// coordinates" << std::endl;
2807   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2808   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2809   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2810   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2811   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2812   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2813   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2814   return ret.str();
2815 }
2816
2817 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2818 {
2819   std::ostringstream ret;
2820   reprConnectivityOfThisLL(ret);
2821   return ret.str();
2822 }
2823
2824 /*!
2825  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2826  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2827  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2828  * some algos).
2829  * 
2830  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2831  * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
2832  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2833  */
2834 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2835 {
2836   int mdim=getMeshDimension();
2837   if(mdim<0)
2838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2839   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
2840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2841   bool needToCpyCT=true;
2842   if(!_nodal_connec)
2843     {
2844       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2845       needToCpyCT=false;
2846     }
2847   else
2848     {
2849       tmp1=_nodal_connec;
2850       tmp1->incrRef();
2851     }
2852   if(!_nodal_connec_index)
2853     {
2854       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2855       needToCpyCT=false;
2856     }
2857   else
2858     {
2859       tmp2=_nodal_connec_index;
2860       tmp2->incrRef();
2861     }
2862   ret->setConnectivity(tmp1,tmp2,false);
2863   if(needToCpyCT)
2864     ret->_types=_types;
2865   if(!_coords)
2866     {
2867       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2868       ret->setCoords(coords);
2869     }
2870   else
2871     ret->setCoords(_coords);
2872   return ret.retn();
2873 }
2874
2875 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2876 {
2877   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2878     {
2879       int nbOfCells=getNumberOfCells();
2880       const int *c=_nodal_connec->getConstPointer();
2881       const int *ci=_nodal_connec_index->getConstPointer();
2882       for(int i=0;i<nbOfCells;i++)
2883         {
2884           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2885           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2886           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2887           stream << "\n";
2888         }
2889     }
2890   else
2891     stream << "Connectivity not defined !\n";
2892 }
2893
2894 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2895 {
2896   const int *ptI=_nodal_connec_index->getConstPointer();
2897   const int *pt=_nodal_connec->getConstPointer();
2898   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2899     return ptI[cellId+1]-ptI[cellId]-1;
2900   else
2901     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2902 }
2903
2904 /*!
2905  * Returns types of cells of the specified part of \a this mesh.
2906  * This method avoids computing sub-mesh explicitely to get its types.
2907  *  \param [in] begin - an array of cell ids of interest.
2908  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2909  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2910  *         describing the cell types. 
2911  *  \throw If the coordinates array is not set.
2912  *  \throw If the nodal connectivity of cells is not defined.
2913  *  \sa getAllTypes()
2914  */
2915 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2916 {
2917   checkFullyDefined();
2918   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2919   const int *conn=_nodal_connec->getConstPointer();
2920   const int *connIndex=_nodal_connec_index->getConstPointer();
2921   for(const int *w=begin;w!=end;w++)
2922     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2923   return ret;
2924 }
2925
2926 /*!
2927  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2928  * a set of types of cells constituting \a this mesh. 
2929  * This method is for advanced users having prepared their connectivity before. For
2930  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2931  *  \param [in] conn - the nodal connectivity array. 
2932  *  \param [in] connIndex - the nodal connectivity index array.
2933  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2934  *         mesh is updated.
2935  */
2936 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2937 {
2938   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2939   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2940   if(isComputingTypes)
2941     computeTypes();
2942   declareAsNew();
2943 }
2944
2945 /*!
2946  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2947  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2948  */
2949 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2950                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2951                                                                                 _types(other._types)
2952 {
2953   if(other._nodal_connec)
2954     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2955   if(other._nodal_connec_index)
2956     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2957 }
2958
2959 MEDCouplingUMesh::~MEDCouplingUMesh()
2960 {
2961   if(_nodal_connec)
2962     _nodal_connec->decrRef();
2963   if(_nodal_connec_index)
2964     _nodal_connec_index->decrRef();
2965 }
2966
2967 /*!
2968  * Recomputes a set of cell types of \a this mesh. For more info see
2969  * \ref MEDCouplingUMeshNodalConnectivity.
2970  */
2971 void MEDCouplingUMesh::computeTypes()
2972 {
2973   if(_nodal_connec && _nodal_connec_index)
2974     {
2975       _types.clear();
2976       const int *conn=_nodal_connec->getConstPointer();
2977       const int *connIndex=_nodal_connec_index->getConstPointer();
2978       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2979       if (nbOfElem > 0)
2980         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2981           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2982     }
2983 }
2984
2985 /*!
2986  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2987  */
2988 void MEDCouplingUMesh::checkFullyDefined() const
2989 {
2990   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2991     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2992 }
2993
2994 /*!
2995  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2996  */
2997 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
2998 {
2999   if(!_nodal_connec_index || !_nodal_connec)
3000     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3001 }
3002
3003 /*!
3004  * Returns a number of cells constituting \a this mesh. 
3005  *  \return int - the number of cells in \a this mesh.
3006  *  \throw If the nodal connectivity of cells is not defined.
3007  */
3008 int MEDCouplingUMesh::getNumberOfCells() const
3009
3010   if(_nodal_connec_index)
3011     return _nodal_connec_index->getNumberOfTuples()-1;
3012   else
3013     if(_mesh_dim==-1)
3014       return 1;
3015     else
3016       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3017 }
3018
3019 /*!
3020  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3021  * mesh. For more info see \ref MEDCouplingMeshesPage.
3022  *  \return int - the dimension of \a this mesh.
3023  *  \throw If the mesh dimension is not defined using setMeshDimension().
3024  */
3025 int MEDCouplingUMesh::getMeshDimension() const
3026 {
3027   if(_mesh_dim<-1)
3028     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3029   return _mesh_dim;
3030 }
3031
3032 /*!
3033  * Returns a length of the nodal connectivity array.
3034  * This method is for test reason. Normally the integer returned is not useable by
3035  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3036  *  \return int - the length of the nodal connectivity array.
3037  */
3038 int MEDCouplingUMesh::getMeshLength() const
3039 {
3040   return _nodal_connec->getNbOfElems();
3041 }
3042
3043 /*!
3044  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3045  */
3046 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3047 {
3048   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3049   tinyInfo.push_back(getMeshDimension());
3050   tinyInfo.push_back(getNumberOfCells());
3051   if(_nodal_connec)
3052     tinyInfo.push_back(getMeshLength());
3053   else
3054     tinyInfo.push_back(-1);
3055 }
3056
3057 /*!
3058  * First step of unserialization process.
3059  */
3060 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3061 {
3062   return tinyInfo[6]<=0;
3063 }
3064
3065 /*!
3066  * Second step of serialization process.
3067  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3068  */
3069 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3070 {
3071   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3072   if(tinyInfo[5]!=-1)
3073     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3074 }
3075
3076 /*!
3077  * Third and final step of serialization process.
3078  */
3079 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3080 {
3081   MEDCouplingPointSet::serialize(a1,a2);
3082   if(getMeshDimension()>-1)
3083     {
3084       a1=DataArrayInt::New();
3085       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3086       int *ptA1=a1->getPointer();
3087       const int *conn=getNodalConnectivity()->getConstPointer();
3088       const int *index=getNodalConnectivityIndex()->getConstPointer();
3089       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3090       std::copy(conn,conn+getMeshLength(),ptA1);
3091     }
3092   else
3093     a1=0;
3094 }
3095
3096 /*!
3097  * Second and final unserialization process.
3098  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3099  */
3100 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3101 {
3102   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3103   setMeshDimension(tinyInfo[5]);
3104   if(tinyInfo[7]!=-1)
3105     {
3106       // Connectivity
3107       const int *recvBuffer=a1->getConstPointer();
3108       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3109       myConnecIndex->alloc(tinyInfo[6]+1,1);
3110       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3111       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3112       myConnec->alloc(tinyInfo[7],1);
3113       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3114       setConnectivity(myConnec, myConnecIndex);
3115     }
3116 }
3117
3118 /*!
3119  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3120  * CellIds are given using range specified by a start an end and step.
3121  */
3122 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3123 {
3124   checkFullyDefined();
3125   int ncell=getNumberOfCells();
3126   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3127   ret->_mesh_dim=_mesh_dim;
3128   ret->setCoords(_coords);
3129   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3131   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3132   int work=start;
3133   const int *conn=_nodal_connec->getConstPointer();
3134   const int *connIndex=_nodal_connec_index->getConstPointer();
3135   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3136     {
3137       if(work>=0 && work<ncell)
3138         {
3139           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3140         }
3141       else
3142         {
3143           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3144           throw INTERP_KERNEL::Exception(oss.str().c_str());
3145         }
3146     }
3147   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3148   int *newConnPtr=newConn->getPointer();
3149   std::set<INTERP_KERNEL::NormalizedCellType> types;
3150   work=start;
3151   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3152     {
3153       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3154       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3155     }
3156   ret->setConnectivity(newConn,newConnI,false);
3157   ret->_types=types;
3158   ret->copyTinyInfoFrom(this);
3159   return ret.retn();
3160 }
3161
3162 /*!
3163  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3164  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3165  * The return newly allocated mesh will share the same coordinates as \a this.
3166  */
3167 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3168 {
3169   checkConnectivityFullyDefined();
3170   int ncell=getNumberOfCells();
3171   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3172   ret->_mesh_dim=_mesh_dim;
3173   ret->setCoords(_coords);
3174   std::size_t nbOfElemsRet=std::distance(begin,end);
3175   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3176   connIndexRet[0]=0;
3177   const int *conn=_nodal_connec->getConstPointer();
3178   const int *connIndex=_nodal_connec_index->getConstPointer();
3179   int newNbring=0;
3180   for(const int *work=begin;work!=end;work++,newNbring++)
3181     {
3182       if(*work>=0 && *work<ncell)
3183         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3184       else
3185         {
3186           free(connIndexRet);
3187           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3188           throw INTERP_KERNEL::Exception(oss.str().c_str());
3189         }
3190     }
3191   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3192   int *connRetWork=connRet;
3193   std::set<INTERP_KERNEL::NormalizedCellType> types;
3194   for(const int *work=begin;work!=end;work++)
3195     {
3196       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3197       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3198     }
3199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3200   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3202   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3203   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3204   ret->_types=types;
3205   ret->copyTinyInfoFrom(this);
3206   return ret.retn();
3207 }
3208
3209 /*!
3210  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3211  * mesh.<br>
3212  * For 1D cells, the returned field contains lengths.<br>
3213  * For 2D cells, the returned field contains areas.<br>
3214  * For 3D cells, the returned field contains volumes.
3215  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3216  *         orientation, i.e. the volume is always positive.
3217  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3218  *         and one time . The caller is to delete this field using decrRef() as it is no
3219  *         more needed.
3220  */
3221 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3222 {
3223   std::string name="MeasureOfMesh_";
3224   name+=getName();
3225   int nbelem=getNumberOfCells();
3226   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3227   field->setName(name.c_str());
3228   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3229   array->alloc(nbelem,1);
3230   double *area_vol=array->getPointer();
3231   field->setArray(array) ; array=0;
3232   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3233   field->synchronizeTimeWithMesh();
3234   if(getMeshDimension()!=-1)
3235     {
3236       int ipt;
3237       INTERP_KERNEL::NormalizedCellType type;
3238       int dim_space=getSpaceDimension();
3239       const double *coords=getCoords()->getConstPointer();
3240       const int *connec=getNodalConnectivity()->getConstPointer();
3241       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3242       for(int iel=0;iel<nbelem;iel++)
3243         {
3244           ipt=connec_index[iel];
3245           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3246           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);
3247         }
3248       if(isAbs)
3249         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3250     }
3251   else
3252     {
3253       area_vol[0]=std::numeric_limits<double>::max();
3254     }
3255   return field.retn();
3256 }
3257
3258 /*!
3259  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3260  * mesh.<br>
3261  * For 1D cells, the returned array contains lengths.<br>
3262  * For 2D cells, the returned array contains areas.<br>
3263  * For 3D cells, the returned array contains volumes.
3264  * This method avoids building explicitly a part of \a this mesh to perform the work.
3265  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3266  *         orientation, i.e. the volume is always positive.
3267  *  \param [in] begin - an array of cell ids of interest.
3268  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3269  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3270  *          delete this array using decrRef() as it is no more needed.
3271  * 
3272  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3273  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3274  *  \sa getMeasureField()
3275  */
3276 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3277 {
3278   std::string name="PartMeasureOfMesh_";
3279   name+=getName();
3280   int nbelem=(int)std::distance(begin,end);
3281   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3282   array->setName(name.c_str());
3283   array->alloc(nbelem,1);
3284   double *area_vol=array->getPointer();
3285   if(getMeshDimension()!=-1)
3286     {
3287       int ipt;
3288       INTERP_KERNEL::NormalizedCellType type;
3289       int dim_space=getSpaceDimension();
3290       const double *coords=getCoords()->getConstPointer();
3291       const int *connec=getNodalConnectivity()->getConstPointer();
3292       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3293       for(const int *iel=begin;iel!=end;iel++)
3294         {
3295           ipt=connec_index[*iel];
3296           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3297           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3298         }
3299       if(isAbs)
3300         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3301     }
3302   else
3303     {
3304       area_vol[0]=std::numeric_limits<double>::max();
3305     }
3306   return array.retn();
3307 }
3308
3309 /*!
3310  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3311  * \a this one. The returned field contains the dual cell volume for each corresponding
3312  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3313  *  the dual mesh in P1 sens of \a this.<br>
3314  * For 1D cells, the returned field contains lengths.<br>
3315  * For 2D cells, the returned field contains areas.<br>
3316  * For 3D cells, the returned field contains volumes.
3317  * This method is useful to check "P1*" conservative interpolators.
3318  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3319  *         orientation, i.e. the volume is always positive.
3320  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3321  *          nodes and one time. The caller is to delete this array using decrRef() as
3322  *          it is no more needed.
3323  */
3324 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3325 {
3326   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3327   std::string name="MeasureOnNodeOfMesh_";
3328   name+=getName();
3329   int nbNodes=getNumberOfNodes();
3330   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3331   double cst=1./((double)getMeshDimension()+1.);
3332   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3333   array->alloc(nbNodes,1);
3334   double *valsToFill=array->getPointer();
3335   std::fill(valsToFill,valsToFill+nbNodes,0.);
3336   const double *values=tmp->getArray()->getConstPointer();
3337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3339   getReverseNodalConnectivity(da,daInd);
3340   const int *daPtr=da->getConstPointer();
3341   const int *daIPtr=daInd->getConstPointer();
3342   for(int i=0;i<nbNodes;i++)
3343     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3344       valsToFill[i]+=cst*values[*cell];
3345   ret->setMesh(this);
3346   ret->setArray(array);
3347   return ret.retn();
3348 }
3349
3350 /*!
3351  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3352  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3353  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3354  * and are normalized.
3355  * <br> \a this can be either 
3356  * - a  2D mesh in 2D or 3D space or 
3357  * - an 1D mesh in 2D space.
3358  * 
3359  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3360  *          cells and one time. The caller is to delete this field using decrRef() as
3361  *          it is no more needed.
3362  *  \throw If the nodal connectivity of cells is not defined.
3363  *  \throw If the coordinates array is not set.
3364  *  \throw If the mesh dimension is not set.
3365  *  \throw If the mesh and space dimension is not as specified above.
3366  */
3367 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3368 {
3369   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3370     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3371   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3372   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3373   int nbOfCells=getNumberOfCells();
3374   int nbComp=getMeshDimension()+1;
3375   array->alloc(nbOfCells,nbComp);
3376   double *vals=array->getPointer();
3377   const int *connI=_nodal_connec_index->getConstPointer();
3378   const int *conn=_nodal_connec->getConstPointer();
3379   const double *coords=_coords->getConstPointer();
3380   if(getMeshDimension()==2)
3381     {
3382       if(getSpaceDimension()==3)
3383         {
3384           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3385           const double *locPtr=loc->getConstPointer();
3386           for(int i=0;i<nbOfCells;i++,vals+=3)
3387             {
3388               int offset=connI[i];
3389               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3390               double n=INTERP_KERNEL::norm<3>(vals);
3391               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3392             }
3393         }
3394       else
3395         {
3396           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3397           const double *isAbsPtr=isAbs->getArray()->begin();
3398           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3399             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3400         }
3401     }
3402   else//meshdimension==1
3403     {
3404       double tmp[2];
3405       for(int i=0;i<nbOfCells;i++)
3406         {
3407           int offset=connI[i];
3408           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3409           double n=INTERP_KERNEL::norm<2>(tmp);
3410           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3411           *vals++=-tmp[1];
3412           *vals++=tmp[0];
3413         }
3414     }
3415   ret->setArray(array);
3416   ret->setMesh(this);
3417   ret->synchronizeTimeWithSupport();
3418   return ret.retn();
3419 }
3420
3421 /*!
3422  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3423  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3424  * and are normalized.
3425  * <br> \a this can be either 
3426  * - a  2D mesh in 2D or 3D space or 
3427  * - an 1D mesh in 2D space.
3428  * 
3429  * This method avoids building explicitly a part of \a this mesh to perform the work.
3430  *  \param [in] begin - an array of cell ids of interest.
3431  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3432  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3433  *          cells and one time. The caller is to delete this field using decrRef() as
3434  *          it is no more needed.
3435  *  \throw If the nodal connectivity of cells is not defined.
3436  *  \throw If the coordinates array is not set.
3437  *  \throw If the mesh dimension is not set.
3438  *  \throw If the mesh and space dimension is not as specified above.
3439  *  \sa buildOrthogonalField()
3440  *
3441  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3442  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3443  */
3444 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3445 {
3446   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3447     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3448   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3449   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3450   std::size_t nbelems=std::distance(begin,end);
3451   int nbComp=getMeshDimension()+1;
3452   array->alloc((int)nbelems,nbComp);
3453   double *vals=array->getPointer();
3454   const int *connI=_nodal_connec_index->getConstPointer();
3455   const int *conn=_nodal_connec->getConstPointer();
3456   const double *coords=_coords->getConstPointer();
3457   if(getMeshDimension()==2)
3458     {
3459       if(getSpaceDimension()==3)
3460         {
3461           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3462           const double *locPtr=loc->getConstPointer();
3463           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3464             {
3465               int offset=connI[*i];
3466               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3467               double n=INTERP_KERNEL::norm<3>(vals);
3468               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3469             }
3470         }
3471       else
3472         {
3473           for(std::size_t i=0;i<nbelems;i++)
3474             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3475         }
3476     }
3477   else//meshdimension==1
3478     {
3479       double tmp[2];
3480       for(const int *i=begin;i!=end;i++)
3481         {
3482           int offset=connI[*i];
3483           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3484           double n=INTERP_KERNEL::norm<2>(tmp);
3485           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3486           *vals++=-tmp[1];
3487           *vals++=tmp[0];
3488         }
3489     }
3490   ret->setArray(array);
3491   ret->setMesh(this);
3492   ret->synchronizeTimeWithSupport();
3493   return ret.retn();
3494 }
3495
3496 /*!
3497  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3498  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3499  * and are \b not normalized.
3500  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3501  *          cells and one time. The caller is to delete this field using decrRef() as
3502  *          it is no more needed.
3503  *  \throw If the nodal connectivity of cells is not defined.
3504  *  \throw If the coordinates array is not set.
3505  *  \throw If \a this->getMeshDimension() != 1.
3506  *  \throw If \a this mesh includes cells of type other than SEG2.
3507  */
3508 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3509 {
3510    if(getMeshDimension()!=1)
3511     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3512    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3513      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3514    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3515    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3516    int nbOfCells=getNumberOfCells();
3517    int spaceDim=getSpaceDimension();
3518    array->alloc(nbOfCells,spaceDim);
3519    double *pt=array->getPointer();
3520    const double *coo=getCoords()->getConstPointer();
3521    std::vector<int> conn;
3522    conn.reserve(2);
3523    for(int i=0;i<nbOfCells;i++)
3524      {
3525        conn.resize(0);
3526        getNodeIdsOfCell(i,conn);
3527        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3528      }
3529    ret->setArray(array);
3530    ret->setMesh(this);
3531    ret->synchronizeTimeWithSupport();
3532    return ret.retn();   
3533 }
3534
3535 /*!
3536  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3537  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3538  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3539  * from. If a result face is shared by two 3D cells, then the face in included twice in
3540  * the result mesh.
3541  *  \param [in] origin - 3 components of a point defining location of the plane.
3542  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3543  *         must be greater than 1e-6.
3544  *  \param [in] eps - half-thickness of the plane.
3545  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3546  *         producing correspondent 2D cells. The caller is to delete this array
3547  *         using decrRef() as it is no more needed.
3548  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3549  *         not share the node coordinates array with \a this mesh. The caller is to
3550  *         delete this mesh using decrRef() as it is no more needed.  
3551  *  \throw If the coordinates array is not set.
3552  *  \throw If the nodal connectivity of cells is not defined.
3553  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3554  *  \throw If magnitude of \a vec is less than 1e-6.
3555  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3556  *  \throw If \a this includes quadratic cells.
3557  */
3558 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3559 {
3560   checkFullyDefined();
3561   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3562     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3563   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3564   if(candidates->empty())
3565     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3566   std::vector<int> nodes;
3567   DataArrayInt *cellIds1D=0;
3568   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3569   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3570   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3571   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3572   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3573   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3574   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3575   revDesc2=0; revDescIndx2=0;
3576   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3577   revDesc1=0; revDescIndx1=0;
3578   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3580   //
3581   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3582   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3583     cut3DCurve[*it]=-1;
3584   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3585   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3586   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3587                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3588                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3589   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3590   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3591   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3592   if(cellIds2->empty())
3593     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3594   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3595   ret->setCoords(mDesc1->getCoords());
3596   ret->setConnectivity(conn,connI,true);
3597   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3598   return ret.retn();
3599 }
3600
3601 /*!
3602  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3603 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
3604 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3605 the result mesh.
3606  *  \param [in] origin - 3 components of a point defining location of the plane.
3607  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3608  *         must be greater than 1e-6.
3609  *  \param [in] eps - half-thickness of the plane.
3610  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3611  *         producing correspondent segments. The caller is to delete this array
3612  *         using decrRef() as it is no more needed.
3613  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3614  *         mesh in 3D space. This mesh does not share the node coordinates array with
3615  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3616  *         no more needed. 
3617  *  \throw If the coordinates array is not set.
3618  *  \throw If the nodal connectivity of cells is not defined.
3619  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3620  *  \throw If magnitude of \a vec is less than 1e-6.
3621  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3622  *  \throw If \a this includes quadratic cells.
3623  */
3624 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3625 {
3626   checkFullyDefined();
3627   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3628     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3630   if(candidates->empty())
3631     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3632   std::vector<int> nodes;
3633   DataArrayInt *cellIds1D=0;
3634   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3635   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3639   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3640   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3641   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3642   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3643   //
3644   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3645   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3646     cut3DCurve[*it]=-1;
3647   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3648   int ncellsSub=subMesh->getNumberOfCells();
3649   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3650   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3651                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3652                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3653   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3654   conn->alloc(0,1);
3655   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3656   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3657   for(int i=0;i<ncellsSub;i++)
3658     {
3659       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3660         {
3661           if(cut3DSurf[i].first!=-2)
3662             {
3663               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3664               connI->pushBackSilent(conn->getNumberOfTuples());
3665               cellIds2->pushBackSilent(i);
3666             }
3667           else
3668             {
3669               int cellId3DSurf=cut3DSurf[i].second;
3670               int offset=nodalI[cellId3DSurf]+1;
3671               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3672               for(int j=0;j<nbOfEdges;j++)
3673                 {
3674                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3675                   connI->pushBackSilent(conn->getNumberOfTuples());
3676                   cellIds2->pushBackSilent(cellId3DSurf);
3677                 }
3678             }
3679         }
3680     }
3681   if(cellIds2->empty())
3682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3683   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3684   ret->setCoords(mDesc1->getCoords());
3685   ret->setConnectivity(conn,connI,true);
3686   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3687   return ret.retn();
3688 }
3689
3690 /*!
3691  * Finds cells whose bounding boxes intersect a given plane.
3692  *  \param [in] origin - 3 components of a point defining location of the plane.
3693  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3694  *         must be greater than 1e-6.
3695  *  \param [in] eps - half-thickness of the plane.
3696  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3697  *         cells. The caller is to delete this array using decrRef() as it is no more
3698  *         needed.
3699  *  \throw If the coordinates array is not set.
3700  *  \throw If the nodal connectivity of cells is not defined.
3701  *  \throw If \a this->getSpaceDimension() != 3.
3702  *  \throw If magnitude of \a vec is less than 1e-6.
3703  *  \sa buildSlice3D()
3704  */
3705 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3706 {
3707   checkFullyDefined();
3708   if(getSpaceDimension()!=3)
3709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3710   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3711   if(normm<1e-6)
3712     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3713   double vec2[3];
3714   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3715   double angle=acos(vec[2]/normm);
3716   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3717   double bbox[6];
3718   if(angle>eps)
3719     {
3720       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3721       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3722       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3723       mw->setCoords(coo);
3724       mw->getBoundingBox(bbox);
3725       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3726       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3727     }
3728   else
3729     {
3730       getBoundingBox(bbox);
3731       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3732       cellIds=getCellsInBoundingBox(bbox,eps);
3733     }
3734   return cellIds.retn();
3735 }
3736
3737 /*!
3738  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3739  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3740  * No consideration of coordinate is done by this method.
3741  * 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)
3742  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3743  */
3744 bool MEDCouplingUMesh::isContiguous1D() const
3745 {
3746   if(getMeshDimension()!=1)
3747     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3748   int nbCells=getNumberOfCells();
3749   if(nbCells<1)
3750     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3751   const int *connI=_nodal_connec_index->getConstPointer();
3752   const int *conn=_nodal_connec->getConstPointer();
3753   int ref=conn[connI[0]+2];
3754   for(int i=1;i<nbCells;i++)
3755     {
3756       if(conn[connI[i]+1]!=ref)
3757         return false;
3758       ref=conn[connI[i]+2];
3759     }
3760   return true;
3761 }
3762
3763 /*!
3764  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3765  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3766  * \param pt reference point of the line
3767  * \param v normalized director vector of the line
3768  * \param eps max precision before throwing an exception
3769  * \param res output of size this->getNumberOfCells
3770  */
3771 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3772 {
3773   if(getMeshDimension()!=1)
3774     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3775    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3776      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3777    if(getSpaceDimension()!=3)
3778      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3779    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3780    const double *fPtr=f->getArray()->getConstPointer();
3781    double tmp[3];
3782    for(int i=0;i<getNumberOfCells();i++)
3783      {
3784        const double *tmp1=fPtr+3*i;
3785        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3786        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3787        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3788        double n1=INTERP_KERNEL::norm<3>(tmp);
3789        n1/=INTERP_KERNEL::norm<3>(tmp1);
3790        if(n1>eps)
3791          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3792      }
3793    const double *coo=getCoords()->getConstPointer();
3794    for(int i=0;i<getNumberOfNodes();i++)
3795      {
3796        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3797        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3798        res[i]=std::accumulate(tmp,tmp+3,0.);
3799      }
3800 }
3801
3802 /*!
3803  * 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. 
3804  * \a this is expected to be a mesh so that its space dimension is equal to its
3805  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3806  * 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).
3807  
3808  * 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
3809  * 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).
3810  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3811  *
3812  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3813  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3814  *
3815  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3816  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3817  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3818  * \return the positive value of the distance.
3819  * \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
3820  * dimension - 1.
3821  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3822  */
3823 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3824 {
3825   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3826   if(meshDim!=spaceDim-1)
3827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3828   if(meshDim!=2 && meshDim!=1)
3829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3830   checkFullyDefined();
3831   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3832     { 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()); }
3833   DataArrayInt *ret1=0;
3834   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3835   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3837   cellId=*ret1Safe->begin();
3838   return *ret0->begin();
3839 }
3840
3841 /*!
3842  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3843  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3844  * 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
3845  * 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).
3846  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3847  * 
3848  * \a this is expected to be a mesh so that its space dimension is equal to its
3849  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3850  * 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).
3851  *
3852  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3853  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3854  *
3855  * \param [in] pts the list of points in which each tuple represents a point
3856  * \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.
3857  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3858  * \throw if number of components of \a pts is not equal to the space dimension.
3859  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3860  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3861  */
3862 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3863 {
3864   if(!pts)
3865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3866   pts->checkAllocated();
3867   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3868   if(meshDim!=spaceDim-1)
3869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3870   if(meshDim!=2 && meshDim!=1)
3871     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3872   if(pts->getNumberOfComponents()!=spaceDim)
3873     {
3874       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3875       throw INTERP_KERNEL::Exception(oss.str().c_str());
3876     }
3877   checkFullyDefined();
3878   int nbCells=getNumberOfCells();
3879   if(nbCells==0)
3880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3881   int nbOfPts=pts->getNumberOfTuples();
3882   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3884   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3885   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3886   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3887   const double *bbox(bboxArr->begin());
3888   switch(spaceDim)
3889     {
3890     case 3:
3891       {
3892         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3893         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3894           {
3895             double x=std::numeric_limits<double>::max();
3896             std::vector<int> elems;
3897             myTree.getMinDistanceOfMax(ptsPtr,x);
3898             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3899             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3900           }
3901         break;
3902       }
3903     case 2:
3904       {
3905         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3906         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3907           {
3908             double x=std::numeric_limits<double>::max();
3909             std::vector<int> elems;
3910             myTree.getMinDistanceOfMax(ptsPtr,x);
3911             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3912             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3913           }
3914         break;
3915       }
3916     default:
3917       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3918     }
3919   cellIds=ret1.retn();
3920   return ret0.retn();
3921 }
3922
3923 /*!
3924  * \param [in] pt the start pointer (included) of the coordinates of the point
3925  * \param [in] cellIdsBg the start pointer (included) of cellIds
3926  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3927  * \param [in] nc nodal connectivity
3928  * \param [in] ncI nodal connectivity index
3929  * \param [in,out] ret0 the min distance between \a this and the external input point
3930  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3931  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3932  */
3933 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)
3934 {
3935   cellId=-1;
3936   ret0=std::numeric_limits<double>::max();
3937   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3938     {
3939       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3940         {
3941         case INTERP_KERNEL::NORM_TRI3:
3942           {
3943             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3944             if(tmp<ret0)
3945               { ret0=tmp; cellId=*zeCell; }
3946             break;
3947           }
3948         case INTERP_KERNEL::NORM_QUAD4:
3949         case INTERP_KERNEL::NORM_POLYGON:
3950           {
3951             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3952             if(tmp<ret0)
3953               { ret0=tmp; cellId=*zeCell; }
3954             break;
3955           }
3956         default:
3957           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3958         }
3959     }
3960 }
3961
3962 /*!
3963  * \param [in] pt the start pointer (included) of the coordinates of the point
3964  * \param [in] cellIdsBg the start pointer (included) of cellIds
3965  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3966  * \param [in] nc nodal connectivity
3967  * \param [in] ncI nodal connectivity index
3968  * \param [in,out] ret0 the min distance between \a this and the external input point
3969  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3970  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3971  */
3972 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)
3973 {
3974   cellId=-1;
3975   ret0=std::numeric_limits<double>::max();
3976   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3977     {
3978        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3979         {
3980         case INTERP_KERNEL::NORM_SEG2:
3981           {
3982             std::size_t uselessEntry=0;
3983             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3984             tmp=sqrt(tmp);
3985             if(tmp<ret0)
3986               { ret0=tmp; cellId=*zeCell; }
3987             break;
3988           }
3989         default:
3990           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3991         }
3992     }
3993 }
3994
3995 /*!
3996  * Finds cells in contact with a ball (i.e. a point with precision). 
3997  * \warning This method is suitable if the caller intends to evaluate only one
3998  *          point, for more points getCellsContainingPoints() is recommended as it is
3999  *          faster. 
4000  *  \param [in] pos - array of coordinates of the ball central point.
4001  *  \param [in] eps - ball radius.
4002  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4003  *         if there are no such cells.
4004  *  \throw If the coordinates array is not set.
4005  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4006  */
4007 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4008 {
4009   std::vector<int> elts;
4010   getCellsContainingPoint(pos,eps,elts);
4011   if(elts.empty())
4012     return -1;
4013   return elts.front();
4014 }
4015
4016 /*!
4017  * Finds cells in contact with a ball (i.e. a point with precision).
4018  * \warning This method is suitable if the caller intends to evaluate only one
4019  *          point, for more points getCellsContainingPoints() is recommended as it is
4020  *          faster. 
4021  *  \param [in] pos - array of coordinates of the ball central point.
4022  *  \param [in] eps - ball radius.
4023  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4024  *         before inserting ids.
4025  *  \throw If the coordinates array is not set.
4026  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4027  *
4028  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4029  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4030  */
4031 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4032 {
4033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4034   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4035   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4036 }
4037
4038 /// @cond INTERNAL
4039
4040 namespace ParaMEDMEM
4041 {
4042   template<const int SPACEDIMM>
4043   class DummyClsMCUG
4044   {
4045   public:
4046     static const int MY_SPACEDIM=SPACEDIMM;
4047     static const int MY_MESHDIM=8;
4048     typedef int MyConnType;
4049     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4050     // begin
4051     // useless, but for windows compilation ...
4052     const double* getCoordinatesPtr() const { return 0; }
4053     const int* getConnectivityPtr() const { return 0; }
4054     const int* getConnectivityIndexPtr() const { return 0; }
4055     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4056     // end
4057   };
4058
4059   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4060   {
4061     INTERP_KERNEL::Edge *ret=0;
4062     switch(typ)
4063       {
4064       case INTERP_KERNEL::NORM_SEG2:
4065         {
4066           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4067           break;
4068         }
4069       case INTERP_KERNEL::NORM_SEG3:
4070         {
4071           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4072           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4073           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4074           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4075           bool colinearity=inters.areColinears();
4076           delete e1; delete e2;
4077           if(colinearity)
4078             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4079           else
4080             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4081           mapp2[bg[2]].second=false;
4082           break;
4083         }
4084       default:
4085         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4086       }
4087     return ret;
4088   }
4089
4090   /*!
4091    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4092    * the global mesh 'mDesc'.
4093    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4094    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4095    */
4096   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4097       std::map<INTERP_KERNEL::Node *,int>& mapp)
4098       throw(INTERP_KERNEL::Exception)
4099   {
4100     mapp.clear();
4101     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.
4102     const double *coo=mDesc->getCoords()->getConstPointer();
4103     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4104     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4105     std::set<int> s;
4106     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4107       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4108     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4109       {
4110         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4111         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4112       }
4113     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4114     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4115       {
4116         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4117         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4118       }
4119     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4120       {
4121         if((*it2).second.second)
4122           mapp[(*it2).second.first]=(*it2).first;
4123         ((*it2).second.first)->decrRef();
4124       }
4125     return ret;
4126   }
4127
4128   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4129   {
4130     if(nodeId>=offset2)
4131       {
4132         int locId=nodeId-offset2;
4133         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4134       }
4135     if(nodeId>=offset1)
4136       {
4137         int locId=nodeId-offset1;
4138         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4139       }
4140     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4141   }
4142
4143   /**
4144    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4145    */
4146   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4147                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4148                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4149   {
4150     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4151       {
4152         int eltId1=abs(*desc1)-1;
4153         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4154           {
4155             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4156             if(it==mappRev.end())
4157               {
4158                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4159                 mapp[node]=*it1;
4160                 mappRev[*it1]=node;
4161               }
4162           }
4163       }
4164   }
4165 }
4166
4167 /// @endcond
4168
4169 template<int SPACEDIM>
4170 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4171                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4172 {
4173   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4174   int *eltsIndexPtr(eltsIndex->getPointer());
4175   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4176   const double *bbox(bboxArr->begin());
4177   int nbOfCells=getNumberOfCells();
4178   const int *conn=_nodal_connec->getConstPointer();
4179   const int *connI=_nodal_connec_index->getConstPointer();
4180   double bb[2*SPACEDIM];
4181   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4182   for(int i=0;i<nbOfPoints;i++)
4183     {
4184       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4185       for(int j=0;j<SPACEDIM;j++)
4186         {
4187           bb[2*j]=pos[SPACEDIM*i+j];
4188           bb[2*j+1]=pos[SPACEDIM*i+j];
4189         }
4190       std::vector<int> candidates;
4191       myTree.getIntersectingElems(bb,candidates);
4192       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4193         {
4194           int sz=connI[(*iter)+1]-connI[*iter]-1;
4195           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4196                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4197                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4198             {
4199               eltsIndexPtr[i+1]++;
4200               elts->pushBackSilent(*iter);
4201             }
4202         }
4203     }
4204 }
4205 /*!
4206  * Finds cells in contact with several balls (i.e. points with precision).
4207  * This method is an extension of getCellContainingPoint() and
4208  * getCellsContainingPoint() for the case of multiple points.
4209  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4210  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4211  *         this->getSpaceDimension() * \a nbOfPoints 
4212  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4213  *  \param [in] eps - radius of balls (i.e. the precision).
4214  *  \param [out] elts - vector returning ids of found cells.
4215  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4216  *         dividing cell ids in \a elts into groups each referring to one
4217  *         point. Its every element (except the last one) is an index pointing to the
4218  *         first id of a group of cells. For example cells in contact with the *i*-th
4219  *         point are described by following range of indices:
4220  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4221  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4222  *         Number of cells in contact with the *i*-th point is
4223  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4224  *  \throw If the coordinates array is not set.
4225  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4226  *
4227  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4228  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4229  */
4230 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4231                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4232 {
4233   int spaceDim=getSpaceDimension();
4234   int mDim=getMeshDimension();
4235   if(spaceDim==3)
4236     {
4237       if(mDim==3)
4238         {
4239           const double *coords=_coords->getConstPointer();
4240           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4241         }
4242       /*else if(mDim==2)
4243         {
4244           
4245         }*/
4246       else
4247         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4248     }
4249   else if(spaceDim==2)
4250     {
4251       if(mDim==2)
4252         {
4253           const double *coords=_coords->getConstPointer();
4254           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4255         }
4256       else
4257         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4258     }
4259   else if(spaceDim==1)
4260     {
4261       if(mDim==1)
4262         {
4263           const double *coords=_coords->getConstPointer();
4264           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4265         }
4266       else
4267         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4268     }
4269   else
4270     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4271 }
4272
4273 /*!
4274  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4275  * least two its edges intersect each other anywhere except their extremities. An
4276  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4277  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4278  *         cleared before filling in.
4279  *  \param [in] eps - precision.
4280  *  \throw If \a this->getMeshDimension() != 2.
4281  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4282  */
4283 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4284 {
4285   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4286   if(getMeshDimension()!=2)
4287     throw INTERP_KERNEL::Exception(msg);
4288   int spaceDim=getSpaceDimension();
4289   if(spaceDim!=2 && spaceDim!=3)
4290     throw INTERP_KERNEL::Exception(msg);
4291   const int *conn=_nodal_connec->getConstPointer();
4292   const int *connI=_nodal_connec_index->getConstPointer();
4293   int nbOfCells=getNumberOfCells();
4294   std::vector<double> cell2DinS2;
4295   for(int i=0;i<nbOfCells;i++)
4296     {
4297       int offset=connI[i];
4298       int nbOfNodesForCell=connI[i+1]-offset-1;
4299       if(nbOfNodesForCell<=3)
4300         continue;
4301       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4302       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4303       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4304         cells.push_back(i);
4305       cell2DinS2.clear();
4306     }
4307 }
4308
4309 /*!
4310  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4311  *
4312  * 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.
4313  * 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.
4314  * 
4315  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4316  * This convex envelop is computed using Jarvis march algorithm.
4317  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4318  * 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)
4319  * 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.
4320  *
4321  * \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.
4322  */
4323 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4324 {
4325   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4326     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4327   checkFullyDefined();
4328   const double *coords=getCoords()->getConstPointer();
4329   int nbOfCells=getNumberOfCells();
4330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4331   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4333   int *workIndexOut=nodalConnecIndexOut->getPointer();
4334   *workIndexOut=0;
4335   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4336   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4337   std::set<INTERP_KERNEL::NormalizedCellType> types;
4338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4339   isChanged->alloc(0,1);
4340   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4341     {
4342       int pos=nodalConnecOut->getNumberOfTuples();
4343       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4344         isChanged->pushBackSilent(i);
4345       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4346       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4347     }
4348   if(isChanged->empty())
4349     return 0;
4350   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4351   _types=types;
4352   return isChanged.retn();
4353 }
4354
4355 /*!
4356  * This method is \b NOT const because it can modify \a this.
4357  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4358  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4359  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4360  * \b 1 for translation and rotation around point of 'mesh1D'.
4361  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4362  */
4363 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4364 {
4365   checkFullyDefined();
4366   mesh1D->checkFullyDefined();
4367   if(!mesh1D->isContiguous1D())
4368     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4369   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4370     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4371   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4372     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4373   if(mesh1D->getMeshDimension()!=1)
4374     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4375   bool isQuad=false;
4376   if(isPresenceOfQuadratic())
4377     {
4378       if(mesh1D->isFullyQuadratic())
4379         isQuad=true;
4380       else
4381         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4382     }
4383   zipCoords();
4384   int oldNbOfNodes=getNumberOfNodes();
4385   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4386   switch(policy)
4387     {
4388     case 0:
4389       {
4390         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4391         break;
4392       }
4393     case 1:
4394       {
4395         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4396         break;
4397       }
4398     default:
4399       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4400     }
4401   setCoords(newCoords);
4402   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4403   updateTime();
4404   return ret.retn();
4405 }
4406
4407 /*!
4408  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4409  * If it is not the case an exception will be thrown.
4410  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4411  * intersection of plane defined by ('origin','vec').
4412  * This method has one in/out parameter : 'cut3DCurve'.
4413  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4414  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4415  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4416  * This method will throw an exception if \a this contains a non linear segment.
4417  */
4418 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4419 {
4420   checkFullyDefined();
4421   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4422     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4423   int ncells=getNumberOfCells();
4424   int nnodes=getNumberOfNodes();
4425   double vec2[3],vec3[3],vec4[3];
4426   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4427   if(normm<1e-6)
4428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4429   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4430   const int *conn=_nodal_connec->getConstPointer();
4431   const int *connI=_nodal_connec_index->getConstPointer();
4432   const double *coo=_coords->getConstPointer();
4433   std::vector<double> addCoo;
4434   for(int i=0;i<ncells;i++)
4435     {
4436       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4437         {
4438           if(cut3DCurve[i]==-2)
4439             {
4440               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4441               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];
4442               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4443               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4444               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4445                 {
4446                   const double *st2=coo+3*st;
4447                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4448                   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]));
4449                   if(pos>eps && pos<1-eps)
4450                     {
4451                       int nNode=((int)addCoo.size())/3;
4452                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4453                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4454                       cut3DCurve[i]=nnodes+nNode;
4455                     }
4456                 }
4457             }
4458         }
4459       else
4460         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4461     }
4462   if(!addCoo.empty())
4463     {
4464       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4465       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4466       coo2->alloc(newNbOfNodes,3);
4467       double *tmp=coo2->getPointer();
4468       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4469       std::copy(addCoo.begin(),addCoo.end(),tmp);
4470       DataArrayDouble::SetArrayIn(coo2,_coords);
4471     }
4472 }
4473
4474 /*!
4475  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4476  * \param mesh1D is the input 1D mesh used for translation computation.
4477  * \return newCoords new coords filled by this method. 
4478  */
4479 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4480 {
4481   int oldNbOfNodes=getNumberOfNodes();
4482   int nbOf1DCells=mesh1D->getNumberOfCells();
4483   int spaceDim=getSpaceDimension();
4484   DataArrayDouble *ret=DataArrayDouble::New();
4485   std::vector<bool> isQuads;
4486   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4487   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4488   double *retPtr=ret->getPointer();
4489   const double *coords=getCoords()->getConstPointer();
4490   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4491   std::vector<int> v;
4492   std::vector<double> c;
4493   double vec[3];
4494   v.reserve(3);
4495   c.reserve(6);
4496   for(int i=0;i<nbOf1DCells;i++)
4497     {
4498       v.resize(0);
4499       mesh1D->getNodeIdsOfCell(i,v);
4500       c.resize(0);
4501       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4502       mesh1D->getCoordinatesOfNode(v[0],c);
4503       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4504       for(int j=0;j<oldNbOfNodes;j++)
4505         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4506       if(isQuad)
4507         {
4508           c.resize(0);
4509           mesh1D->getCoordinatesOfNode(v[1],c);
4510           mesh1D->getCoordinatesOfNode(v[0],c);
4511           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4512           for(int j=0;j<oldNbOfNodes;j++)
4513             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4514         }
4515     }
4516   ret->copyStringInfoFrom(*getCoords());
4517   return ret;
4518 }
4519
4520 /*!
4521  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4522  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4523  * \return newCoords new coords filled by this method. 
4524  */
4525 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4526 {
4527   if(mesh1D->getSpaceDimension()==2)
4528     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4529   if(mesh1D->getSpaceDimension()==3)
4530     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4531   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4532 }
4533
4534 /*!
4535  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4536  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4537  * \return newCoords new coords filled by this method. 
4538  */
4539 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4540 {
4541   if(isQuad)
4542     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4543   int oldNbOfNodes=getNumberOfNodes();
4544   int nbOf1DCells=mesh1D->getNumberOfCells();
4545   if(nbOf1DCells<2)
4546     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4547   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4548   int nbOfLevsInVec=nbOf1DCells+1;
4549   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4550   double *retPtr=ret->getPointer();
4551   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4552   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4553   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4554   tmp->setCoords(tmp2);
4555   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4556   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4557   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4558   for(int i=1;i<nbOfLevsInVec;i++)
4559     {
4560       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4561       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4562       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4563       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4564       tmp->translate(vec);
4565       double tmp3[2],radius,alpha,alpha0;
4566       const double *p0=i+1<nbOfLevsInVec?begin:third;
4567       const double *p1=i+1<nbOfLevsInVec?end:begin;
4568       const double *p2=i+1<nbOfLevsInVec?third:end;
4569       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4570       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]);
4571       double angle=acos(cosangle/(radius*radius));
4572       tmp->rotate(end,0,angle);
4573       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4574     }
4575   return ret.retn();
4576 }
4577
4578 /*!
4579  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4580  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4581  * \return newCoords new coords filled by this method. 
4582  */
4583 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4584 {
4585   if(isQuad)
4586     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4587   int oldNbOfNodes=getNumberOfNodes();
4588   int nbOf1DCells=mesh1D->getNumberOfCells();
4589   if(nbOf1DCells<2)
4590     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4591   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4592   int nbOfLevsInVec=nbOf1DCells+1;
4593   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4594   double *retPtr=ret->getPointer();
4595   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4596   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4597   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4598   tmp->setCoords(tmp2);
4599   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4600   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4601   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4602   for(int i=1;i<nbOfLevsInVec;i++)
4603     {
4604       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4605       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4606       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4607       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4608       tmp->translate(vec);
4609       double tmp3[2],radius,alpha,alpha0;
4610       const double *p0=i+1<nbOfLevsInVec?begin:third;
4611       const double *p1=i+1<nbOfLevsInVec?end:begin;
4612       const double *p2=i+1<nbOfLevsInVec?third:end;
4613       double vecPlane[3]={
4614         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4615         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4616         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4617       };
4618       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4619       if(norm>1.e-7)
4620         {
4621           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4622           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4623           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4624           double s2=norm2;
4625           double c2=cos(asin(s2));
4626           double m[3][3]={
4627             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4628             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4629             {-vec2[1]*s2, vec2[0]*s2, c2}
4630           };
4631           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]};
4632           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]};
4633           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]};
4634           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4635           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]);
4636           double angle=acos(cosangle/(radius*radius));
4637           tmp->rotate(end,vecPlane,angle);
4638           
4639         }
4640       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4641     }
4642   return ret.retn();
4643 }
4644
4645 /*!
4646  * This method is private because not easy to use for end user. This method is const contrary to
4647  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4648  * the coords sorted slice by slice.
4649  * \param isQuad specifies presence of quadratic cells.
4650  */
4651 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4652 {
4653   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4654   int nbOf2DCells=getNumberOfCells();
4655   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4656   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4657   const int *conn=_nodal_connec->getConstPointer();
4658   const int *connI=_nodal_connec_index->getConstPointer();
4659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4661   newConnI->alloc(nbOf3DCells+1,1);
4662   int *newConnIPtr=newConnI->getPointer();
4663   *newConnIPtr++=0;
4664   std::vector<int> newc;
4665   for(int j=0;j<nbOf2DCells;j++)
4666     {
4667       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4668       *newConnIPtr++=(int)newc.size();
4669     }
4670   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4671   int *newConnPtr=newConn->getPointer();
4672   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4673   newConnIPtr=newConnI->getPointer();
4674   for(int iz=0;iz<nbOf1DCells;iz++)
4675     {
4676       if(iz!=0)
4677         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4678       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4679         {
4680           int icell=(int)(iter-newc.begin());
4681           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4682             {
4683               if(*iter!=-1)
4684                 *newConnPtr=(*iter)+iz*deltaPerLev;
4685               else
4686                 *newConnPtr=-1;
4687             }
4688           else
4689             *newConnPtr=(*iter);
4690         }
4691     }
4692   ret->setConnectivity(newConn,newConnI,true);
4693   ret->setCoords(getCoords());
4694   return ret;
4695 }
4696
4697 /*!
4698  * Checks if \a this mesh is constituted by only quadratic cells.
4699  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4700  *  \throw If the coordinates array is not set.
4701  *  \throw If the nodal connectivity of cells is not defined.
4702  */
4703 bool MEDCouplingUMesh::isFullyQuadratic() const
4704 {
4705   checkFullyDefined();
4706   bool ret=true;
4707   int nbOfCells=getNumberOfCells();
4708   for(int i=0;i<nbOfCells && ret;i++)
4709     {
4710       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4711       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4712       ret=cm.isQuadratic();
4713     }
4714   return ret;
4715 }
4716
4717 /*!
4718  * Checks if \a this mesh includes any quadratic cell.
4719  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4720  *  \throw If the coordinates array is not set.
4721  *  \throw If the nodal connectivity of cells is not defined.
4722  */
4723 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4724 {
4725   checkFullyDefined();
4726   bool ret=false;
4727   int nbOfCells=getNumberOfCells();
4728   for(int i=0;i<nbOfCells && !ret;i++)
4729     {
4730       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4731       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4732       ret=cm.isQuadratic();
4733     }
4734   return ret;
4735 }
4736
4737 /*!
4738  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4739  * this mesh, it remains unchanged.
4740  *  \throw If the coordinates array is not set.
4741  *  \throw If the nodal connectivity of cells is not defined.
4742  */
4743 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4744 {
4745   checkFullyDefined();
4746   int nbOfCells=getNumberOfCells();
4747   int delta=0;
4748   const int *iciptr=_nodal_connec_index->getConstPointer();
4749   for(int i=0;i<nbOfCells;i++)
4750     {
4751       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4752       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4753       if(cm.isQuadratic())
4754         {
4755           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4756           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4757           if(!cml.isDynamic())
4758             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4759           else
4760             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4761         }
4762     }
4763   if(delta==0)
4764     return ;
4765   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4766   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4767   const int *icptr=_nodal_connec->getConstPointer();
4768   newConn->alloc(getMeshLength()-delta,1);
4769   newConnI->alloc(nbOfCells+1,1);
4770   int *ocptr=newConn->getPointer();
4771   int *ociptr=newConnI->getPointer();
4772   *ociptr=0;
4773   _types.clear();
4774   for(int i=0;i<nbOfCells;i++,ociptr++)
4775     {
4776       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4777       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4778       if(!cm.isQuadratic())
4779         {
4780           _types.insert(type);
4781           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4782           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4783         }
4784       else
4785         {
4786           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4787           _types.insert(typel);
4788           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4789           int newNbOfNodes=cml.getNumberOfNodes();
4790           if(cml.isDynamic())
4791             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4792           *ocptr++=(int)typel;
4793           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4794           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4795         }
4796     }
4797   setConnectivity(newConn,newConnI,false);
4798 }
4799
4800 /*!
4801  * This method converts all linear cell in \a this to quadratic one.
4802  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4803  * 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)
4804  * 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.
4805  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4806  * end of the existing coordinates.
4807  * 
4808  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4809  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4810  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4811  * 
4812  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4813  *
4814  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4815  */
4816 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4817 {
4818   DataArrayInt *conn=0,*connI=0;
4819   DataArrayDouble *coords=0;
4820   std::set<INTERP_KERNEL::NormalizedCellType> types;
4821   checkFullyDefined();
4822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4823   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4824   int meshDim=getMeshDimension();
4825   switch(conversionType)
4826     {
4827     case 0:
4828       switch(meshDim)
4829         {
4830         case 1:
4831           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4832           connSafe=conn; connISafe=connI; coordsSafe=coords;
4833           break;
4834         case 2:
4835           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4836           connSafe=conn; connISafe=connI; coordsSafe=coords;
4837           break;
4838         case 3:
4839           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4840           connSafe=conn; connISafe=connI; coordsSafe=coords;
4841           break;
4842         default:
4843           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4844         }
4845       break;
4846     case 1:
4847       {
4848         switch(meshDim)
4849         {
4850         case 1:
4851           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4852           connSafe=conn; connISafe=connI; coordsSafe=coords;
4853           break;
4854         case 2:
4855           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4856           connSafe=conn; connISafe=connI; coordsSafe=coords;
4857           break;
4858         case 3:
4859           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4860           connSafe=conn; connISafe=connI; coordsSafe=coords;
4861           break;
4862         default:
4863           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4864         }
4865         break;
4866       }
4867     default:
4868       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4869     }
4870   setConnectivity(connSafe,connISafe,false);
4871   _types=types;
4872   setCoords(coordsSafe);
4873   return ret.retn();
4874 }
4875
4876 /*!
4877  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4878  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4879  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4880  */
4881 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4882 {
4883   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4887   int nbOfCells=getNumberOfCells();
4888   int nbOfNodes=getNumberOfNodes();
4889   const int *cPtr=_nodal_connec->getConstPointer();
4890   const int *icPtr=_nodal_connec_index->getConstPointer();
4891   int lastVal=0,offset=nbOfNodes;
4892   for(int i=0;i<nbOfCells;i++,icPtr++)
4893     {
4894       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4895       if(type==INTERP_KERNEL::NORM_SEG2)
4896         {
4897           types.insert(INTERP_KERNEL::NORM_SEG3);
4898           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4899           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4900           newConn->pushBackSilent(offset++);
4901           lastVal+=4;
4902           newConnI->pushBackSilent(lastVal);
4903           ret->pushBackSilent(i);
4904         }
4905       else
4906         {
4907           types.insert(type);
4908           lastVal+=(icPtr[1]-icPtr[0]);
4909           newConnI->pushBackSilent(lastVal);
4910           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4911         }
4912     }
4913   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4914   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4915   return ret.retn();
4916 }
4917
4918 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
4919 {
4920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4921   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4923   //
4924   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4925   DataArrayInt *conn1D=0,*conn1DI=0;
4926   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4927   DataArrayDouble *coordsTmp=0;
4928   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4929   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4930   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4931   const int *c1DPtr=conn1D->begin();
4932   const int *c1DIPtr=conn1DI->begin();
4933   int nbOfCells=getNumberOfCells();
4934   const int *cPtr=_nodal_connec->getConstPointer();
4935   const int *icPtr=_nodal_connec_index->getConstPointer();
4936   int lastVal=0;
4937   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4938     {
4939       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4940       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4941       if(!cm.isQuadratic())
4942         {
4943           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4944           types.insert(typ2); newConn->pushBackSilent(typ2);
4945           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4946           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4947             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4948           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4949           newConnI->pushBackSilent(lastVal);
4950           ret->pushBackSilent(i);
4951         }
4952       else
4953         {
4954           types.insert(typ);
4955           lastVal+=(icPtr[1]-icPtr[0]);
4956           newConnI->pushBackSilent(lastVal);
4957           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4958         }
4959     }
4960   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4961   return ret.retn();
4962 }
4963
4964 /*!
4965  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4966  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4967  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4968  */
4969 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4970 {
4971   
4972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4973   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4974   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4975 }
4976
4977 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4978 {
4979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4980   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4981   //
4982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4985   //
4986   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4987   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4988   DataArrayInt *conn1D=0,*conn1DI=0;
4989   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4990   DataArrayDouble *coordsTmp=0;
4991   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4992   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4994   const int *c1DPtr=conn1D->begin();
4995   const int *c1DIPtr=conn1DI->begin();
4996   int nbOfCells=getNumberOfCells();
4997   const int *cPtr=_nodal_connec->getConstPointer();
4998   const int *icPtr=_nodal_connec_index->getConstPointer();
4999   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5000   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5001     {
5002       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5003       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5004       if(!cm.isQuadratic())
5005         {
5006           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5007           types.insert(typ2); newConn->pushBackSilent(typ2);
5008           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5009           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5010             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5011           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5012           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5013           newConnI->pushBackSilent(lastVal);
5014           ret->pushBackSilent(i);
5015         }
5016       else
5017         {
5018           types.insert(typ);
5019           lastVal+=(icPtr[1]-icPtr[0]);
5020           newConnI->pushBackSilent(lastVal);
5021           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5022         }
5023     }
5024   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5025   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5026   return ret.retn();
5027 }
5028
5029 /*!
5030  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5031  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5032  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5033  */
5034 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5035 {
5036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5037   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5038   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5039 }
5040
5041 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5042 {
5043   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5044   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5046   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5047   //
5048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5051   //
5052   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5053   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5054   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5055   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5056   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5057   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5059   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5061   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5062   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5063   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5064   int nbOfCells=getNumberOfCells();
5065   const int *cPtr=_nodal_connec->getConstPointer();
5066   const int *icPtr=_nodal_connec_index->getConstPointer();
5067   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5068   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5069     {
5070       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5071       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5072       if(!cm.isQuadratic())
5073         {
5074           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5075           if(typ2==INTERP_KERNEL::NORM_ERROR)
5076             {
5077               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5078               throw INTERP_KERNEL::Exception(oss.str().c_str());
5079             }
5080           types.insert(typ2); newConn->pushBackSilent(typ2);
5081           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5082           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5083             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5084           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5085             {
5086               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5087               int tmpPos=newConn->getNumberOfTuples();
5088               newConn->pushBackSilent(nodeId2);
5089               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5090             }
5091           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5092           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5093           newConnI->pushBackSilent(lastVal);
5094           ret->pushBackSilent(i);
5095         }
5096       else
5097         {
5098           types.insert(typ);
5099           lastVal+=(icPtr[1]-icPtr[0]);
5100           newConnI->pushBackSilent(lastVal);
5101           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5102         }
5103     }
5104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5106   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5107   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5108   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5109   int *c=newConn->getPointer();
5110   const int *cI(newConnI->begin());
5111   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5112     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5113   offset=coordsTmp2Safe->getNumberOfTuples();
5114   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5115     c[cI[(*elt)+1]-1]+=offset;
5116   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5117   return ret.retn();
5118 }
5119
5120 /*!
5121  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5122  * so that the number of cells remains the same. Quadratic faces are converted to
5123  * polygons. This method works only for 2D meshes in
5124  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5125  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5126  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5127  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5128  *         a polylinized edge constituting the input polygon.
5129  *  \throw If the coordinates array is not set.
5130  *  \throw If the nodal connectivity of cells is not defined.
5131  *  \throw If \a this->getMeshDimension() != 2.
5132  *  \throw If \a this->getSpaceDimension() != 2.
5133  */
5134 void MEDCouplingUMesh::tessellate2D(double eps)
5135 {
5136   checkFullyDefined();
5137   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5138     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5139   double epsa=fabs(eps);
5140   if(epsa<std::numeric_limits<double>::min())
5141     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 !");
5142   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5143   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5144   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5145   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5146   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5147   revDesc1=0; revDescIndx1=0;
5148   mDesc->tessellate2DCurve(eps);
5149   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5150   setCoords(mDesc->getCoords());
5151 }
5152
5153 /*!
5154  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5155  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5156  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5157  *         a sub-divided edge.
5158  *  \throw If the coordinates array is not set.
5159  *  \throw If the nodal connectivity of cells is not defined.
5160  *  \throw If \a this->getMeshDimension() != 1.
5161  *  \throw If \a this->getSpaceDimension() != 2.
5162  */
5163 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5164 {
5165   checkFullyDefined();
5166   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5167     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5168   double epsa=fabs(eps);
5169   if(epsa<std::numeric_limits<double>::min())
5170     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 !");
5171   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5172   int nbCells=getNumberOfCells();
5173   int nbNodes=getNumberOfNodes();
5174   const int *conn=_nodal_connec->getConstPointer();
5175   const int *connI=_nodal_connec_index->getConstPointer();
5176   const double *coords=_coords->getConstPointer();
5177   std::vector<double> addCoo;
5178   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5180   newConnI->alloc(nbCells+1,1);
5181   int *newConnIPtr=newConnI->getPointer();
5182   *newConnIPtr=0;
5183   int tmp1[3];
5184   INTERP_KERNEL::Node *tmp2[3];
5185   std::set<INTERP_KERNEL::NormalizedCellType> types;
5186   for(int i=0;i<nbCells;i++,newConnIPtr++)
5187     {
5188       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5189       if(cm.isQuadratic())
5190         {//assert(connI[i+1]-connI[i]-1==3)
5191           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5192           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5193           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5194           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5195           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5196           if(eac)
5197             {
5198               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5199               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5200               delete eac;
5201               newConnIPtr[1]=(int)newConn.size();
5202             }
5203           else
5204             {
5205               types.insert(INTERP_KERNEL::NORM_SEG2);
5206               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5207               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5208               newConnIPtr[1]=newConnIPtr[0]+3;
5209             }
5210         }
5211       else
5212         {
5213           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5214           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5215           newConnIPtr[1]=newConnIPtr[0]+3;
5216         }
5217     }
5218   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5219     return ;
5220   _types=types;
5221   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5223   newConnArr->alloc((int)newConn.size(),1);
5224   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5225   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5226   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5227   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5228   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5229   std::copy(addCoo.begin(),addCoo.end(),work);
5230   DataArrayDouble::SetArrayIn(newCoords,_coords);
5231   updateTime();
5232 }
5233
5234 /*!
5235  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5236  * In addition, returns an array mapping new cells to old ones. <br>
5237  * This method typically increases the number of cells in \a this mesh
5238  * but the number of nodes remains \b unchanged.
5239  * That's why the 3D splitting policies
5240  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5241  *  \param [in] policy - specifies a pattern used for splitting.
5242  * The semantic of \a policy is:
5243  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5244  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5245  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5246  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5247  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5248  *          an id of old cell producing it. The caller is to delete this array using
5249  *         decrRef() as it is no more needed. 
5250  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5251  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5252  *          and \a this->getMeshDimension() != 3. 
5253  *  \throw If \a policy is not one of the four discussed above.
5254  *  \throw If the nodal connectivity of cells is not defined.
5255  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5256  */
5257 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5258 {
5259   switch(policy)
5260     {
5261     case 0:
5262       return simplexizePol0();
5263     case 1:
5264       return simplexizePol1();
5265     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5266       return simplexizePlanarFace5();
5267     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5268       return simplexizePlanarFace6();
5269     default:
5270       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)");
5271     }
5272 }
5273
5274 /*!
5275  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5276  * - 1D: INTERP_KERNEL::NORM_SEG2
5277  * - 2D: INTERP_KERNEL::NORM_TRI3
5278  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5279  *
5280  * This method is useful for users that need to use P1 field services as
5281  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5282  * All these methods need mesh support containing only simplex cells.
5283  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5284  *  \throw If the coordinates array is not set.
5285  *  \throw If the nodal connectivity of cells is not defined.
5286  *  \throw If \a this->getMeshDimension() < 1.
5287  */
5288 bool MEDCouplingUMesh::areOnlySimplexCells() const
5289 {
5290   checkFullyDefined();
5291   int mdim=getMeshDimension();
5292   if(mdim<1 || mdim>3)
5293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5294   int nbCells=getNumberOfCells();
5295   const int *conn=_nodal_connec->getConstPointer();
5296   const int *connI=_nodal_connec_index->getConstPointer();
5297   for(int i=0;i<nbCells;i++)
5298     {
5299       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5300       if(!cm.isSimplex())
5301         return false;
5302     }
5303   return true;
5304 }
5305
5306 /*!
5307  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5308  */
5309 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5310 {
5311   checkConnectivityFullyDefined();
5312   if(getMeshDimension()!=2)
5313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5314   int nbOfCells=getNumberOfCells();
5315   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5316   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5317   ret->alloc(nbOfCells+nbOfCutCells,1);
5318   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5319   int *retPt=ret->getPointer();
5320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5322   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5323   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5324   int *pt=newConn->getPointer();
5325   int *ptI=newConnI->getPointer();
5326   ptI[0]=0;
5327   const int *oldc=_nodal_connec->getConstPointer();
5328   const int *ci=_nodal_connec_index->getConstPointer();
5329   for(int i=0;i<nbOfCells;i++,ci++)
5330     {
5331       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5332         {
5333           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5334                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5335           pt=std::copy(tmp,tmp+8,pt);
5336           ptI[1]=ptI[0]+4;
5337           ptI[2]=ptI[0]+8;
5338           *retPt++=i;
5339           *retPt++=i;
5340           ptI+=2;
5341         }
5342       else
5343         {
5344           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5345           ptI[1]=ptI[0]+ci[1]-ci[0];
5346           ptI++;
5347           *retPt++=i;
5348         }
5349     }
5350   _nodal_connec->decrRef();
5351   _nodal_connec=newConn.retn();
5352   _nodal_connec_index->decrRef();
5353   _nodal_connec_index=newConnI.retn();
5354   computeTypes();
5355   updateTime();
5356   return ret.retn();
5357 }
5358
5359 /*!
5360  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5361  */
5362 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5363 {
5364   checkConnectivityFullyDefined();
5365   if(getMeshDimension()!=2)
5366     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5367   int nbOfCells=getNumberOfCells();
5368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5369   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5370   ret->alloc(nbOfCells+nbOfCutCells,1);
5371   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5372   int *retPt=ret->getPointer();
5373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5375   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5376   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5377   int *pt=newConn->getPointer();
5378   int *ptI=newConnI->getPointer();
5379   ptI[0]=0;
5380   const int *oldc=_nodal_connec->getConstPointer();
5381   const int *ci=_nodal_connec_index->getConstPointer();
5382   for(int i=0;i<nbOfCells;i++,ci++)
5383     {
5384       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5385         {
5386           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5387                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5388           pt=std::copy(tmp,tmp+8,pt);
5389           ptI[1]=ptI[0]+4;
5390           ptI[2]=ptI[0]+8;
5391           *retPt++=i;
5392           *retPt++=i;
5393           ptI+=2;
5394         }
5395       else
5396         {
5397           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5398           ptI[1]=ptI[0]+ci[1]-ci[0];
5399           ptI++;
5400           *retPt++=i;
5401         }
5402     }
5403   _nodal_connec->decrRef();
5404   _nodal_connec=newConn.retn();
5405   _nodal_connec_index->decrRef();
5406   _nodal_connec_index=newConnI.retn();
5407   computeTypes();
5408   updateTime();
5409   return ret.retn();
5410 }
5411
5412 /*!
5413  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5414  */
5415 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5416 {
5417   checkConnectivityFullyDefined();
5418   if(getMeshDimension()!=3)
5419     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5420   int nbOfCells=getNumberOfCells();
5421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5422   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5423   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5424   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5425   int *retPt=ret->getPointer();
5426   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5427   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5428   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5429   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5430   int *pt=newConn->getPointer();
5431   int *ptI=newConnI->getPointer();
5432   ptI[0]=0;
5433   const int *oldc=_nodal_connec->getConstPointer();
5434   const int *ci=_nodal_connec_index->getConstPointer();
5435   for(int i=0;i<nbOfCells;i++,ci++)
5436     {
5437       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5438         {
5439           for(int j=0;j<5;j++,pt+=5,ptI++)
5440             {
5441               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5442               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];
5443               *retPt++=i;
5444               ptI[1]=ptI[0]+5;
5445             }
5446         }
5447       else
5448         {
5449           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5450           ptI[1]=ptI[0]+ci[1]-ci[0];
5451           ptI++;
5452           *retPt++=i;
5453         }
5454     }
5455   _nodal_connec->decrRef();
5456   _nodal_connec=newConn.retn();
5457   _nodal_connec_index->decrRef();
5458   _nodal_connec_index=newConnI.retn();
5459   computeTypes();
5460   updateTime();
5461   return ret.retn();
5462 }
5463
5464 /*!
5465  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5466  */
5467 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5468 {
5469   checkConnectivityFullyDefined();
5470   if(getMeshDimension()!=3)
5471     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5472   int nbOfCells=getNumberOfCells();
5473   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5474   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5475   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5476   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5477   int *retPt=ret->getPointer();
5478   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5480   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5481   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5482   int *pt=newConn->getPointer();
5483   int *ptI=newConnI->getPointer();
5484   ptI[0]=0;
5485   const int *oldc=_nodal_connec->getConstPointer();
5486   const int *ci=_nodal_connec_index->getConstPointer();
5487   for(int i=0;i<nbOfCells;i++,ci++)
5488     {
5489       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5490         {
5491           for(int j=0;j<6;j++,pt+=5,ptI++)
5492             {
5493               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5494               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];
5495               *retPt++=i;
5496               ptI[1]=ptI[0]+5;
5497             }
5498         }
5499       else
5500         {
5501           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5502           ptI[1]=ptI[0]+ci[1]-ci[0];
5503           ptI++;
5504           *retPt++=i;
5505         }
5506     }
5507   _nodal_connec->decrRef();
5508   _nodal_connec=newConn.retn();
5509   _nodal_connec_index->decrRef();
5510   _nodal_connec_index=newConnI.retn();
5511   computeTypes();
5512   updateTime();
5513   return ret.retn();
5514 }
5515
5516 /*!
5517  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5518  * This method completly ignore coordinates.
5519  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5520  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5521  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5522  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5523  */
5524 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5525 {
5526   checkFullyDefined();
5527   if(getMeshDimension()!=2)
5528     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5529   int nbOfCells=getNumberOfCells();
5530   int *connI=_nodal_connec_index->getPointer();
5531   int newConnLgth=0;
5532   for(int i=0;i<nbOfCells;i++,connI++)
5533     {
5534       int offset=descIndex[i];
5535       int nbOfEdges=descIndex[i+1]-offset;
5536       //
5537       bool ddirect=desc[offset+nbOfEdges-1]>0;
5538       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5539       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5540       for(int j=0;j<nbOfEdges;j++)
5541         {
5542           bool direct=desc[offset+j]>0;
5543           int edgeId=std::abs(desc[offset+j])-1;
5544           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5545             {
5546               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5547               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5548               int ref2=direct?id1:id2;
5549               if(ref==ref2)
5550                 {
5551                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5552                   newConnLgth+=nbOfSubNodes-1;
5553                   ref=direct?id2:id1;
5554                 }
5555               else
5556                 {
5557                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5558                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5559                 }
5560             }
5561           else
5562             {
5563               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5564             }
5565         }
5566       newConnLgth++;//+1 is for cell type
5567       connI[1]=newConnLgth;
5568     }
5569   //
5570   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5571   newConn->alloc(newConnLgth,1);
5572   int *work=newConn->getPointer();
5573   for(int i=0;i<nbOfCells;i++)
5574     {
5575       *work++=INTERP_KERNEL::NORM_POLYGON;
5576       int offset=descIndex[i];
5577       int nbOfEdges=descIndex[i+1]-offset;
5578       for(int j=0;j<nbOfEdges;j++)
5579         {
5580           bool direct=desc[offset+j]>0;
5581           int edgeId=std::abs(desc[offset+j])-1;
5582           if(direct)
5583             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5584           else
5585             {
5586               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5587               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5588               work=std::copy(it,it+nbOfSubNodes-1,work);
5589             }
5590         }
5591     }
5592   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5593   _types.clear();
5594   if(nbOfCells>0)
5595     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5596 }
5597
5598 /*!
5599  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5600  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5601  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5602  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5603  * so it can be useful to call mergeNodes() before calling this method.
5604  *  \throw If \a this->getMeshDimension() <= 1.
5605  *  \throw If the coordinates array is not set.
5606  *  \throw If the nodal connectivity of cells is not defined.
5607  */
5608 void MEDCouplingUMesh::convertDegeneratedCells()
5609 {
5610   checkFullyDefined();
5611   if(getMeshDimension()<=1)
5612     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5613   int nbOfCells=getNumberOfCells();
5614   if(nbOfCells<1)
5615     return ;
5616   int initMeshLgth=getMeshLength();
5617   int *conn=_nodal_connec->getPointer();
5618   int *index=_nodal_connec_index->getPointer();
5619   int posOfCurCell=0;
5620   int newPos=0;
5621   int lgthOfCurCell;
5622   for(int i=0;i<nbOfCells;i++)
5623     {
5624       lgthOfCurCell=index[i+1]-posOfCurCell;
5625       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5626       int newLgth;
5627       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5628                                                                                                      conn+newPos+1,newLgth);
5629       conn[newPos]=newType;
5630       newPos+=newLgth+1;
5631       posOfCurCell=index[i+1];
5632       index[i+1]=newPos;
5633     }
5634   if(newPos!=initMeshLgth)
5635     _nodal_connec->reAlloc(newPos);
5636   computeTypes();
5637 }
5638
5639 /*!
5640  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5641  * A cell is considered to be oriented correctly if an angle between its
5642  * normal vector and a given vector is less than \c PI / \c 2.
5643  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5644  *         cells. 
5645  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5646  *         checked.
5647  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5648  *         is not cleared before filling in.
5649  *  \throw If \a this->getMeshDimension() != 2.
5650  *  \throw If \a this->getSpaceDimension() != 3.
5651  *
5652  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5653  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5654  */
5655 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5656 {
5657   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5658     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5659   int nbOfCells=getNumberOfCells();
5660   const int *conn=_nodal_connec->getConstPointer();
5661   const int *connI=_nodal_connec_index->getConstPointer();
5662   const double *coordsPtr=_coords->getConstPointer();
5663   for(int i=0;i<nbOfCells;i++)
5664     {
5665       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5666       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5667         {
5668           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5669           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5670             cells.push_back(i);
5671         }
5672     }
5673 }
5674
5675 /*!
5676  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5677  * considered to be oriented correctly if an angle between its normal vector and a
5678  * given vector is less than \c PI / \c 2. 
5679  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5680  *         cells. 
5681  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5682  *         checked.
5683  *  \throw If \a this->getMeshDimension() != 2.
5684  *  \throw If \a this->getSpaceDimension() != 3.
5685  *
5686  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5687  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5688  */
5689 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5690 {
5691   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5692     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5693   int nbOfCells=getNumberOfCells();
5694   int *conn=_nodal_connec->getPointer();
5695   const int *connI=_nodal_connec_index->getConstPointer();
5696   const double *coordsPtr=_coords->getConstPointer();
5697   bool isModified=false;
5698   for(int i=0;i<nbOfCells;i++)
5699     {
5700       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5701       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5702         {
5703           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5704           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5705             {
5706               isModified=true;
5707               if(!isQuadratic)
5708                 {
5709                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5710                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5711                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5712                 }
5713               else
5714                 {
5715                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5716                   std::vector<int> tmp0(sz-1),tmp1(sz);
5717                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5718                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5719                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5720                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5721                 }
5722             }
5723         }
5724     }
5725   if(isModified)
5726     _nodal_connec->declareAsNew();
5727   updateTime();
5728 }
5729
5730 /*!
5731  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5732  * oriented facets. The normal vector of the facet should point out of the cell.
5733  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5734  *         is not cleared before filling in.
5735  *  \throw If \a this->getMeshDimension() != 3.
5736  *  \throw If \a this->getSpaceDimension() != 3.
5737  *  \throw If the coordinates array is not set.
5738  *  \throw If the nodal connectivity of cells is not defined.
5739  *
5740  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5741  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5742  */
5743 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5744 {
5745   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5746     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5747   int nbOfCells=getNumberOfCells();
5748   const int *conn=_nodal_connec->getConstPointer();
5749   const int *connI=_nodal_connec_index->getConstPointer();
5750   const double *coordsPtr=_coords->getConstPointer();
5751   for(int i=0;i<nbOfCells;i++)
5752     {
5753       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5754       if(type==INTERP_KERNEL::NORM_POLYHED)
5755         {
5756           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5757             cells.push_back(i);
5758         }
5759     }
5760 }
5761
5762 /*!
5763  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5764  * out of the cell. 
5765  *  \throw If \a this->getMeshDimension() != 3.
5766  *  \throw If \a this->getSpaceDimension() != 3.
5767  *  \throw If the coordinates array is not set.
5768  *  \throw If the nodal connectivity of cells is not defined.
5769  *  \throw If the reparation fails.
5770  *
5771  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5772  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5773  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5774  */
5775 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5776 {
5777   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5778     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5779   int nbOfCells=getNumberOfCells();
5780   int *conn=_nodal_connec->getPointer();
5781   const int *connI=_nodal_connec_index->getConstPointer();
5782   const double *coordsPtr=_coords->getConstPointer();
5783   for(int i=0;i<nbOfCells;i++)
5784     {
5785       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5786       if(type==INTERP_KERNEL::NORM_POLYHED)
5787         {
5788           try
5789             {
5790               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5791                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5792             }
5793           catch(INTERP_KERNEL::Exception& e)
5794             {
5795               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5796               throw INTERP_KERNEL::Exception(oss.str().c_str());
5797             }
5798         }
5799     }
5800   updateTime();
5801 }
5802
5803 /*!
5804  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5805  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5806  * according to which the first facet of the cell should be oriented to have the normal vector
5807  * pointing out of cell.
5808  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5809  *         cells. The caller is to delete this array using decrRef() as it is no more
5810  *         needed. 
5811  *  \throw If \a this->getMeshDimension() != 3.
5812  *  \throw If \a this->getSpaceDimension() != 3.
5813  *  \throw If the coordinates array is not set.
5814  *  \throw If the nodal connectivity of cells is not defined.
5815  *
5816  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5817  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5818  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5819  */
5820 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5821 {
5822   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5823   if(getMeshDimension()!=3)
5824     throw INTERP_KERNEL::Exception(msg);
5825   int spaceDim=getSpaceDimension();
5826   if(spaceDim!=3)
5827     throw INTERP_KERNEL::Exception(msg);
5828   //
5829   int nbOfCells=getNumberOfCells();
5830   int *conn=_nodal_connec->getPointer();
5831   const int *connI=_nodal_connec_index->getConstPointer();
5832   const double *coo=getCoords()->getConstPointer();
5833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5834   for(int i=0;i<nbOfCells;i++)
5835     {
5836       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5837       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5838         {
5839           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5840             {
5841               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5842               cells->pushBackSilent(i);
5843             }
5844         }
5845     }
5846   return cells.retn();
5847 }
5848
5849 /*!
5850  * This method is a faster method to correct orientation of all 3D cells in \a this.
5851  * 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.
5852  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5853  * 
5854  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5855  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5856  */
5857 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5858 {
5859   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5860     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5861   int nbOfCells=getNumberOfCells();
5862   int *conn=_nodal_connec->getPointer();
5863   const int *connI=_nodal_connec_index->getConstPointer();
5864   const double *coordsPtr=_coords->getConstPointer();
5865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5866   for(int i=0;i<nbOfCells;i++)
5867     {
5868       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5869       switch(type)
5870         {
5871         case INTERP_KERNEL::NORM_TETRA4:
5872           {
5873             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5874               {
5875                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5876                 ret->pushBackSilent(i);
5877               }
5878             break;
5879           }
5880         case INTERP_KERNEL::NORM_PYRA5:
5881           {
5882             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5883               {
5884                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5885                 ret->pushBackSilent(i);
5886               }
5887             break;
5888           }
5889         case INTERP_KERNEL::NORM_PENTA6:
5890         case INTERP_KERNEL::NORM_HEXA8:
5891         case INTERP_KERNEL::NORM_HEXGP12:
5892           {
5893             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5894               {
5895                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5896                 ret->pushBackSilent(i);
5897               }
5898             break;
5899           }
5900         case INTERP_KERNEL::NORM_POLYHED:
5901           {
5902             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5903               {
5904                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5905                 ret->pushBackSilent(i);
5906               }
5907             break;
5908           }
5909         default:
5910           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 !");
5911         }
5912     }
5913   updateTime();
5914   return ret.retn();
5915 }
5916
5917 /*!
5918  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5919  * If it is not the case an exception will be thrown.
5920  * This method is fast because the first cell of \a this is used to compute the plane.
5921  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5922  * \param pos output of size at least 3 used to store a point owned of searched plane.
5923  */
5924 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5925 {
5926   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5927     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5928   const int *conn=_nodal_connec->getConstPointer();
5929   const int *connI=_nodal_connec_index->getConstPointer();
5930   const double *coordsPtr=_coords->getConstPointer();
5931   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5932   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5933 }
5934
5935 /*!
5936  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5937  * cells. Currently cells of the following types are treated:
5938  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5939  * For a cell of other type an exception is thrown.
5940  * Space dimension of a 2D mesh can be either 2 or 3.
5941  * The Edge Ratio of a cell \f$t\f$ is: 
5942  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5943  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5944  *  the smallest edge lengths of \f$t\f$.
5945  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5946  *          cells and one time, lying on \a this mesh. The caller is to delete this
5947  *          field using decrRef() as it is no more needed. 
5948  *  \throw If the coordinates array is not set.
5949  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5950  *  \throw If the connectivity data array has more than one component.
5951  *  \throw If the connectivity data array has a named component.
5952  *  \throw If the connectivity index data array has more than one component.
5953  *  \throw If the connectivity index data array has a named component.
5954  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5955  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5956  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5957  */
5958 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5959 {
5960   checkCoherency();
5961   int spaceDim=getSpaceDimension();
5962   int meshDim=getMeshDimension();
5963   if(spaceDim!=2 && spaceDim!=3)
5964     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5965   if(meshDim!=2 && meshDim!=3)
5966     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5967   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5968   ret->setMesh(this);
5969   int nbOfCells=getNumberOfCells();
5970   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5971   arr->alloc(nbOfCells,1);
5972   double *pt=arr->getPointer();
5973   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5974   const int *conn=_nodal_connec->getConstPointer();
5975   const int *connI=_nodal_connec_index->getConstPointer();
5976   const double *coo=_coords->getConstPointer();
5977   double tmp[12];
5978   for(int i=0;i<nbOfCells;i++,pt++)
5979     {
5980       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5981       switch(t)
5982         {
5983           case INTERP_KERNEL::NORM_TRI3:
5984             {
5985               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5986               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5987               break;
5988             }
5989           case INTERP_KERNEL::NORM_QUAD4:
5990             {
5991               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5992               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5993               break;
5994             }
5995           case INTERP_KERNEL::NORM_TETRA4:
5996             {
5997               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5998               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5999               break;
6000             }
6001         default:
6002           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6003         }
6004       conn+=connI[i+1]-connI[i];
6005     }
6006   ret->setName("EdgeRatio");
6007   ret->synchronizeTimeWithSupport();
6008   return ret.retn();
6009 }
6010
6011 /*!
6012  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6013  * cells. Currently cells of the following types are treated:
6014  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6015  * For a cell of other type an exception is thrown.
6016  * Space dimension of a 2D mesh can be either 2 or 3.
6017  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6018  *          cells and one time, lying on \a this mesh. The caller is to delete this
6019  *          field using decrRef() as it is no more needed. 
6020  *  \throw If the coordinates array is not set.
6021  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6022  *  \throw If the connectivity data array has more than one component.
6023  *  \throw If the connectivity data array has a named component.
6024  *  \throw If the connectivity index data array has more than one component.
6025  *  \throw If the connectivity index data array has a named component.
6026  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6027  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6028  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6029  */
6030 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6031 {
6032   checkCoherency();
6033   int spaceDim=getSpaceDimension();
6034   int meshDim=getMeshDimension();
6035   if(spaceDim!=2 && spaceDim!=3)
6036     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6037   if(meshDim!=2 && meshDim!=3)
6038     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6039   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6040   ret->setMesh(this);
6041   int nbOfCells=getNumberOfCells();
6042   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6043   arr->alloc(nbOfCells,1);
6044   double *pt=arr->getPointer();
6045   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6046   const int *conn=_nodal_connec->getConstPointer();
6047   const int *connI=_nodal_connec_index->getConstPointer();
6048   const double *coo=_coords->getConstPointer();
6049   double tmp[12];
6050   for(int i=0;i<nbOfCells;i++,pt++)
6051     {
6052       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6053       switch(t)
6054         {
6055           case INTERP_KERNEL::NORM_TRI3:
6056             {
6057               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6058               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6059               break;
6060             }
6061           case INTERP_KERNEL::NORM_QUAD4:
6062             {
6063               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6064               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6065               break;
6066             }
6067           case INTERP_KERNEL::NORM_TETRA4:
6068             {
6069               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6070               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6071               break;
6072             }
6073         default:
6074           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6075         }
6076       conn+=connI[i+1]-connI[i];
6077     }
6078   ret->setName("AspectRatio");
6079   ret->synchronizeTimeWithSupport();
6080   return ret.retn();
6081 }
6082
6083 /*!
6084  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6085  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6086  * treated: INTERP_KERNEL::NORM_QUAD4.
6087  * For a cell of other type an exception is thrown.
6088  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6089  *          cells and one time, lying on \a this mesh. The caller is to delete this
6090  *          field using decrRef() as it is no more needed. 
6091  *  \throw If the coordinates array is not set.
6092  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6093  *  \throw If the connectivity data array has more than one component.
6094  *  \throw If the connectivity data array has a named component.
6095  *  \throw If the connectivity index data array has more than one component.
6096  *  \throw If the connectivity index data array has a named component.
6097  *  \throw If \a this->getMeshDimension() != 2.
6098  *  \throw If \a this->getSpaceDimension() != 3.
6099  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6100  */
6101 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6102 {
6103   checkCoherency();
6104   int spaceDim=getSpaceDimension();
6105   int meshDim=getMeshDimension();
6106   if(spaceDim!=3)
6107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6108   if(meshDim!=2)
6109     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6110   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6111   ret->setMesh(this);
6112   int nbOfCells=getNumberOfCells();
6113   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6114   arr->alloc(nbOfCells,1);
6115   double *pt=arr->getPointer();
6116   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6117   const int *conn=_nodal_connec->getConstPointer();
6118   const int *connI=_nodal_connec_index->getConstPointer();
6119   const double *coo=_coords->getConstPointer();
6120   double tmp[12];
6121   for(int i=0;i<nbOfCells;i++,pt++)
6122     {
6123       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6124       switch(t)
6125         {
6126           case INTERP_KERNEL::NORM_QUAD4:
6127             {
6128               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6129               *pt=INTERP_KERNEL::quadWarp(tmp);
6130               break;
6131             }
6132         default:
6133           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6134         }
6135       conn+=connI[i+1]-connI[i];
6136     }
6137   ret->setName("Warp");
6138   ret->synchronizeTimeWithSupport();
6139   return ret.retn();
6140 }
6141
6142
6143 /*!
6144  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6145  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6146  * treated: INTERP_KERNEL::NORM_QUAD4.
6147  * For a cell of other type an exception is thrown.
6148  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6149  *          cells and one time, lying on \a this mesh. The caller is to delete this
6150  *          field using decrRef() as it is no more needed. 
6151  *  \throw If the coordinates array is not set.
6152  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6153  *  \throw If the connectivity data array has more than one component.
6154  *  \throw If the connectivity data array has a named component.
6155  *  \throw If the connectivity index data array has more than one component.
6156  *  \throw If the connectivity index data array has a named component.
6157  *  \throw If \a this->getMeshDimension() != 2.
6158  *  \throw If \a this->getSpaceDimension() != 3.
6159  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6160  */
6161 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6162 {
6163   checkCoherency();
6164   int spaceDim=getSpaceDimension();
6165   int meshDim=getMeshDimension();
6166   if(spaceDim!=3)
6167     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6168   if(meshDim!=2)
6169     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6170   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6171   ret->setMesh(this);
6172   int nbOfCells=getNumberOfCells();
6173   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6174   arr->alloc(nbOfCells,1);
6175   double *pt=arr->getPointer();
6176   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6177   const int *conn=_nodal_connec->getConstPointer();
6178   const int *connI=_nodal_connec_index->getConstPointer();
6179   const double *coo=_coords->getConstPointer();
6180   double tmp[12];
6181   for(int i=0;i<nbOfCells;i++,pt++)
6182     {
6183       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6184       switch(t)
6185         {
6186           case INTERP_KERNEL::NORM_QUAD4:
6187             {
6188               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6189               *pt=INTERP_KERNEL::quadSkew(tmp);
6190               break;
6191             }
6192         default:
6193           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6194         }
6195       conn+=connI[i+1]-connI[i];
6196     }
6197   ret->setName("Skew");
6198   ret->synchronizeTimeWithSupport();
6199   return ret.retn();
6200 }
6201
6202 /*!
6203  * This method aggregate the bbox of each cell and put it into bbox parameter.
6204  * 
6205  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6206  * 
6207  * \throw If \a this is not fully set (coordinates and connectivity).
6208  * \throw If a cell in \a this has no valid nodeId.
6209  */
6210 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6211 {
6212   checkFullyDefined();
6213   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6214   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6215   double *bbox(ret->getPointer());
6216   for(int i=0;i<nbOfCells*spaceDim;i++)
6217     {
6218       bbox[2*i]=std::numeric_limits<double>::max();
6219       bbox[2*i+1]=-std::numeric_limits<double>::max();
6220     }
6221   const double *coordsPtr(_coords->getConstPointer());
6222   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6223   for(int i=0;i<nbOfCells;i++)
6224     {
6225       int offset=connI[i]+1;
6226       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6227       for(int j=0;j<nbOfNodesForCell;j++)
6228         {
6229           int nodeId=conn[offset+j];
6230           if(nodeId>=0 && nodeId<nbOfNodes)
6231             {
6232               for(int k=0;k<spaceDim;k++)
6233                 {
6234                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6235                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6236                 }
6237               kk++;
6238             }
6239         }
6240       if(kk==0)
6241         {
6242           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6243           throw INTERP_KERNEL::Exception(oss.str().c_str());
6244         }
6245     }
6246   return ret.retn();
6247 }
6248
6249 /// @cond INTERNAL
6250
6251 namespace ParaMEDMEMImpl
6252 {
6253   class ConnReader
6254   {
6255   public:
6256     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6257     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6258   private:
6259     const int *_conn;
6260     int _val;
6261   };
6262
6263   class ConnReader2
6264   {
6265   public:
6266     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6267     bool operator() (const int& pos) { return _conn[pos]==_val; }
6268   private:
6269     const int *_conn;
6270     int _val;
6271   };
6272 }
6273
6274 /// @endcond
6275
6276 /*!
6277  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6278  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6279  * \a this is composed in cell types.
6280  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6281  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6282  * This parameter is kept only for compatibility with other methode listed above.
6283  */
6284 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6285 {
6286   checkConnectivityFullyDefined();
6287   const int *conn=_nodal_connec->getConstPointer();
6288   const int *connI=_nodal_connec_index->getConstPointer();
6289   const int *work=connI;
6290   int nbOfCells=getNumberOfCells();
6291   std::size_t n=getAllTypes().size();
6292   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6293   std::set<INTERP_KERNEL::NormalizedCellType> types;
6294   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6295     {
6296       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6297       if(types.find(typ)!=types.end())
6298         {
6299           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6300           oss << " is not contiguous !";
6301           throw INTERP_KERNEL::Exception(oss.str().c_str());
6302         }
6303       types.insert(typ);
6304       ret[3*i]=typ;
6305       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6306       ret[3*i+1]=(int)std::distance(work,work2);
6307       work=work2;
6308     }
6309   return ret;
6310 }
6311
6312 /*!
6313  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6314  * only for types cell, type node is not managed.
6315  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6316  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6317  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6318  * If 2 or more same geometric type is in \a code and exception is thrown too.
6319  *
6320  * This method firstly checks
6321  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6322  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6323  * an exception is thrown too.
6324  * 
6325  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6326  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6327  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6328  */
6329 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6330 {
6331   if(code.empty())
6332     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6333   std::size_t sz=code.size();
6334   std::size_t n=sz/3;
6335   if(sz%3!=0)
6336     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6337   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6338   int nb=0;
6339   bool isNoPflUsed=true;
6340   for(std::size_t i=0;i<n;i++)
6341     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6342       {
6343         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6344         nb+=code[3*i+1];
6345         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6346           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6347         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6348       }
6349   if(types.size()!=n)
6350     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6351   if(isNoPflUsed)
6352     {
6353       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6354         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6355       if(types.size()==_types.size())
6356         return 0;
6357     }
6358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6359   ret->alloc(nb,1);
6360   int *retPtr=ret->getPointer();
6361   const int *connI=_nodal_connec_index->getConstPointer();
6362   const int *conn=_nodal_connec->getConstPointer();
6363   int nbOfCells=getNumberOfCells();
6364   const int *i=connI;
6365   int kk=0;
6366   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6367     {
6368       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6369       int offset=(int)std::distance(connI,i);
6370       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6371       int nbOfCellsOfCurType=(int)std::distance(i,j);
6372       if(code[3*kk+2]==-1)
6373         for(int k=0;k<nbOfCellsOfCurType;k++)
6374           *retPtr++=k+offset;
6375       else
6376         {
6377           int idInIdsPerType=code[3*kk+2];
6378           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6379             {
6380               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6381               if(zePfl)
6382                 {
6383                   zePfl->checkAllocated();
6384                   if(zePfl->getNumberOfComponents()==1)
6385                     {
6386                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6387                         {
6388                           if(*k>=0 && *k<nbOfCellsOfCurType)
6389                             *retPtr=(*k)+offset;
6390                           else
6391                             {
6392                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6393                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6394                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6395                             }
6396                         }
6397                     }
6398                   else
6399                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6400                 }
6401               else
6402                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6403             }
6404           else
6405             {
6406               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6407               oss << " should be in [0," << idsPerType.size() << ") !";
6408               throw INTERP_KERNEL::Exception(oss.str().c_str());
6409             }
6410         }
6411       i=j;
6412     }
6413   return ret.retn();
6414 }
6415
6416 /*!
6417  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6418  * 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.
6419  * 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.
6420  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6421  * 
6422  * \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.
6423  * \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,
6424  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6425  * \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.
6426  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6427  * \throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if \a this is not fully defined
6428  */
6429 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6430 {
6431   if(!profile)
6432     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6433   if(profile->getNumberOfComponents()!=1)
6434     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6435   checkConnectivityFullyDefined();
6436   const int *conn=_nodal_connec->getConstPointer();
6437   const int *connI=_nodal_connec_index->getConstPointer();
6438   int nbOfCells=getNumberOfCells();
6439   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6440   std::vector<int> typeRangeVals(1);
6441   for(const int *i=connI;i!=connI+nbOfCells;)
6442     {
6443       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6444       if(std::find(types.begin(),types.end(),curType)!=types.end())
6445         {
6446           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6447         }
6448       types.push_back(curType);
6449       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6450       typeRangeVals.push_back((int)std::distance(connI,i));
6451     }
6452   //
6453   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6454   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6458   //
6459   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6460   code.resize(3*nbOfCastsFinal);
6461   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6462   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6463   for(int i=0;i<nbOfCastsFinal;i++)
6464     {
6465       int castId=castsPresent->getIJ(i,0);
6466       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6467       idsInPflPerType2.push_back(tmp3);
6468       code[3*i]=(int)types[castId];
6469       code[3*i+1]=tmp3->getNumberOfTuples();
6470       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6471       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6472         {
6473           tmp4->copyStringInfoFrom(*profile);
6474           idsPerType2.push_back(tmp4);
6475           code[3*i+2]=(int)idsPerType2.size()-1;
6476         }
6477       else
6478         {
6479           code[3*i+2]=-1;
6480         }
6481     }
6482   std::size_t sz2=idsInPflPerType2.size();
6483   idsInPflPerType.resize(sz2);
6484   for(std::size_t i=0;i<sz2;i++)
6485     {
6486       DataArrayInt *locDa=idsInPflPerType2[i];
6487       locDa->incrRef();
6488       idsInPflPerType[i]=locDa;
6489     }
6490   std::size_t sz=idsPerType2.size();
6491   idsPerType.resize(sz);
6492   for(std::size_t i=0;i<sz;i++)
6493     {
6494       DataArrayInt *locDa=idsPerType2[i];
6495       locDa->incrRef();
6496       idsPerType[i]=locDa;
6497     }
6498 }
6499
6500 /*!
6501  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6502  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6503  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6504  * 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.
6505  */
6506 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6507 {
6508   checkFullyDefined();
6509   nM1LevMesh->checkFullyDefined();
6510   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6511     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6512   if(_coords!=nM1LevMesh->getCoords())
6513     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6516   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6518   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6519   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6520   tmp->setConnectivity(tmp0,tmp1);
6521   tmp->renumberCells(ret0->getConstPointer(),false);
6522   revDesc=tmp->getNodalConnectivity();
6523   revDescIndx=tmp->getNodalConnectivityIndex();
6524   DataArrayInt *ret=0;
6525   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6526     {
6527       int tmp2;
6528       ret->getMaxValue(tmp2);
6529       ret->decrRef();
6530       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6531       throw INTERP_KERNEL::Exception(oss.str().c_str());
6532     }
6533   nM1LevMeshIds=ret;
6534   //
6535   revDesc->incrRef();
6536   revDescIndx->incrRef();
6537   ret1->incrRef();
6538   ret0->incrRef();
6539   meshnM1Old2New=ret0;
6540   return ret1;
6541 }
6542
6543 /*!
6544  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6545  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6546  * in "Old to New" mode.
6547  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6548  *          this array using decrRef() as it is no more needed.
6549  *  \throw If the nodal connectivity of cells is not defined.
6550  */
6551 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6552 {
6553   checkConnectivityFullyDefined();
6554   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6555   renumberCells(ret->getConstPointer(),false);
6556   return ret.retn();
6557 }
6558
6559 /*!
6560  * This methods checks that cells are sorted by their types.
6561  * This method makes asumption (no check) that connectivity is correctly set before calling.
6562  */
6563 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6564 {
6565   checkFullyDefined();
6566   const int *conn=_nodal_connec->getConstPointer();
6567   const int *connI=_nodal_connec_index->getConstPointer();
6568   int nbOfCells=getNumberOfCells();
6569   std::set<INTERP_KERNEL::NormalizedCellType> types;
6570   for(const int *i=connI;i!=connI+nbOfCells;)
6571     {
6572       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6573       if(types.find(curType)!=types.end())
6574         return false;
6575       types.insert(curType);
6576       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6577     }
6578   return true;
6579 }
6580
6581 /*!
6582  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6583  * The geometric type order is specified by MED file.
6584  * 
6585  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6586  */
6587 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6588 {
6589   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6590 }
6591
6592 /*!
6593  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6594  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6595  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6596  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6597  */
6598 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6599 {
6600   checkFullyDefined();
6601   const int *conn=_nodal_connec->getConstPointer();
6602   const int *connI=_nodal_connec_index->getConstPointer();
6603   int nbOfCells=getNumberOfCells();
6604   if(nbOfCells==0)
6605     return true;
6606   int lastPos=-1;
6607   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6608   for(const int *i=connI;i!=connI+nbOfCells;)
6609     {
6610       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6611       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6612       if(isTypeExists!=orderEnd)
6613         {
6614           int pos=(int)std::distance(orderBg,isTypeExists);
6615           if(pos<=lastPos)
6616             return false;
6617           lastPos=pos;
6618           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6619         }
6620       else
6621         {
6622           if(sg.find(curType)==sg.end())
6623             {
6624               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6625               sg.insert(curType);
6626             }
6627           else
6628             return false;
6629         }
6630     }
6631   return true;
6632 }
6633
6634 /*!
6635  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6636  * 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
6637  * 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'.
6638  */
6639 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6640 {
6641   checkConnectivityFullyDefined();
6642   int nbOfCells=getNumberOfCells();
6643   const int *conn=_nodal_connec->getConstPointer();
6644   const int *connI=_nodal_connec_index->getConstPointer();
6645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6647   tmpa->alloc(nbOfCells,1);
6648   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6649   tmpb->fillWithZero();
6650   int *tmp=tmpa->getPointer();
6651   int *tmp2=tmpb->getPointer();
6652   for(const int *i=connI;i!=connI+nbOfCells;i++)
6653     {
6654       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6655       if(where!=orderEnd)
6656         {
6657           int pos=(int)std::distance(orderBg,where);
6658           tmp2[pos]++;
6659           tmp[std::distance(connI,i)]=pos;
6660         }
6661       else
6662         {
6663           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6664           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6665           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6666           throw INTERP_KERNEL::Exception(oss.str().c_str());
6667         }
6668     }
6669   nbPerType=tmpb.retn();
6670   return tmpa.retn();
6671 }
6672
6673 /*!
6674  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6675  *
6676  * \return a new object containing the old to new correspondance.
6677  *
6678  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6679  */
6680 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6681 {
6682   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6683 }
6684
6685 /*!
6686  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
6687  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6688  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6689  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6690  */
6691 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6692 {
6693   DataArrayInt *nbPerType=0;
6694   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6695   nbPerType->decrRef();
6696   return tmpa->buildPermArrPerLevel();
6697 }
6698
6699 /*!
6700  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6701  * The number of cells remains unchanged after the call of this method.
6702  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6703  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6704  *
6705  * \return the array giving the correspondance old to new.
6706  */
6707 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6708 {
6709   checkFullyDefined();
6710   computeTypes();
6711   const int *conn=_nodal_connec->getConstPointer();
6712   const int *connI=_nodal_connec_index->getConstPointer();
6713   int nbOfCells=getNumberOfCells();
6714   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6715   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6716     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6717       {
6718         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6719         types.push_back(curType);
6720         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6721       }
6722   DataArrayInt *ret=DataArrayInt::New();
6723   ret->alloc(nbOfCells,1);
6724   int *retPtr=ret->getPointer();
6725   std::fill(retPtr,retPtr+nbOfCells,-1);
6726   int newCellId=0;
6727   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6728     {
6729       for(const int *i=connI;i!=connI+nbOfCells;i++)
6730         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6731           retPtr[std::distance(connI,i)]=newCellId++;
6732     }
6733   renumberCells(retPtr,false);
6734   return ret;
6735 }
6736
6737 /*!
6738  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6739  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6740  * This method makes asumption that connectivity is correctly set before calling.
6741  */
6742 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6743 {
6744   checkConnectivityFullyDefined();
6745   const int *conn=_nodal_connec->getConstPointer();
6746   const int *connI=_nodal_connec_index->getConstPointer();
6747   int nbOfCells=getNumberOfCells();
6748   std::vector<MEDCouplingUMesh *> ret;
6749   for(const int *i=connI;i!=connI+nbOfCells;)
6750     {
6751       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6752       int beginCellId=(int)std::distance(connI,i);
6753       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6754       int endCellId=(int)std::distance(connI,i);
6755       int sz=endCellId-beginCellId;
6756       int *cells=new int[sz];
6757       for(int j=0;j<sz;j++)
6758         cells[j]=beginCellId+j;
6759       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6760       delete [] cells;
6761       ret.push_back(m);
6762     }
6763   return ret;
6764 }
6765
6766 /*!
6767  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6768  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6769  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6770  *
6771  * \return a newly allocated instance, that the caller must manage.
6772  * \throw If \a this contains more than one geometric type.
6773  * \throw If the nodal connectivity of \a this is not fully defined.
6774  * \throw If the internal data is not coherent.
6775  */
6776 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6777 {
6778   checkConnectivityFullyDefined();
6779     if(_types.size()!=1)
6780     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6781   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6782   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6783   ret->setCoords(getCoords());
6784   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6785   if(retC)
6786     {
6787       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6788       retC->setNodalConnectivity(c);
6789     }
6790   else
6791     {
6792       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6793       if(!retD)
6794         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6795       DataArrayInt *c=0,*ci=0;
6796       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6797       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6798       retD->setNodalConnectivity(cs,cis);
6799     }
6800   return ret.retn();
6801 }
6802
6803 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6804 {
6805   checkConnectivityFullyDefined();
6806     if(_types.size()!=1)
6807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6808   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6809   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6810   if(cm.isDynamic())
6811     {
6812       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6813       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6814       throw INTERP_KERNEL::Exception(oss.str().c_str());
6815     }
6816   int nbCells=getNumberOfCells();
6817   int typi=(int)typ;
6818   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6820   int *outPtr=connOut->getPointer();
6821   const int *conn=_nodal_connec->begin();
6822   const int *connI=_nodal_connec_index->begin();
6823   nbNodesPerCell++;
6824   for(int i=0;i<nbCells;i++,connI++)
6825     {
6826       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6827         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6828       else
6829         {
6830           std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
6831           throw INTERP_KERNEL::Exception(oss.str().c_str());
6832         }
6833     }
6834   return connOut.retn();
6835 }
6836
6837 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6838 {
6839   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6840   checkConnectivityFullyDefined();
6841   if(_types.size()!=1)
6842     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6843   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6844   if(lgth<nbCells)
6845     throw INTERP_KERNEL::Exception(msg0);
6846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6847   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6848   int *cp(c->getPointer()),*cip(ci->getPointer());
6849   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6850   cip[0]=0;
6851   for(int i=0;i<nbCells;i++,cip++,incip++)
6852     {
6853       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6854       int delta(stop-strt);
6855       if(delta>=1)
6856         {
6857           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6858             cp=std::copy(incp+strt,incp+stop,cp);
6859           else
6860             throw INTERP_KERNEL::Exception(msg0);
6861         }
6862       else
6863         throw INTERP_KERNEL::Exception(msg0);
6864       cip[1]=cip[0]+delta;
6865     }
6866   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6867 }
6868
6869 /*!
6870  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6871  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6872  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6873  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6874  * are not used here to avoid the build of big permutation array.
6875  *
6876  * \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
6877  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6878  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6879  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6880  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6881  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6882  * \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
6883  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6884  */
6885 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6886                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6887                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6888 {
6889   std::vector<const MEDCouplingUMesh *> ms2;
6890   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6891     if(*it)
6892       {
6893         (*it)->checkConnectivityFullyDefined();
6894         ms2.push_back(*it);
6895       }
6896   if(ms2.empty())
6897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6898   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6899   int meshDim=ms2[0]->getMeshDimension();
6900   std::vector<const MEDCouplingUMesh *> m1ssm;
6901   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6902   //
6903   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6904   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6905   int fake=0,rk=0;
6906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6907   ret1->alloc(0,1); ret2->alloc(0,1);
6908   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6909     {
6910       if(meshDim!=(*it)->getMeshDimension())
6911         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6912       if(refCoo!=(*it)->getCoords())
6913         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6914       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6915       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6916       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6917       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6918         {
6919           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6920           m1ssmSingleAuto.push_back(singleCell);
6921           m1ssmSingle.push_back(singleCell);
6922           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6923         }
6924     }
6925   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6927   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6928   for(std::size_t i=0;i<m1ssm.size();i++)
6929     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6930   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6931   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6932   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6933   return ret0.retn();
6934 }
6935
6936 /*!
6937  * This method returns a newly created DataArrayInt instance.
6938  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6939  */
6940 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6941 {
6942   checkFullyDefined();
6943   const int *conn=_nodal_connec->getConstPointer();
6944   const int *connIndex=_nodal_connec_index->getConstPointer();
6945   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6946   for(const int *w=begin;w!=end;w++)
6947     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6948       ret->pushBackSilent(*w);
6949   return ret.retn();
6950 }
6951
6952 /*!
6953  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6954  * are in [0:getNumberOfCells())
6955  */
6956 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6957 {
6958   checkFullyDefined();
6959   const int *conn=_nodal_connec->getConstPointer();
6960   const int *connI=_nodal_connec_index->getConstPointer();
6961   int nbOfCells=getNumberOfCells();
6962   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6963   int *tmp=new int[nbOfCells];
6964   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6965     {
6966       int j=0;
6967       for(const int *i=connI;i!=connI+nbOfCells;i++)
6968         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6969           tmp[std::distance(connI,i)]=j++;
6970     }
6971   DataArrayInt *ret=DataArrayInt::New();
6972   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6973   ret->copyStringInfoFrom(*da);
6974   int *retPtr=ret->getPointer();
6975   const int *daPtr=da->getConstPointer();
6976   int nbOfElems=da->getNbOfElems();
6977   for(int k=0;k<nbOfElems;k++)
6978     retPtr[k]=tmp[daPtr[k]];
6979   delete [] tmp;
6980   return ret;
6981 }
6982
6983 /*!
6984  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6985  * This method \b works \b for mesh sorted by type.
6986  * cells whose ids is in 'idsPerGeoType' array.
6987  * This method conserves coords and name of mesh.
6988  */
6989 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6990 {
6991   std::vector<int> code=getDistributionOfTypes();
6992   std::size_t nOfTypesInThis=code.size()/3;
6993   int sz=0,szOfType=0;
6994   for(std::size_t i=0;i<nOfTypesInThis;i++)
6995     {
6996       if(code[3*i]!=type)
6997         sz+=code[3*i+1];
6998       else
6999         szOfType=code[3*i+1];
7000     }
7001   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7002     if(*work<0 || *work>=szOfType)
7003       {
7004         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7005         oss << ". It should be in [0," << szOfType << ") !";
7006         throw INTERP_KERNEL::Exception(oss.str().c_str());
7007       }
7008   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7009   int *idsPtr=idsTokeep->getPointer();
7010   int offset=0;
7011   for(std::size_t i=0;i<nOfTypesInThis;i++)
7012     {
7013       if(code[3*i]!=type)
7014         for(int j=0;j<code[3*i+1];j++)
7015           *idsPtr++=offset+j;
7016       else
7017         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7018       offset+=code[3*i+1];
7019     }
7020   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7021   ret->copyTinyInfoFrom(this);
7022   return ret.retn();
7023 }
7024
7025 /*!
7026  * This method returns a vector of size 'this->getNumberOfCells()'.
7027  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7028  */
7029 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7030 {
7031   int ncell=getNumberOfCells();
7032   std::vector<bool> ret(ncell);
7033   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7034   const int *c=getNodalConnectivity()->getConstPointer();
7035   for(int i=0;i<ncell;i++)
7036     {
7037       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7038       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7039       ret[i]=cm.isQuadratic();
7040     }
7041   return ret;
7042 }
7043
7044 /*!
7045  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7046  */
7047 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7048 {
7049   if(other->getType()!=UNSTRUCTURED)
7050     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7051   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7052   return MergeUMeshes(this,otherC);
7053 }
7054
7055 /*!
7056  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7057  * computed by averaging coordinates of cell nodes, so this method is not a right
7058  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7059  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7060  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7061  *          components. The caller is to delete this array using decrRef() as it is
7062  *          no more needed.
7063  *  \throw If the coordinates array is not set.
7064  *  \throw If the nodal connectivity of cells is not defined.
7065  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7066  */
7067 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7068 {
7069   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7070   int spaceDim=getSpaceDimension();
7071   int nbOfCells=getNumberOfCells();
7072   ret->alloc(nbOfCells,spaceDim);
7073   ret->copyStringInfoFrom(*getCoords());
7074   double *ptToFill=ret->getPointer();
7075   const int *nodal=_nodal_connec->getConstPointer();
7076   const int *nodalI=_nodal_connec_index->getConstPointer();
7077   const double *coor=_coords->getConstPointer();
7078   for(int i=0;i<nbOfCells;i++)
7079     {
7080       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7081       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7082       ptToFill+=spaceDim;
7083     }
7084   return ret.retn();
7085 }
7086
7087 /*!
7088  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7089  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7090  * 
7091  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7092  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7093  * 
7094  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7095  * \throw If \a this is not fully defined (coordinates and connectivity)
7096  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7097  */
7098 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7099 {
7100   checkFullyDefined();
7101   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7102   int spaceDim=getSpaceDimension();
7103   int nbOfCells=getNumberOfCells();
7104   int nbOfNodes=getNumberOfNodes();
7105   ret->alloc(nbOfCells,spaceDim);
7106   double *ptToFill=ret->getPointer();
7107   const int *nodal=_nodal_connec->getConstPointer();
7108   const int *nodalI=_nodal_connec_index->getConstPointer();
7109   const double *coor=_coords->getConstPointer();
7110   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7111     {
7112       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7113       std::fill(ptToFill,ptToFill+spaceDim,0.);
7114       if(type!=INTERP_KERNEL::NORM_POLYHED)
7115         {
7116           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7117             {
7118               if(*conn>=0 && *conn<nbOfNodes)
7119                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7120               else
7121                 {
7122                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7123                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7124                 }
7125             }
7126           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7127           if(nbOfNodesInCell>0)
7128             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7129           else
7130             {
7131               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7132               throw INTERP_KERNEL::Exception(oss.str().c_str());
7133             }
7134         }
7135       else
7136         {
7137           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7138           s.erase(-1);
7139           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7140             {
7141               if(*it>=0 && *it<nbOfNodes)
7142                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7143               else
7144                 {
7145                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7146                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7147                 }
7148             }
7149           if(!s.empty())
7150             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7151           else
7152             {
7153               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7154               throw INTERP_KERNEL::Exception(oss.str().c_str());
7155             }
7156         }
7157     }
7158   return ret.retn();
7159 }
7160
7161 /*!
7162  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7163  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7164  * are specified via an array of cell ids. 
7165  *  \warning Validity of the specified cell ids is not checked! 
7166  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7167  *  \param [in] begin - an array of cell ids of interest.
7168  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7169  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7170  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7171  *          caller is to delete this array using decrRef() as it is no more needed. 
7172  *  \throw If the coordinates array is not set.
7173  *  \throw If the nodal connectivity of cells is not defined.
7174  *
7175  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7176  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7177  */
7178 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7179 {
7180   DataArrayDouble *ret=DataArrayDouble::New();
7181   int spaceDim=getSpaceDimension();
7182   int nbOfTuple=(int)std::distance(begin,end);
7183   ret->alloc(nbOfTuple,spaceDim);
7184   double *ptToFill=ret->getPointer();
7185   double *tmp=new double[spaceDim];
7186   const int *nodal=_nodal_connec->getConstPointer();
7187   const int *nodalI=_nodal_connec_index->getConstPointer();
7188   const double *coor=_coords->getConstPointer();
7189   for(const int *w=begin;w!=end;w++)
7190     {
7191       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7192       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7193       ptToFill+=spaceDim;
7194     }
7195   delete [] tmp;
7196   return ret;
7197 }
7198
7199 /*!
7200  * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7201  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7202  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7203  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7204  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7205  * 
7206  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7207  * \throw If spaceDim!=3 or meshDim!=2.
7208  * \throw If connectivity of \a this is invalid.
7209  * \throw If connectivity of a cell in \a this points to an invalid node.
7210  */
7211 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7212 {
7213   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7214   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7215   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7216     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7217   ret->alloc(nbOfCells,4);
7218   double *retPtr(ret->getPointer());
7219   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7220   const double *coor(_coords->begin());
7221   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7222     {
7223       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7224       if(nodalI[1]-nodalI[0]>=3)
7225         {
7226           for(int j=0;j<3;j++)
7227             {
7228               int nodeId(nodal[nodalI[0]+1+j]);
7229               if(nodeId>=0 && nodeId<nbOfNodes)
7230                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7231               else
7232                 {
7233                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7234                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7235                 }
7236             }
7237         }
7238       else
7239         {
7240           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7241           throw INTERP_KERNEL::Exception(oss.str().c_str());
7242         }
7243       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7244       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7245     }
7246   return ret.retn();
7247 }
7248
7249 /*!
7250  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7251  * 
7252  */
7253 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7254 {
7255   if(!da)
7256     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7257   da->checkAllocated();
7258   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7259   ret->setCoords(da);
7260   int nbOfTuples=da->getNumberOfTuples();
7261   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7263   c->alloc(2*nbOfTuples,1);
7264   cI->alloc(nbOfTuples+1,1);
7265   int *cp=c->getPointer();
7266   int *cip=cI->getPointer();
7267   *cip++=0;
7268   for(int i=0;i<nbOfTuples;i++)
7269     {
7270       *cp++=INTERP_KERNEL::NORM_POINT1;
7271       *cp++=i;
7272       *cip++=2*(i+1);
7273     }
7274   ret->setConnectivity(c,cI,true);
7275   return ret.retn();
7276 }
7277 /*!
7278  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7279  * Cells and nodes of
7280  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7281  *  \param [in] mesh1 - the first mesh.
7282  *  \param [in] mesh2 - the second mesh.
7283  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7284  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7285  *          is no more needed.
7286  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7287  *  \throw If the coordinates array is not set in none of the meshes.
7288  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7289  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7290  */
7291 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7292 {
7293   std::vector<const MEDCouplingUMesh *> tmp(2);
7294   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7295   return MergeUMeshes(tmp);
7296 }
7297
7298 /*!
7299  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7300  * Cells and nodes of
7301  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7302  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7303  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7304  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7305  *          is no more needed.
7306  *  \throw If \a a.size() == 0.
7307  *  \throw If \a a[ *i* ] == NULL.
7308  *  \throw If the coordinates array is not set in none of the meshes.
7309  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7310  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7311 */
7312 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7313 {
7314   std::size_t sz=a.size();
7315   if(sz==0)
7316     return MergeUMeshesLL(a);
7317   for(std::size_t ii=0;ii<sz;ii++)
7318     if(!a[ii])
7319       {
7320         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7321         throw INTERP_KERNEL::Exception(oss.str().c_str());
7322       }
7323   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7324   std::vector< const MEDCouplingUMesh * > aa(sz);
7325   int spaceDim=-3;
7326   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7327     {
7328       const MEDCouplingUMesh *cur=a[i];
7329       const DataArrayDouble *coo=cur->getCoords();
7330       if(coo)
7331         spaceDim=coo->getNumberOfComponents();
7332     }
7333   if(spaceDim==-3)
7334     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7335   for(std::size_t i=0;i<sz;i++)
7336     {
7337       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7338       aa[i]=bb[i];
7339     }
7340   return MergeUMeshesLL(aa);
7341 }
7342
7343 /// @cond INTERNAL
7344
7345 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7346 {
7347   if(a.empty())
7348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7349   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7350   int meshDim=(*it)->getMeshDimension();
7351   int nbOfCells=(*it)->getNumberOfCells();
7352   int meshLgth=(*it++)->getMeshLength();
7353   for(;it!=a.end();it++)
7354     {
7355       if(meshDim!=(*it)->getMeshDimension())
7356         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7357       nbOfCells+=(*it)->getNumberOfCells();
7358       meshLgth+=(*it)->getMeshLength();
7359     }
7360   std::vector<const MEDCouplingPointSet *> aps(a.size());
7361   std::copy(a.begin(),a.end(),aps.begin());
7362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7363   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7364   ret->setCoords(pts);
7365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7366   c->alloc(meshLgth,1);
7367   int *cPtr=c->getPointer();
7368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7369   cI->alloc(nbOfCells+1,1);
7370   int *cIPtr=cI->getPointer();
7371   *cIPtr++=0;
7372   int offset=0;
7373   int offset2=0;
7374   for(it=a.begin();it!=a.end();it++)
7375     {
7376       int curNbOfCell=(*it)->getNumberOfCells();
7377       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7378       const int *curC=(*it)->_nodal_connec->getConstPointer();
7379       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7380       for(int j=0;j<curNbOfCell;j++)
7381         {
7382           const int *src=curC+curCI[j];
7383           *cPtr++=*src++;
7384           for(;src!=curC+curCI[j+1];src++,cPtr++)
7385             {
7386               if(*src!=-1)
7387                 *cPtr=*src+offset2;
7388               else
7389                 *cPtr=-1;
7390             }
7391         }
7392       offset+=curCI[curNbOfCell];
7393       offset2+=(*it)->getNumberOfNodes();
7394     }
7395   //
7396   ret->setConnectivity(c,cI,true);
7397   return ret.retn();
7398 }
7399
7400 /// @endcond
7401
7402 /*!
7403  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7404  * dimension and sharing the node coordinates array.
7405  * All cells of the first mesh precede all cells of the second mesh
7406  * within the result mesh. 
7407  *  \param [in] mesh1 - the first mesh.
7408  *  \param [in] mesh2 - the second mesh.
7409  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7410  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7411  *          is no more needed.
7412  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7413  *  \throw If the meshes do not share the node coordinates array.
7414  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7415  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7416  */
7417 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7418 {
7419   std::vector<const MEDCouplingUMesh *> tmp(2);
7420   tmp[0]=mesh1; tmp[1]=mesh2;
7421   return MergeUMeshesOnSameCoords(tmp);
7422 }
7423
7424 /*!
7425  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7426  * dimension and sharing the node coordinates array.
7427  * All cells of the *i*-th mesh precede all cells of the
7428  * (*i*+1)-th mesh within the result mesh.
7429  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7430  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7431  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7432  *          is no more needed.
7433  *  \throw If \a a.size() == 0.
7434  *  \throw If \a a[ *i* ] == NULL.
7435  *  \throw If the meshes do not share the node coordinates array.
7436  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7437  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7438  */
7439 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7440 {
7441   if(meshes.empty())
7442     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7443   for(std::size_t ii=0;ii<meshes.size();ii++)
7444     if(!meshes[ii])
7445       {
7446         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7447         throw INTERP_KERNEL::Exception(oss.str().c_str());
7448       }
7449   const DataArrayDouble *coords=meshes.front()->getCoords();
7450   int meshDim=meshes.front()->getMeshDimension();
7451   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7452   int meshLgth=0;
7453   int meshIndexLgth=0;
7454   for(;iter!=meshes.end();iter++)
7455     {
7456       if(coords!=(*iter)->getCoords())
7457         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7458       if(meshDim!=(*iter)->getMeshDimension())
7459         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7460       meshLgth+=(*iter)->getMeshLength();
7461       meshIndexLgth+=(*iter)->getNumberOfCells();
7462     }
7463   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7464   nodal->alloc(meshLgth,1);
7465   int *nodalPtr=nodal->getPointer();
7466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7467   nodalIndex->alloc(meshIndexLgth+1,1);
7468   int *nodalIndexPtr=nodalIndex->getPointer();
7469   int offset=0;
7470   for(iter=meshes.begin();iter!=meshes.end();iter++)
7471     {
7472       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7473       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7474       int nbOfCells=(*iter)->getNumberOfCells();
7475       int meshLgth2=(*iter)->getMeshLength();
7476       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7477       if(iter!=meshes.begin())
7478         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7479       else
7480         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7481       offset+=meshLgth2;
7482     }
7483   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7484   ret->setName("merge");
7485   ret->setMeshDimension(meshDim);
7486   ret->setConnectivity(nodal,nodalIndex,true);
7487   ret->setCoords(coords);
7488   return ret;
7489 }
7490
7491 /*!
7492  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7493  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7494  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7495  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7496  * New" mode are returned for each input mesh.
7497  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7498  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7499  *          valid values [0,1,2], see zipConnectivityTraducer().
7500  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7501  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7502  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7503  *          no more needed.
7504  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7505  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7506  *          is no more needed.
7507  *  \throw If \a meshes.size() == 0.
7508  *  \throw If \a meshes[ *i* ] == NULL.
7509  *  \throw If the meshes do not share the node coordinates array.
7510  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7511  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7512  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7513  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7514  */
7515 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7516 {
7517   //All checks are delegated to MergeUMeshesOnSameCoords
7518   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7519   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7520   corr.resize(meshes.size());
7521   std::size_t nbOfMeshes=meshes.size();
7522   int offset=0;
7523   const int *o2nPtr=o2n->getConstPointer();
7524   for(std::size_t i=0;i<nbOfMeshes;i++)
7525     {
7526       DataArrayInt *tmp=DataArrayInt::New();
7527       int curNbOfCells=meshes[i]->getNumberOfCells();
7528       tmp->alloc(curNbOfCells,1);
7529       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7530       offset+=curNbOfCells;
7531       tmp->setName(meshes[i]->getName().c_str());
7532       corr[i]=tmp;
7533     }
7534   return ret.retn();
7535 }
7536
7537 /*!
7538  * Makes all given meshes share the nodal connectivity array. The common connectivity
7539  * array is created by concatenating the connectivity arrays of all given meshes. All
7540  * the given meshes must be of the same space dimension but dimension of cells **can
7541  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7542  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7543  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7544  *  \param [in,out] meshes - a vector of meshes to update.
7545  *  \throw If any of \a meshes is NULL.
7546  *  \throw If the coordinates array is not set in any of \a meshes.
7547  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7548  *  \throw If \a meshes are of different space dimension.
7549  */
7550 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7551 {
7552   std::size_t sz=meshes.size();
7553   if(sz==0 || sz==1)
7554     return;
7555   std::vector< const DataArrayDouble * > coords(meshes.size());
7556   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7557   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7558     {
7559       if((*it))
7560         {
7561           (*it)->checkConnectivityFullyDefined();
7562           const DataArrayDouble *coo=(*it)->getCoords();
7563           if(coo)
7564             *it2=coo;
7565           else
7566             {
7567               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7568               oss << " has no coordinate array defined !";
7569               throw INTERP_KERNEL::Exception(oss.str().c_str());
7570             }
7571         }
7572       else
7573         {
7574           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7575           oss << " is null !";
7576           throw INTERP_KERNEL::Exception(oss.str().c_str());
7577         }
7578     }
7579   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7580   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7581   int offset=(*it)->getNumberOfNodes();
7582   (*it++)->setCoords(res);
7583   for(;it!=meshes.end();it++)
7584     {
7585       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7586       (*it)->setCoords(res);
7587       (*it)->shiftNodeNumbersInConn(offset);
7588       offset+=oldNumberOfNodes;
7589     }
7590 }
7591
7592 /*!
7593  * Merges nodes coincident with a given precision within all given meshes that share
7594  * the nodal connectivity array. The given meshes **can be of different** mesh
7595  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7596  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7597  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7598  *  \param [in,out] meshes - a vector of meshes to update.
7599  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7600  *  \throw If any of \a meshes is NULL.
7601  *  \throw If the \a meshes do not share the same node coordinates array.
7602  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7603  */
7604 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7605 {
7606   if(meshes.empty())
7607     return ;
7608   std::set<const DataArrayDouble *> s;
7609   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7610     {
7611       if(*it)
7612         s.insert((*it)->getCoords());
7613       else
7614         {
7615           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 !";
7616           throw INTERP_KERNEL::Exception(oss.str().c_str());
7617         }
7618     }
7619   if(s.size()!=1)
7620     {
7621       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 !";
7622       throw INTERP_KERNEL::Exception(oss.str().c_str());
7623     }
7624   const DataArrayDouble *coo=*(s.begin());
7625   if(!coo)
7626     return;
7627   //
7628   DataArrayInt *comm,*commI;
7629   coo->findCommonTuples(eps,-1,comm,commI);
7630   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7631   int oldNbOfNodes=coo->getNumberOfTuples();
7632   int newNbOfNodes;
7633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7634   if(oldNbOfNodes==newNbOfNodes)
7635     return ;
7636   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7637   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7638     {
7639       (*it)->renumberNodesInConn(o2n->getConstPointer());
7640       (*it)->setCoords(newCoords);
7641     } 
7642 }
7643
7644 /*!
7645  * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [ \a connBg , \a connEnd ) and returns its extruded cell by inserting the result at the end of ret.
7646  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7647  * \param isQuad specifies the policy of connectivity.
7648  * @ret in/out parameter in which the result will be append
7649  */
7650 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7651 {
7652   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7653   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7654   ret.push_back(cm.getExtrudedType());
7655   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7656   switch(flatType)
7657     {
7658     case INTERP_KERNEL::NORM_POINT1:
7659       {
7660         ret.push_back(connBg[1]);
7661         ret.push_back(connBg[1]+nbOfNodesPerLev);
7662         break;
7663       }
7664     case INTERP_KERNEL::NORM_SEG2:
7665       {
7666         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7667         ret.insert(ret.end(),conn,conn+4);
7668         break;
7669       }
7670     case INTERP_KERNEL::NORM_SEG3:
7671       {
7672         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7673         ret.insert(ret.end(),conn,conn+8);
7674         break;
7675       }
7676     case INTERP_KERNEL::NORM_QUAD4:
7677       {
7678         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7679         ret.insert(ret.end(),conn,conn+8);
7680         break;
7681       }
7682     case INTERP_KERNEL::NORM_TRI3:
7683       {
7684         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7685         ret.insert(ret.end(),conn,conn+6);
7686         break;
7687       }
7688     case INTERP_KERNEL::NORM_TRI6:
7689       {
7690         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,
7691                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7692         ret.insert(ret.end(),conn,conn+15);
7693         break;
7694       }
7695     case INTERP_KERNEL::NORM_QUAD8:
7696       {
7697         int conn[20]={
7698           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7699           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7700           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7701         };
7702         ret.insert(ret.end(),conn,conn+20);
7703         break;
7704       }
7705     case INTERP_KERNEL::NORM_POLYGON:
7706       {
7707         std::back_insert_iterator< std::vector<int> > ii(ret);
7708         std::copy(connBg+1,connEnd,ii);
7709         *ii++=-1;
7710         std::reverse_iterator<const int *> rConnBg(connEnd);
7711         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7712         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7713         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7714         for(std::size_t i=0;i<nbOfRadFaces;i++)
7715           {
7716             *ii++=-1;
7717             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7718             std::copy(conn,conn+4,ii);
7719           }
7720         break;
7721       }
7722     default:
7723       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7724     }
7725 }
7726
7727 /*!
7728  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7729  */
7730 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7731 {
7732   double v[3]={0.,0.,0.};
7733   std::size_t sz=std::distance(begin,end);
7734   if(isQuadratic)
7735     sz/=2;
7736   for(std::size_t i=0;i<sz;i++)
7737     {
7738       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];
7739       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7740       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7741     }
7742   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7743 }
7744
7745 /*!
7746  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7747  */
7748 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7749 {
7750   std::vector<std::pair<int,int> > edges;
7751   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7752   const int *bgFace=begin;
7753   for(std::size_t i=0;i<nbOfFaces;i++)
7754     {
7755       const int *endFace=std::find(bgFace+1,end,-1);
7756       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7757       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7758         {
7759           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7760           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7761             return false;
7762           edges.push_back(p1);
7763         }
7764       bgFace=endFace+1;
7765     }
7766   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7767 }
7768
7769 /*!
7770  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7771  */
7772 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7773 {
7774   double vec0[3],vec1[3];
7775   std::size_t sz=std::distance(begin,end);
7776   if(sz%2!=0)
7777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7778   int nbOfNodes=(int)sz/2;
7779   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7780   const double *pt0=coords+3*begin[0];
7781   const double *pt1=coords+3*begin[nbOfNodes];
7782   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7783   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7784 }
7785
7786 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7787 {
7788   std::size_t sz=std::distance(begin,end);
7789   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7790   std::size_t nbOfNodes(sz/2);
7791   std::copy(begin,end,(int *)tmp);
7792   for(std::size_t j=1;j<nbOfNodes;j++)
7793     {
7794       begin[j]=tmp[nbOfNodes-j];
7795       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7796     }
7797 }
7798
7799 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7800 {
7801   std::size_t sz=std::distance(begin,end);
7802   if(sz!=4)
7803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7804   double vec0[3],vec1[3];
7805   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7806   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]; 
7807   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;
7808 }
7809
7810 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7811 {
7812   std::size_t sz=std::distance(begin,end);
7813   if(sz!=5)
7814     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7815   double vec0[3];
7816   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7817   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7818   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7819 }
7820
7821 /*!
7822  * 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 ) 
7823  * 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
7824  * a 2D space.
7825  *
7826  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7827  * \param [in] coords the coordinates with nb of components exactly equal to 3
7828  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7829  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7830  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7831  */
7832 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
7833 {
7834   int nbFaces=std::count(begin+1,end,-1)+1;
7835   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7836   double *vPtr=v->getPointer();
7837   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7838   double *pPtr=p->getPointer();
7839   const int *stFaceConn=begin+1;
7840   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7841     {
7842       const int *endFaceConn=std::find(stFaceConn,end,-1);
7843       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7844       stFaceConn=endFaceConn+1;
7845     }
7846   pPtr=p->getPointer(); vPtr=v->getPointer();
7847   DataArrayInt *comm1=0,*commI1=0;
7848   v->findCommonTuples(eps,-1,comm1,commI1);
7849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7850   const int *comm1Ptr=comm1->getConstPointer();
7851   const int *commI1Ptr=commI1->getConstPointer();
7852   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7853   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7854   //
7855   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7856   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7857   mm->finishInsertingCells();
7858   //
7859   for(int i=0;i<nbOfGrps1;i++)
7860     {
7861       int vecId=comm1Ptr[commI1Ptr[i]];
7862       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7863       DataArrayInt *comm2=0,*commI2=0;
7864       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7865       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7866       const int *comm2Ptr=comm2->getConstPointer();
7867       const int *commI2Ptr=commI2->getConstPointer();
7868       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7869       for(int j=0;j<nbOfGrps2;j++)
7870         {
7871           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7872             {
7873               res->insertAtTheEnd(begin,end);
7874               res->pushBackSilent(-1);
7875             }
7876           else
7877             {
7878               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7879               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7880               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7881               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7882               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7883               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7884               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7885               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7886               const int *idsNodePtr=idsNode->getConstPointer();
7887               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];
7888               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7889               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7890               if(std::abs(norm)>eps)
7891                 {
7892                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7893                   mm3->rotate(center,vec,angle);
7894                 }
7895               mm3->changeSpaceDimension(2);
7896               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7897               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7898               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7899               int nbOfCells=mm4->getNumberOfCells();
7900               for(int k=0;k<nbOfCells;k++)
7901                 {
7902                   int l=0;
7903                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7904                     res->pushBackSilent(idsNodePtr[*work]);
7905                   res->pushBackSilent(-1);
7906                 }
7907             }
7908         }
7909     }
7910   res->popBackSilent();
7911 }
7912
7913 /*!
7914  * 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
7915  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7916  * 
7917  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7918  * \param [in] coords coordinates expected to have 3 components.
7919  * \param [in] begin start of the nodal connectivity of the face.
7920  * \param [in] end end of the nodal connectivity (excluded) of the face.
7921  * \param [out] v the normalized vector of size 3
7922  * \param [out] p the pos of plane
7923  */
7924 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7925 {
7926   std::size_t nbPoints=std::distance(begin,end);
7927   if(nbPoints<3)
7928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7929   double vec[3]={0.,0.,0.};
7930   std::size_t j=0;
7931   bool refFound=false;
7932   for(;j<nbPoints-1 && !refFound;j++)
7933     {
7934       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7935       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7936       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7937       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7938       if(norm>eps)
7939         {
7940           refFound=true;
7941           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7942         }
7943     }
7944   for(std::size_t i=j;i<nbPoints-1;i++)
7945     {
7946       double curVec[3];
7947       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7948       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7949       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7950       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7951       if(norm<eps)
7952         continue;
7953       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7954       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];
7955       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7956       if(norm>eps)
7957         {
7958           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7959           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7960           return ;
7961         }
7962     }
7963   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7964 }
7965
7966 /*!
7967  * This method tries to obtain a well oriented polyhedron.
7968  * If the algorithm fails, an exception will be thrown.
7969  */
7970 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7971 {
7972   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7973   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7974   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7975   isPerm[0]=true;
7976   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7977   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7978   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7979   //
7980   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7981     {
7982       bgFace=begin;
7983       std::size_t smthChanged=0;
7984       for(std::size_t i=0;i<nbOfFaces;i++)
7985         {
7986           endFace=std::find(bgFace+1,end,-1);
7987           nbOfEdgesInFace=std::distance(bgFace,endFace);
7988           if(!isPerm[i])
7989             {
7990               bool b;
7991               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7992                 {
7993                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7994                   std::pair<int,int> p2(p1.second,p1.first);
7995                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7996                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7997                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7998                 }
7999               if(isPerm[i])
8000                 { 
8001                   if(!b)
8002                     std::reverse(bgFace+1,endFace);
8003                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8004                     {
8005                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8006                       std::pair<int,int> p2(p1.second,p1.first);
8007                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8008                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8009                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8010                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8011                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8012                       if(it!=edgesOK.end())
8013                         {
8014                           edgesOK.erase(it);
8015                           edgesFinished.push_back(p1);
8016                         }
8017                       else
8018                         edgesOK.push_back(p1);
8019                     }
8020                 }
8021             }
8022           bgFace=endFace+1;
8023         }
8024       if(smthChanged==0)
8025         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8026     }
8027   if(!edgesOK.empty())
8028     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8029   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8030     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8031       bgFace=begin;
8032       for(std::size_t i=0;i<nbOfFaces;i++)
8033         {
8034           endFace=std::find(bgFace+1,end,-1);
8035           std::reverse(bgFace+1,endFace);
8036           bgFace=endFace+1;
8037         }
8038     }
8039 }
8040
8041 /*!
8042  * This method makes the assumption spacedimension == meshdimension == 2.
8043  * This method works only for linear cells.
8044  * 
8045  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8046  */
8047 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8048 {
8049   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8051   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8053   int nbOfNodesExpected=m->getNumberOfNodes();
8054   if(m->getNumberOfCells()!=nbOfNodesExpected)
8055     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8056   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8057   const int *n2oPtr=n2o->getConstPointer();
8058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8059   m->getReverseNodalConnectivity(revNodal,revNodalI);
8060   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8061   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8062   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8063   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8064   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
8065   if(nbOfNodesExpected<1)
8066     return ret.retn();
8067   int prevCell=0;
8068   int prevNode=nodalPtr[nodalIPtr[0]+1];
8069   *work++=n2oPtr[prevNode];
8070   for(int i=1;i<nbOfNodesExpected;i++)
8071     {
8072       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8073         {
8074           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8075           conn.erase(prevNode);
8076           if(conn.size()==1)
8077             {
8078               int curNode=*(conn.begin());
8079               *work++=n2oPtr[curNode];
8080               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8081               shar.erase(prevCell);
8082               if(shar.size()==1)
8083                 {
8084                   prevCell=*(shar.begin());
8085                   prevNode=curNode;
8086                 }
8087               else
8088                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8089             }
8090           else
8091             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8092         }
8093       else
8094         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8095     }
8096   return ret.retn();
8097 }
8098
8099 /*!
8100  * This method makes the assumption spacedimension == meshdimension == 3.
8101  * This method works only for linear cells.
8102  * 
8103  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8104  */
8105 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8106 {
8107   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8109   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8110   const int *conn=m->getNodalConnectivity()->getConstPointer();
8111   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8112   int nbOfCells=m->getNumberOfCells();
8113   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8114   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8115   if(nbOfCells<1)
8116     return ret.retn();
8117   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8118   for(int i=1;i<nbOfCells;i++)
8119     {
8120       *work++=-1;
8121       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8122     }
8123   return ret.retn();
8124 }
8125
8126 /*!
8127  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8128  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8129  */
8130 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8131 {
8132   double *w=zipFrmt;
8133   if(spaceDim==3)
8134     for(int i=0;i<nbOfNodesInCell;i++)
8135       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8136   else if(spaceDim==2)
8137     {
8138       for(int i=0;i<nbOfNodesInCell;i++)
8139         {
8140           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8141           *w++=0.;
8142         }
8143     }
8144   else
8145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8146 }
8147
8148 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8149 {
8150   int nbOfCells=getNumberOfCells();
8151   if(nbOfCells<=0)
8152     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8153   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};
8154   ofs << "  <" << getVTKDataSetType() << ">\n";
8155   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8156   ofs << "      <PointData>\n" << pointData << std::endl;
8157   ofs << "      </PointData>\n";
8158   ofs << "      <CellData>\n" << cellData << std::endl;
8159   ofs << "      </CellData>\n";
8160   ofs << "      <Points>\n";
8161   if(getSpaceDimension()==3)
8162     _coords->writeVTK(ofs,8,"Points",byteData);
8163   else
8164     {
8165       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8166       coo->writeVTK(ofs,8,"Points",byteData);
8167     }
8168   ofs << "      </Points>\n";
8169   ofs << "      <Cells>\n";
8170   const int *cPtr=_nodal_connec->getConstPointer();
8171   const int *cIPtr=_nodal_connec_index->getConstPointer();
8172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8176   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8177   int szFaceOffsets=0,szConn=0;
8178   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8179     {
8180       *w2=cPtr[cIPtr[i]];
8181       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8182         {
8183           *w1=-1;
8184           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8185           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8186         }
8187       else
8188         {
8189           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8190           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8191           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8192           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8193           w4=std::copy(c.begin(),c.end(),w4);
8194         }
8195     }
8196   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8197   types->writeVTK(ofs,8,"UInt8","types",byteData);
8198   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8199   if(szFaceOffsets!=0)
8200     {//presence of Polyhedra
8201       connectivity->reAlloc(szConn);
8202       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8203       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8204       w1=faces->getPointer();
8205       for(int i=0;i<nbOfCells;i++)
8206         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8207           {
8208             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8209             *w1++=nbFaces;
8210             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8211             for(int j=0;j<nbFaces;j++)
8212               {
8213                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8214                 *w1++=(int)std::distance(w6,w5);
8215                 w1=std::copy(w6,w5,w1);
8216                 w6=w5+1;
8217               }
8218           }
8219       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8220     }
8221   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8222   ofs << "      </Cells>\n";
8223   ofs << "    </Piece>\n";
8224   ofs << "  </" << getVTKDataSetType() << ">\n";
8225 }
8226
8227 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8228 {
8229   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8230   if(_mesh_dim==-2)
8231     { stream << " Not set !"; return ; }
8232   stream << " Mesh dimension : " << _mesh_dim << ".";
8233   if(_mesh_dim==-1)
8234     return ;
8235   if(!_coords)
8236     { stream << " No coordinates set !"; return ; }
8237   if(!_coords->isAllocated())
8238     { stream << " Coordinates set but not allocated !"; return ; }
8239   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8240   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8241   if(!_nodal_connec_index)
8242     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8243   if(!_nodal_connec_index->isAllocated())
8244     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8245   int lgth=_nodal_connec_index->getNumberOfTuples();
8246   int cpt=_nodal_connec_index->getNumberOfComponents();
8247   if(cpt!=1 || lgth<1)
8248     return ;
8249   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8250 }
8251
8252 std::string MEDCouplingUMesh::getVTKDataSetType() const
8253 {
8254   return std::string("UnstructuredGrid");
8255 }
8256
8257 /*!
8258  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8259  * returns a result mesh constituted by polygons.
8260  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8261  * all nodes from m2.
8262  * The meshes should be in 2D space. In
8263  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8264  * meshes.
8265  *  \param [in] m1 - the first input mesh which is a partitioned object.
8266  *  \param [in] m2 - the second input mesh which is a partition tool.
8267  *  \param [in] eps - precision used to detect coincident mesh entities.
8268  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8269  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8270  *         this array using decrRef() as it is no more needed.
8271  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8272  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8273  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8274  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8275  *         it is no more needed.  
8276  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8277  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8278  *         is no more needed.  
8279  *  \throw If the coordinates array is not set in any of the meshes.
8280  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8281  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8282  */
8283 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8284                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8285 {
8286   m1->checkFullyDefined();
8287   m2->checkFullyDefined();
8288   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8289     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8290
8291   // Step 1: compute all edge intersections (new nodes)
8292   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8293   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8294   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8295   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8296   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8297   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8298   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8299                                       m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8300                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8301   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8303   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8304
8305   // Step 2: re-order newly created nodes according to the ordering found in m2
8306   std::vector< std::vector<int> > intersectEdge2;
8307   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8308   subDiv2.clear(); dd5=0; dd6=0;
8309
8310   // Step 3:
8311   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8312   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8313   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8314                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8315
8316   // Step 4: Prepare final result:
8317   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8318   addCooDa->alloc((int)(addCoo.size())/2,2);
8319   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8320   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8321   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8322   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8323   std::vector<const DataArrayDouble *> coordss(4);
8324   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8325   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8326   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8331   ret->setConnectivity(conn,connI,true);
8332   ret->setCoords(coo);
8333   cellNb1=c1.retn(); cellNb2=c2.retn();
8334   return ret.retn();
8335 }
8336
8337
8338 /**
8339  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8340  * (newly created) nodes corresponding to the edge intersections.
8341  * Output params:
8342  * @param[out] cr, crI connectivity of the resulting mesh
8343  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8344  * TODO: describe input parameters
8345  */
8346 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8347                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8348                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8349                                                          const std::vector<double>& addCoords,
8350                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8351 {
8352   static const int SPACEDIM=2;
8353   const double *coo1=m1->getCoords()->getConstPointer();
8354   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8355   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8356   int offset1=m1->getNumberOfNodes();
8357   const double *coo2=m2->getCoords()->getConstPointer();
8358   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8359   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8360   int offset2=offset1+m2->getNumberOfNodes();
8361   int offset3=offset2+((int)addCoords.size())/2;
8362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8363   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8364   // Here a BBTree on 2D-cells, not on segments:
8365   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8366   int ncell1=m1->getNumberOfCells();
8367   crI.push_back(0);
8368   for(int i=0;i<ncell1;i++)
8369     {
8370       std::vector<int> candidates2;
8371       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8372       std::map<INTERP_KERNEL::Node *,int> mapp;
8373       std::map<int,INTERP_KERNEL::Node *> mappRev;
8374       INTERP_KERNEL::QuadraticPolygon pol1;
8375       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8376       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8377       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8378       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8379       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8380                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8381       //
8382       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
8383       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8384       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8385       for(it1.first();!it1.finished();it1.next())
8386         edges1.insert(it1.current()->getPtr());
8387       //
8388       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8389       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8390       int ii=0;
8391       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8392         {
8393           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8394           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8395           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8396           // pol2 is the new QP in the final merged result.
8397           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8398                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8399         }
8400       ii=0;
8401       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8402         {
8403           pol1.initLocationsWithOther(pol2s[ii]);
8404           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8405           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8406           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8407         }
8408       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8409       // by m2 but that we still want to keep in the final result.
8410       if(!edges1.empty())
8411         {
8412           try
8413             {
8414               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8415             }
8416           catch(INTERP_KERNEL::Exception& e)
8417             {
8418               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();
8419               throw INTERP_KERNEL::Exception(oss.str().c_str());
8420             }
8421         }
8422       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8423         (*it).second->decrRef();
8424     }
8425 }
8426
8427 /*!
8428  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8429  * It builds the descending connectivity of the two meshes, and then using a binary tree
8430  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8431  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8432  */
8433 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8434                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8435                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8436                                                    std::vector<double>& addCoo,
8437                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
8438                                                    throw(INTERP_KERNEL::Exception)
8439 {
8440   static const int SPACEDIM=2;
8441   // Build desc connectivity
8442   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8443   desc2=DataArrayInt::New();
8444   descIndx2=DataArrayInt::New();
8445   revDesc2=DataArrayInt::New();
8446   revDescIndx2=DataArrayInt::New();
8447   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8448   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8449   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8450   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8451   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8452   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8453   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8454
8455   // Build BB tree of all edges in the tool mesh (second mesh)
8456   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8457   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8458   int nDescCell1=m1Desc->getNumberOfCells();
8459   int nDescCell2=m2Desc->getNumberOfCells();
8460   intersectEdge1.resize(nDescCell1);
8461   colinear2.resize(nDescCell2);
8462   subDiv2.resize(nDescCell2);
8463   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8464
8465   std::vector<int> candidates1(1);
8466   int offset1=m1->getNumberOfNodes();
8467   int offset2=offset1+m2->getNumberOfNodes();
8468   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
8469     {
8470       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
8471       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8472       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
8473         {
8474           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8475           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
8476           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8477           candidates1[0]=i;
8478           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8479           // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
8480           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
8481           std::set<INTERP_KERNEL::Node *> nodes;
8482           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8483           std::size_t szz(nodes.size());
8484           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8485           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8486           for(std::size_t iii=0;iii<szz;iii++,itt++)
8487             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8488           // end of protection
8489           // Performs egde cutting:
8490           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8491           delete pol2;
8492           delete pol1;
8493         }
8494       else
8495         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8496     }
8497   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8498   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8499 }
8500
8501 /*!
8502  * This method performs the 2nd step of Partition of 2D mesh.
8503  * This method has 4 inputs :
8504  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8505  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8506  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
8507  * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
8508  * Nodes end up lying consecutively on a cutted edge.
8509  * \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.
8510  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
8511  * \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.
8512  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
8513  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
8514  */
8515 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8516       const std::vector<double>& addCoo,
8517       const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
8518 {
8519   int offset1=m1->getNumberOfNodes();
8520   int ncell=m2->getNumberOfCells();
8521   const int *c=m2->getNodalConnectivity()->getConstPointer();
8522   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8523   const double *coo=m2->getCoords()->getConstPointer();
8524   const double *cooBis=m1->getCoords()->getConstPointer();
8525   int offset2=offset1+m2->getNumberOfNodes();
8526   intersectEdge.resize(ncell);
8527   for(int i=0;i<ncell;i++,cI++)
8528     {
8529       const std::vector<int>& divs=subDiv[i];
8530       int nnode=cI[1]-cI[0]-1;
8531       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8532       std::map<INTERP_KERNEL::Node *, int> mapp22;
8533       for(int j=0;j<nnode;j++)
8534         {
8535           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8536           int nnid=c[(*cI)+j+1];
8537           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8538           mapp22[nn]=nnid+offset1;
8539         }
8540       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8541       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8542         ((*it).second.first)->decrRef();
8543       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8544       std::map<INTERP_KERNEL::Node *,int> mapp3;
8545       for(std::size_t j=0;j<divs.size();j++)
8546         {
8547           int id=divs[j];
8548           INTERP_KERNEL::Node *tmp=0;
8549           if(id<offset1)
8550             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8551           else if(id<offset2)
8552             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8553           else
8554             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8555           addNodes[j]=tmp;
8556           mapp3[tmp]=id;
8557         }
8558       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8559       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8560         (*it)->decrRef();
8561       e->decrRef();
8562     }
8563 }
8564
8565 /*!
8566  * 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).
8567  * 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
8568  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8569  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8570  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8571  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8572  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8573  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8574  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8575  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8576  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8577  * \param [out] cut3DSuf input/output param.
8578  */
8579 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8580                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8581                                                    const int *desc, const int *descIndx, 
8582                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8583 {
8584   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8585   int nbOf3DSurfCell=(int)cut3DSurf.size();
8586   for(int i=0;i<nbOf3DSurfCell;i++)
8587     {
8588       std::vector<int> res;
8589       int offset=descIndx[i];
8590       int nbOfSeg=descIndx[i+1]-offset;
8591       for(int j=0;j<nbOfSeg;j++)
8592         {
8593           int edgeId=desc[offset+j];
8594           int status=cut3DCurve[edgeId];
8595           if(status!=-2)
8596             {
8597               if(status>-1)
8598                 res.push_back(status);
8599               else
8600                 {
8601                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8602                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8603                 }
8604             }
8605         }
8606       switch(res.size())
8607         {
8608         case 2:
8609           {
8610             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8611             break;
8612           }
8613         case 1:
8614         case 0:
8615           {
8616             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8617             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8618             if(res.size()==2)
8619               {
8620                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8621               }
8622             else
8623               {
8624                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8625               }
8626             break;
8627           }
8628         default:
8629           {// case when plane is on a multi colinear edge of a polyhedron
8630             if((int)res.size()==2*nbOfSeg)
8631               {
8632                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8633               }
8634             else
8635               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8636           }
8637         }
8638     }
8639 }
8640
8641 /*!
8642  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8643  * 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).
8644  * 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
8645  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8646  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8647  * \param desc is the descending connectivity 3D->3DSurf
8648  * \param descIndx is the descending connectivity index 3D->3DSurf
8649  */
8650 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8651                                                   const int *desc, const int *descIndx,
8652                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8653 {
8654   checkFullyDefined();
8655   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8657   const int *nodal3D=_nodal_connec->getConstPointer();
8658   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8659   int nbOfCells=getNumberOfCells();
8660   for(int i=0;i<nbOfCells;i++)
8661     {
8662       std::map<int, std::set<int> > m;
8663       int offset=descIndx[i];
8664       int nbOfFaces=descIndx[i+1]-offset;
8665       int start=-1;
8666       int end=-1;
8667       for(int j=0;j<nbOfFaces;j++)
8668         {
8669           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8670           if(p.first!=-1 && p.second!=-1)
8671             {
8672               if(p.first!=-2)
8673                 {
8674                   start=p.first; end=p.second;
8675                   m[p.first].insert(p.second);
8676                   m[p.second].insert(p.first);
8677                 }
8678               else
8679                 {
8680                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8681                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8682                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8683                   INTERP_KERNEL::NormalizedCellType cmsId;
8684                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8685                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8686                   for(unsigned k=0;k<nbOfNodesSon;k++)
8687                     {
8688                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8689                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8690                     }
8691                 }
8692             }
8693         }
8694       if(m.empty())
8695         continue;
8696       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8697       int prev=end;
8698       while(end!=start)
8699         {
8700           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8701           const std::set<int>& s=(*it).second;
8702           std::set<int> s2; s2.insert(prev);
8703           std::set<int> s3;
8704           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8705           if(s3.size()==1)
8706             {
8707               int val=*s3.begin();
8708               conn.push_back(start);
8709               prev=start;
8710               start=val;
8711             }
8712           else
8713             start=end;
8714         }
8715       conn.push_back(end);
8716       if(conn.size()>3)
8717         {
8718           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8719           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8720           cellIds->pushBackSilent(i);
8721         }
8722     }
8723 }
8724
8725 /*!
8726  * 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
8727  * 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
8728  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8729  * 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
8730  * 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.
8731  * 
8732  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8733  */
8734 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
8735 {
8736   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8737   if(sz>=4)
8738     {
8739       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8740       if(cm.getDimension()==2)
8741         {
8742           const int *node=nodalConnBg+1;
8743           int startNode=*node++;
8744           double refX=coords[2*startNode];
8745           for(;node!=nodalConnEnd;node++)
8746             {
8747               if(coords[2*(*node)]<refX)
8748                 {
8749                   startNode=*node;
8750                   refX=coords[2*startNode];
8751                 }
8752             }
8753           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8754           refX=1e300;
8755           double tmp1;
8756           double tmp2[2];
8757           double angle0=-M_PI/2;
8758           //
8759           int nextNode=-1;
8760           int prevNode=-1;
8761           double resRef;
8762           double angleNext=0.;
8763           while(nextNode!=startNode)
8764             {
8765               nextNode=-1;
8766               resRef=1e300;
8767               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8768                 {
8769                   if(*node!=tmpOut.back() && *node!=prevNode)
8770                     {
8771                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8772                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8773                       double res;
8774                       if(angleM<=angle0)
8775                         res=angle0-angleM;
8776                       else
8777                         res=angle0-angleM+2.*M_PI;
8778                       if(res<resRef)
8779                         {
8780                           nextNode=*node;
8781                           resRef=res;
8782                           angleNext=angleM;
8783                         }
8784                     }
8785                 }
8786               if(nextNode!=startNode)
8787                 {
8788                   angle0=angleNext-M_PI;
8789                   if(angle0<-M_PI)
8790                     angle0+=2*M_PI;
8791                   prevNode=tmpOut.back();
8792                   tmpOut.push_back(nextNode);
8793                 }
8794             }
8795           std::vector<int> tmp3(2*(sz-1));
8796           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8797           std::copy(nodalConnBg+1,nodalConnEnd,it);
8798           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8799             {
8800               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8801               return false;
8802             }
8803           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8804             {
8805               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8806               return false;
8807             }
8808           else
8809             {
8810               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8811               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8812               return true;
8813             }
8814         }
8815       else
8816         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8817     }
8818   else
8819     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8820 }
8821
8822 /*!
8823  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8824  * 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.
8825  * 
8826  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8827  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8828  * \param [in,out] arr array in which the remove operation will be done.
8829  * \param [in,out] arrIndx array in the remove operation will modify
8830  * \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])
8831  * \return true if \b arr and \b arrIndx have been modified, false if not.
8832  */
8833 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
8834 {
8835   if(!arrIndx || !arr)
8836     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8837   if(offsetForRemoval<0)
8838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8839   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8840   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8841   int *arrIPtr=arrIndx->getPointer();
8842   *arrIPtr++=0;
8843   int previousArrI=0;
8844   const int *arrPtr=arr->getConstPointer();
8845   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8846   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8847     {
8848       if(*arrIPtr-previousArrI>offsetForRemoval)
8849         {
8850           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8851             {
8852               if(s.find(*work)==s.end())
8853                 arrOut.push_back(*work);
8854             }
8855         }
8856       previousArrI=*arrIPtr;
8857       *arrIPtr=(int)arrOut.size();
8858     }
8859   if(arr->getNumberOfTuples()==(int)arrOut.size())
8860     return false;
8861   arr->alloc((int)arrOut.size(),1);
8862   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8863   return true;
8864 }
8865
8866 /*!
8867  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8868  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8869  * The selection of extraction is done standardly in new2old format.
8870  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8871  *
8872  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8873  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8874  * \param [in] arrIn arr origin array from which the extraction will be done.
8875  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8876  * \param [out] arrOut the resulting array
8877  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8878  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8879  */
8880 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8881                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8882 {
8883   if(!arrIn || !arrIndxIn)
8884     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8885   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8886   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8888   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8889   const int *arrInPtr=arrIn->getConstPointer();
8890   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8891   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8892   if(nbOfGrps<0)
8893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8894   int maxSizeOfArr=arrIn->getNumberOfTuples();
8895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8896   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8897   arrIo->alloc((int)(sz+1),1);
8898   const int *idsIt=idsOfSelectBg;
8899   int *work=arrIo->getPointer();
8900   *work++=0;
8901   int lgth=0;
8902   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8903     {
8904       if(*idsIt>=0 && *idsIt<nbOfGrps)
8905         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8906       else
8907         {
8908           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8909           throw INTERP_KERNEL::Exception(oss.str().c_str());
8910         }
8911       if(lgth>=work[-1])
8912         *work=lgth;
8913       else
8914         {
8915           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8916           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8917           throw INTERP_KERNEL::Exception(oss.str().c_str());
8918         }
8919     }
8920   arro->alloc(lgth,1);
8921   work=arro->getPointer();
8922   idsIt=idsOfSelectBg;
8923   for(std::size_t i=0;i<sz;i++,idsIt++)
8924     {
8925       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8926         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8927       else
8928         {
8929           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8930           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8931           throw INTERP_KERNEL::Exception(oss.str().c_str());
8932         }
8933     }
8934   arrOut=arro.retn();
8935   arrIndexOut=arrIo.retn();
8936 }
8937
8938 /*!
8939  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8940  * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
8941  * The selection of extraction is done standardly in new2old format.
8942  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8943  *
8944  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8945  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8946  * \param [in] arrIn arr origin array from which the extraction will be done.
8947  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8948  * \param [out] arrOut the resulting array
8949  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8950  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8951  */
8952 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8953                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8954 {
8955   if(!arrIn || !arrIndxIn)
8956     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8957   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8958   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8959     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8960   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8961   const int *arrInPtr=arrIn->getConstPointer();
8962   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8963   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8964   if(nbOfGrps<0)
8965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8966   int maxSizeOfArr=arrIn->getNumberOfTuples();
8967   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8969   arrIo->alloc((int)(sz+1),1);
8970   int idsIt=idsOfSelectStart;
8971   int *work=arrIo->getPointer();
8972   *work++=0;
8973   int lgth=0;
8974   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8975     {
8976       if(idsIt>=0 && idsIt<nbOfGrps)
8977         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8978       else
8979         {
8980           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8981           throw INTERP_KERNEL::Exception(oss.str().c_str());
8982         }
8983       if(lgth>=work[-1])
8984         *work=lgth;
8985       else
8986         {
8987           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8988           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8989           throw INTERP_KERNEL::Exception(oss.str().c_str());
8990         }
8991     }
8992   arro->alloc(lgth,1);
8993   work=arro->getPointer();
8994   idsIt=idsOfSelectStart;
8995   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8996     {
8997       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8998         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8999       else
9000         {
9001           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9002           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9003           throw INTERP_KERNEL::Exception(oss.str().c_str());
9004         }
9005     }
9006   arrOut=arro.retn();
9007   arrIndexOut=arrIo.retn();
9008 }
9009
9010 /*!
9011  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9012  * 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
9013  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9014  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9015  *
9016  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9017  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9018  * \param [in] arrIn arr origin array from which the extraction will be done.
9019  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9020  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9021  * \param [in] srcArrIndex index array of \b srcArr
9022  * \param [out] arrOut the resulting array
9023  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9024  * 
9025  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9026  */
9027 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9028                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9029                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9030 {
9031   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9032     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9035   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9036   std::vector<bool> v(nbOfTuples,true);
9037   int offset=0;
9038   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9039   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9040   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9041     {
9042       if(*it>=0 && *it<nbOfTuples)
9043         {
9044           v[*it]=false;
9045           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9046         }
9047       else
9048         {
9049           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9050           throw INTERP_KERNEL::Exception(oss.str().c_str());
9051         }
9052     }
9053   srcArrIndexPtr=srcArrIndex->getConstPointer();
9054   arrIo->alloc(nbOfTuples+1,1);
9055   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9056   const int *arrInPtr=arrIn->getConstPointer();
9057   const int *srcArrPtr=srcArr->getConstPointer();
9058   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9059   int *arroPtr=arro->getPointer();
9060   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9061     {
9062       if(v[ii])
9063         {
9064           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9065           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9066         }
9067       else
9068         {
9069           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9070           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9071           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9072         }
9073     }
9074   arrOut=arro.retn();
9075   arrIndexOut=arrIo.retn();
9076 }
9077
9078 /*!
9079  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9080  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9081  *
9082  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9083  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9084  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9085  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9086  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9087  * \param [in] srcArrIndex index array of \b srcArr
9088  * 
9089  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9090  */
9091 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9092                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9093 {
9094   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9095     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9096   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9097   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9098   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9099   int *arrInOutPtr=arrInOut->getPointer();
9100   const int *srcArrPtr=srcArr->getConstPointer();
9101   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9102     {
9103       if(*it>=0 && *it<nbOfTuples)
9104         {
9105           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9106             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9107           else
9108             {
9109               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] !";
9110               throw INTERP_KERNEL::Exception(oss.str().c_str());
9111             }
9112         }
9113       else
9114         {
9115           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9116           throw INTERP_KERNEL::Exception(oss.str().c_str());
9117         }
9118     }
9119 }
9120
9121 /*!
9122  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9123  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9124  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
9125  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9126  * A negative value in \b arrIn means that it is ignored.
9127  * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
9128  * 
9129  * \param [in] arrIn arr origin array from which the extraction will be done.
9130  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9131  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9132  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9133  */
9134 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9135 {
9136   int seed=0,nbOfDepthPeelingPerformed=0;
9137   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9138 }
9139
9140 /*!
9141  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9142  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9143  * 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]].
9144  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9145  * A negative value in \b arrIn means that it is ignored.
9146  * 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.
9147  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9148  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9149  * \param [in] arrIn arr origin array from which the extraction will be done.
9150  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9151  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9152  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9153  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9154  * \sa MEDCouplingUMesh::partitionBySpreadZone
9155  */
9156 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9157 {
9158   nbOfDepthPeelingPerformed=0;
9159   if(!arrIndxIn)
9160     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9161   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9162   if(nbOfTuples<=0)
9163     {
9164       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9165       return ret;
9166     }
9167   //
9168   std::vector<bool> fetched(nbOfTuples,false);
9169   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9170 }
9171
9172 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9173 {
9174   nbOfDepthPeelingPerformed=0;
9175   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9176     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9177   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9178   std::vector<bool> fetched2(nbOfTuples,false);
9179   int i=0;
9180   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9181     {
9182       if(*seedElt>=0 && *seedElt<nbOfTuples)
9183         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9184       else
9185         { 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()); }
9186     }
9187   const int *arrInPtr=arrIn->getConstPointer();
9188   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9189   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9190   std::vector<int> idsToFetch1(seedBg,seedEnd);
9191   std::vector<int> idsToFetch2;
9192   std::vector<int> *idsToFetch=&idsToFetch1;
9193   std::vector<int> *idsToFetchOther=&idsToFetch2;
9194   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9195     {
9196       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9197         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9198           if(!fetched[*it2])
9199             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9200       std::swap(idsToFetch,idsToFetchOther);
9201       idsToFetchOther->clear();
9202       nbOfDepthPeelingPerformed++;
9203     }
9204   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9205   i=0;
9206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9207   int *retPtr=ret->getPointer();
9208   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9209     if(*it)
9210       *retPtr++=i;
9211   return ret.retn();
9212 }
9213
9214 /*!
9215  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9216  * 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
9217  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9218  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9219  *
9220  * \param [in] start begin of set of ids of the input extraction (included)
9221  * \param [in] end end of set of ids of the input extraction (excluded)
9222  * \param [in] step step of the set of ids in range mode.
9223  * \param [in] arrIn arr origin array from which the extraction will be done.
9224  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9225  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9226  * \param [in] srcArrIndex index array of \b srcArr
9227  * \param [out] arrOut the resulting array
9228  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9229  * 
9230  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9231  */
9232 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9233                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9234                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9235 {
9236   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9237     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9240   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9241   int offset=0;
9242   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9243   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9244   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9245   int it=start;
9246   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9247     {
9248       if(it>=0 && it<nbOfTuples)
9249         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9250       else
9251         {
9252           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9253           throw INTERP_KERNEL::Exception(oss.str().c_str());
9254         }
9255     }
9256   srcArrIndexPtr=srcArrIndex->getConstPointer();
9257   arrIo->alloc(nbOfTuples+1,1);
9258   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9259   const int *arrInPtr=arrIn->getConstPointer();
9260   const int *srcArrPtr=srcArr->getConstPointer();
9261   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9262   int *arroPtr=arro->getPointer();
9263   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9264     {
9265       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9266       if(pos<0)
9267         {
9268           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9269           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9270         }
9271       else
9272         {
9273           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9274           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9275         }
9276     }
9277   arrOut=arro.retn();
9278   arrIndexOut=arrIo.retn();
9279 }
9280
9281 /*!
9282  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9283  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9284  *
9285  * \param [in] start begin of set of ids of the input extraction (included)
9286  * \param [in] end end of set of ids of the input extraction (excluded)
9287  * \param [in] step step of the set of ids in range mode.
9288  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9289  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9290  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9291  * \param [in] srcArrIndex index array of \b srcArr
9292  * 
9293  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9294  */
9295 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9296                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9297 {
9298   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9299     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9300   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9301   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9302   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9303   int *arrInOutPtr=arrInOut->getPointer();
9304   const int *srcArrPtr=srcArr->getConstPointer();
9305   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9306   int it=start;
9307   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9308     {
9309       if(it>=0 && it<nbOfTuples)
9310         {
9311           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9312             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9313           else
9314             {
9315               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9316               throw INTERP_KERNEL::Exception(oss.str().c_str());
9317             }
9318         }
9319       else
9320         {
9321           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9322           throw INTERP_KERNEL::Exception(oss.str().c_str());
9323         }
9324     }
9325 }
9326
9327 /*!
9328  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9329  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9330  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9331  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9332  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9333  * 
9334  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9335  */
9336 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9337 {
9338   checkFullyDefined();
9339   int mdim=getMeshDimension();
9340   int spaceDim=getSpaceDimension();
9341   if(mdim!=spaceDim)
9342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9343   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9344   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9345   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9346   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9347   ret->setCoords(getCoords());
9348   ret->allocateCells((int)partition.size());
9349   //
9350   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9351     {
9352       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9353       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9354       switch(mdim)
9355         {
9356         case 2:
9357           cell=tmp->buildUnionOf2DMesh();
9358           break;
9359         case 3:
9360           cell=tmp->buildUnionOf3DMesh();
9361           break;
9362         default:
9363           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9364         }
9365       
9366       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9367     }
9368   //
9369   ret->finishInsertingCells();
9370   return ret.retn();
9371 }
9372
9373 /*!
9374  * This method partitions \b this into contiguous zone.
9375  * This method only needs a well defined connectivity. Coordinates are not considered here.
9376  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9377  */
9378 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9379 {
9380   int nbOfCellsCur=getNumberOfCells();
9381   std::vector<DataArrayInt *> ret;
9382   if(nbOfCellsCur<=0)
9383     return ret;
9384   DataArrayInt *neigh=0,*neighI=0;
9385   computeNeighborsOfCells(neigh,neighI);
9386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9387   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9388   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9389   int seed=0;
9390   while(seed<nbOfCellsCur)
9391     {
9392       int nbOfPeelPerformed=0;
9393       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9394       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9395     }
9396   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9397     ret.push_back((*it).retn());
9398   return ret;
9399 }
9400
9401 /*!
9402  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9403  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9404  *
9405  * \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.
9406  * \return a newly allocated DataArrayInt to be managed by the caller.
9407  * \throw In case of \a code has not the right format (typically of size 3*n)
9408  */
9409 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9410 {
9411   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9412   std::size_t nb=code.size()/3;
9413   if(code.size()%3!=0)
9414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9415   ret->alloc((int)nb,2);
9416   int *retPtr=ret->getPointer();
9417   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9418     {
9419       retPtr[0]=code[3*i+2];
9420       retPtr[1]=code[3*i+2]+code[3*i+1];
9421     }
9422   return ret.retn();
9423 }
9424
9425 /*!
9426  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9427  * All cells in \a this are expected to be linear 3D cells.
9428  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9429  * It leads to an increase to number of cells.
9430  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9431  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9432  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9433  *
9434  * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
9435  *                      For all other cells, the splitting policy will be ignored.
9436  * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added. 
9437  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9438  *          an id of old cell producing it. The caller is to delete this array using
9439  *         decrRef() as it is no more needed.
9440  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9441  *
9442  * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
9443  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9444  * 
9445  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9446  * \throw If \a this is not fully constituted with linear 3D cells.
9447  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9448  */
9449 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9450 {
9451   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9452   checkConnectivityFullyDefined();
9453   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9454     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9455   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9456   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9458   int *retPt(ret->getPointer());
9459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9460   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9461   const int *oldc(_nodal_connec->begin());
9462   const int *oldci(_nodal_connec_index->begin());
9463   const double *coords(_coords->begin());
9464   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9465     {
9466       std::vector<int> a; std::vector<double> b;
9467       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9468       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9469       const int *aa(&a[0]);
9470       if(!b.empty())
9471         {
9472           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9473             if(*it<0)
9474               *it=(-(*(it))-1+nbNodes);
9475           addPts->insertAtTheEnd(b.begin(),b.end());
9476           nbNodes+=(int)b.size()/3;
9477         }
9478       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9479         newConn->insertAtTheEnd(aa,aa+4);
9480     }
9481   if(!addPts->empty())
9482     {
9483       addPts->rearrange(3);
9484       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9485       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9486       ret0->setCoords(addPts);
9487     }
9488   else
9489     {
9490       nbOfAdditionalPoints=0;
9491       ret0->setCoords(getCoords());
9492     }
9493   ret0->setNodalConnectivity(newConn);
9494   //
9495   ret->computeOffsets2();
9496   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9497   return ret0.retn();
9498 }
9499
9500 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9501                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9502 {
9503   if(mesh)
9504     {
9505       mesh->incrRef();
9506       _nb_cell=mesh->getNumberOfCells();
9507     }
9508 }
9509
9510 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9511 {
9512   if(_mesh)
9513     _mesh->decrRef();
9514   if(_own_cell)
9515     delete _cell;
9516 }
9517
9518 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9519                                                                                                                                _own_cell(false),_cell_id(bg-1),
9520                                                                                                                                _nb_cell(end)
9521 {
9522   if(mesh)
9523     mesh->incrRef();
9524 }
9525
9526 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9527 {
9528   _cell_id++;
9529   if(_cell_id<_nb_cell)
9530     {
9531       _cell->next();
9532       return _cell;
9533     }
9534   else
9535     return 0;
9536 }
9537
9538 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9539 {
9540   if(_mesh)
9541     _mesh->incrRef();
9542 }
9543
9544 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9545 {
9546   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9547 }
9548
9549 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9550 {
9551   if(_mesh)
9552     _mesh->decrRef();
9553 }
9554
9555 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9556                                                                                                                                                                   _itc(itc),
9557                                                                                                                                                                   _bg(bg),_end(end)
9558 {
9559   if(_mesh)
9560     _mesh->incrRef();
9561 }
9562
9563 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9564 {
9565   if(_mesh)
9566     _mesh->decrRef();
9567 }
9568
9569 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9570 {
9571   return _type;
9572 }
9573
9574 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9575 {
9576   return _end-_bg;
9577 }
9578
9579 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9580 {
9581   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9582 }
9583
9584 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9585 {
9586   if(mesh)
9587     {
9588       mesh->incrRef();
9589       _nb_cell=mesh->getNumberOfCells();
9590     }
9591 }
9592
9593 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9594 {
9595   if(_mesh)
9596     _mesh->decrRef();
9597   delete _cell;
9598 }
9599
9600 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9601 {
9602   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9603   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9604   if(_cell_id<_nb_cell)
9605     {
9606       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9607       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9608       int startId=_cell_id;
9609       _cell_id+=nbOfElems;
9610       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9611     }
9612   else
9613     return 0;
9614 }
9615
9616 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9617 {
9618   if(mesh)
9619     {
9620       _conn=mesh->getNodalConnectivity()->getPointer();
9621       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9622     }
9623 }
9624
9625 void MEDCouplingUMeshCell::next()
9626 {
9627   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9628     {
9629       _conn+=_conn_lgth;
9630       _conn_indx++;
9631     }
9632   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9633 }
9634
9635 std::string MEDCouplingUMeshCell::repr() const
9636 {
9637   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9638     {
9639       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9640       oss << " : ";
9641       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9642       return oss.str();
9643     }
9644   else
9645     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9646 }
9647
9648 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9649 {
9650   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9651     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9652   else
9653     return INTERP_KERNEL::NORM_ERROR;
9654 }
9655
9656 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9657 {
9658   lgth=_conn_lgth;
9659   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9660     return _conn;
9661   else
9662     return 0;
9663 }